diff --git a/Cargo.lock b/Cargo.lock index b398d06c347df..97492c8dd2736 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -198,9 +198,9 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "askama" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf825125edd887a019d0a3a837dcc5499a68b0d034cc3eb594070c3e18addc" +checksum = "6024d73179f43f15ccd2b881bfea6fee7f3a46ec53f33b52210dea749ebebaa4" dependencies = [ "askama_macros", "itoa", @@ -211,9 +211,9 @@ dependencies = [ [[package]] name = "askama_derive" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1c7065972a130eafa84215f21352ae15b4a7393da48c1f5e103904490736738" +checksum = "071ee5ebf2138e3ad180e0aacf6940c2cab5e6d8333741d9925c7bee2b153f39" dependencies = [ "askama_parser", "basic-toml", @@ -224,23 +224,23 @@ dependencies = [ "rustc-hash 2.1.1", "serde", "serde_derive", - "syn 2.0.117", + "syn 3.0.3", ] [[package]] name = "askama_macros" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e23b1d2c4bd39a41971f6124cef4cc6fd0540913ecb90919b69ab3bbe44ae1a" +checksum = "643e1c7cbb6aec1d920332fe51a7c0d8219e273dcb8602db03f5263e4d16487b" dependencies = [ "askama_derive", ] [[package]] name = "askama_parser" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7db09fde9143e7ac4513358fb32ee32847125b63b18ea715afd487956da715da" +checksum = "2c5ae75772275d268b03ab8bdccdd12117b6169ee23256942b34e46c9f476583" dependencies = [ "rustc-hash 2.1.1", "serde", @@ -4909,6 +4909,7 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_hir", + "rustc_index", "rustc_infer", "rustc_lint_defs", "rustc_macros", diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 426fc4e7be228..bc8753f4dcaa7 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -29,7 +29,6 @@ use rustc_data_structures::stable_hash::{StableHash, StableHashCtxt, StableHashe use rustc_data_structures::tagged_ptr::Tag; use rustc_macros::{Decodable, Encodable, StableHash, Walkable}; pub use rustc_span::AttrId; -use rustc_span::def_id::LocalDefId; use rustc_span::{ ByteSymbol, DUMMY_SP, ErrorGuaranteed, Ident, LocalExpnId, Span, Spanned, Symbol, kw, respan, sym, @@ -4081,6 +4080,8 @@ pub struct TestBinderBody { pub foralls: ThinVec, pub exists: ThinVec, pub constraints: Vec, + /// These are not where clauses, but rather predicates within the body to be proven + pub predicates: Vec, } #[derive(Clone, Encodable, Decodable, Debug, Walkable)] @@ -4114,11 +4115,24 @@ pub enum TestBinderConstraint { #[visitable(extra = LifetimeCtxt::Bound)] rhs: Lifetime, }, - Type { + PlaceholderOutlives { lhs: Box, #[visitable(extra = LifetimeCtxt::Bound)] rhs: Lifetime, }, + AliasOutlives { + bound_type_constraint: TestBinderBoundTypeConstraint, + }, +} + +#[derive(Clone, Encodable, Decodable, Debug, Walkable)] +pub struct TestBinderBoundTypeConstraint { + pub span: Span, + pub node_id: NodeId, + pub params: ThinVec, + pub lhs: Box, + #[visitable(extra = LifetimeCtxt::Bound)] + pub rhs: Lifetime, } // Adding a new variant? Please update `test_item` in `tests/ui/macros/stringify.rs`. @@ -4445,24 +4459,6 @@ impl TryFrom for ForeignItemKind { } pub type ForeignItem = Item; - -/// Fragment of the AST according to "HIR owner" semantics. -/// -/// This is used to map each `LocalDefId` to its content's AST. -#[derive(Debug)] -pub enum AstOwner { - /// This definition does not correspond to a HIR owner. - NonOwner, - /// This definition corresponds to a nested `use` tree. - /// The `LocalDefId` points to its HIR owner. - NestedUseTree(LocalDefId), - Crate(Box), - Item(Box), - TraitItem(Box), - ImplItem(Box), - ForeignItem(Box), -} - // Some nodes are used a lot. Make sure they don't unintentionally get bigger. #[cfg(target_pointer_width = "64")] mod size_asserts { diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index adc211ce6a790..14ef1c147f253 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -600,6 +600,7 @@ macro_rules! common_visitor_and_walkers { fn visit_qself(QSelf); fn visit_test_binder_body(TestBinderBody); fn visit_test_binder_constraint(TestBinderConstraint); + fn visit_test_binder_bound_type_constraint(TestBinderBoundTypeConstraint); fn visit_test_binder_constraints(TestBinderConstraints); fn visit_test_binder_exists(TestBinderExists); fn visit_test_binder_forall(TestBinderForall); @@ -1145,6 +1146,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_qself(QSelf); pub fn walk_test_binder_body(TestBinderBody); pub fn walk_test_binder_constraint(TestBinderConstraint); + pub fn walk_test_binder_bound_type_constraint(TestBinderBoundTypeConstraint); pub fn walk_test_binder_exists(TestBinderExists); pub fn walk_test_binder_forall(TestBinderForall); pub fn walk_trait_ref(TraitRef); diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index b302a8f45e557..95fcde08b60bc 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -432,13 +432,27 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { intravisit::walk_precise_capturing_arg(self, arg); } - fn visit_test_binder_forall(&mut self, forall: &'hir TestBinderForall<'hir>) -> Self::Result { + fn visit_test_binder_forall(&mut self, forall: &'hir TestBinderForall<'hir>) { self.insert(forall.span, forall.hir_id, Node::TestBinderForall(forall)); self.with_parent(forall.hir_id, |this| intravisit::walk_test_binder_forall(this, forall)) } - fn visit_test_binder_exists(&mut self, exists: &'hir TestBinderExists<'hir>) -> Self::Result { + fn visit_test_binder_exists(&mut self, exists: &'hir TestBinderExists<'hir>) { self.insert(exists.span, exists.hir_id, Node::TestBinderExists(exists)); self.with_parent(exists.hir_id, |this| intravisit::walk_test_binder_exists(this, exists)) } + + fn visit_test_binder_bound_type_constraint( + &mut self, + bound_type: &'hir TestBinderBoundTypeConstraint<'hir>, + ) { + self.insert( + bound_type.span, + bound_type.hir_id, + Node::TestBinderBoundTypeConstraint(bound_type), + ); + self.with_parent(bound_type.hir_id, |this| { + intravisit::walk_test_binder_bound_type_constraint(this, bound_type) + }) + } } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index fc3fa99fa0644..b5e28d21a2613 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -8,9 +8,10 @@ use rustc_hir::{ self as hir, CRATE_OWNER_ID, HirId, ImplItemImplKind, LifetimeSource, PredicateOrigin, Target, find_attr, }; +use rustc_middle::middle::resolve::ResolverAstLowering; use rustc_middle::span_bug; +use rustc_middle::ty::TyCtxt; use rustc_middle::ty::data_structures::IndexMap; -use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::{DUMMY_SP, DesugaringKind, Ident, Span, Symbol, kw, sym}; @@ -2111,7 +2112,14 @@ impl<'hir> LoweringContext<'_, 'hir> { body.exists.iter().map(|exists| self.lower_test_binder_exists(exists)), ); let constraints = self.lower_test_binder_constraints_as_and(&body.constraints); - hir::TestBinderBody { foralls, exists, constraints } + let mut dedup_map = Default::default(); + let predicates = self.arena.alloc_from_iter( + body.predicates + .iter() + .flat_map(|w| &w.predicates) + .map(|predicate| self.lower_where_predicate(predicate, &[], &mut dedup_map)), + ); + hir::TestBinderBody { foralls, exists, constraints, predicates } } fn lower_test_binder_forall( @@ -2193,12 +2201,45 @@ impl<'hir> LoweringContext<'_, 'hir> { let rhs = self.lower_lifetime(rhs, LifetimeSource::OutlivesBound, rhs.ident.into()); hir::TestBinderConstraint::Lifetime { lhs, rhs } } - TestBinderConstraint::Type { lhs, rhs } => { + TestBinderConstraint::PlaceholderOutlives { lhs, rhs } => { let lhs = self .lower_ty_alloc(lhs, ImplTraitContext::Disallowed(ImplTraitPosition::Bound)); let rhs = self.lower_lifetime(rhs, LifetimeSource::OutlivesBound, rhs.ident.into()); - hir::TestBinderConstraint::Type { lhs, rhs } + hir::TestBinderConstraint::PlaceholderOutlives { lhs, rhs } + } + TestBinderConstraint::AliasOutlives { bound_type_constraint } => { + hir::TestBinderConstraint::AliasOutlives { + bound_type_constraint: self + .arena + .alloc(self.lower_test_binder_bound_type_constraint(bound_type_constraint)), + } } } } + + fn lower_test_binder_bound_type_constraint( + &mut self, + bound_type: &TestBinderBoundTypeConstraint, + ) -> hir::TestBinderBoundTypeConstraint<'hir> { + let TestBinderBoundTypeConstraint { span, node_id, params, lhs, rhs } = bound_type; + + let (generics, (lhs, rhs)) = self.lower_generics( + &Generics { params: params.clone(), where_clause: Default::default(), span: *span }, + ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + |this| { + let lhs = this + .lower_ty_alloc(lhs, ImplTraitContext::Disallowed(ImplTraitPosition::Bound)); + let rhs = this.lower_lifetime(rhs, LifetimeSource::OutlivesBound, rhs.ident.into()); + (lhs, rhs) + }, + ); + + hir::TestBinderBoundTypeConstraint { + span: *span, + hir_id: self.lower_node_id(*node_id), + params: generics.params, + lhs, + rhs, + } + } } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 5b76606d101bc..93a7c6cc4d305 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -55,7 +55,7 @@ use rustc_data_structures::unord::ExtendUnord; use rustc_errors::codes::*; use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, ErrorGuaranteed}; use rustc_hir::attrs::lang_items::LangItem; -use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; +use rustc_hir::def::{DefKind, Namespace, PerNS, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap}; use rustc_hir::definitions::PerParentDisambiguatorState; use rustc_hir::lints::DelayedLint; @@ -65,9 +65,12 @@ use rustc_hir::{ }; use rustc_index::{Idx, IndexVec}; use rustc_macros::extension; +use rustc_middle::middle::resolve::{ + AstOwner, LifetimeRes, PartialRes, PerOwnerResolverData, ResolverAstLowering, +}; use rustc_middle::queries::Providers; use rustc_middle::span_bug; -use rustc_middle::ty::{PerOwnerResolverData, ResolverAstLowering, TyCtxt}; +use rustc_middle::ty::TyCtxt; use rustc_session::diagnostics::add_feature_diagnostics; use rustc_span::symbol::{Ident, Symbol, kw, sym}; use rustc_span::{DUMMY_SP, DesugaringKind, Span}; @@ -2672,19 +2675,41 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> hir::ConstItemRhs<'hir> { match (body, kind) { (body, ConstItemKind::Body) => { - hir::ConstItemRhs::Body(self.lower_const_body(span, body.as_deref())) - } - (Some(body), ConstItemKind::TypeConst) => { - hir::ConstItemRhs::TypeConst(self.arena.alloc( - match self.can_lower_expr_to_const_arg_direct( - &body, - DirectConstArgContext::MacrolessMinGenericConstArgs, - ) { - Ok(()) => self.lower_expr_to_const_arg_direct(&body, None), - Err(err) => err.emit(self), - }, - )) + let is_direct = |body| { + if self.tcx.features().macroless_generic_const_args() { + self.can_lower_expr_to_const_arg_direct( + body, + DirectConstArgContext::MacrolessMinGenericConstArgs, + ) + .is_ok() + } else { + // do not check can_lower_expr_to_const_arg_direct, but rather just + // ExprKind::DirectConstArg, because we don't want e.g. + // `impl { const C: u8 = N; }` to be a direct-rhs const + matches!(body, Expr { kind: ExprKind::DirectConstArg(_), .. }) + } + }; + // N.B.: the feature gate for this is generic_const_args, not min_generic_const_args + if self.tcx.features().generic_const_args() + && let Some(body) = body + && is_direct(body) + { + hir::ConstItemRhs::Direct( + self.arena.alloc(self.lower_expr_to_const_arg_direct(&body, None)), + ) + } else { + hir::ConstItemRhs::Body(self.lower_const_body(span, body.as_deref())) + } } + (Some(body), ConstItemKind::TypeConst) => hir::ConstItemRhs::Direct(self.arena.alloc( + match self.can_lower_expr_to_const_arg_direct( + &body, + DirectConstArgContext::MacrolessMinGenericConstArgs, + ) { + Ok(()) => self.lower_expr_to_const_arg_direct(&body, None), + Err(err) => err.emit(self), + }, + )), (None, ConstItemKind::TypeConst) => { let const_arg = ConstArg { hir_id: self.next_id(), @@ -2693,7 +2718,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ), span: DUMMY_SP, }; - hir::ConstItemRhs::TypeConst(self.arena.alloc(const_arg)) + hir::ConstItemRhs::Direct(self.arena.alloc(const_arg)) } } } diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 261fcd18d96ba..387aa7566b42a 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -2,9 +2,10 @@ use std::sync::Arc; use rustc_ast::{self as ast, *}; use rustc_errors::StashKey; -use rustc_hir::def::{DefKind, PartialRes, PerNS, Res}; +use rustc_hir::def::{DefKind, PerNS, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, GenericArg}; +use rustc_middle::middle::resolve::PartialRes; use rustc_middle::{span_bug, ty}; use rustc_session::diagnostics::add_feature_diagnostics; use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Ident, Span, Symbol, sym}; diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 15d94530eecae..003865e147aa2 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -395,6 +395,14 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { self.check_late_bound_lifetime_defs(&exists.params); visit::walk_test_binder_exists(self, exists) } + + fn visit_test_binder_bound_type_constraint( + &mut self, + bound_type: &'a ast::TestBinderBoundTypeConstraint, + ) -> Self::Result { + self.check_late_bound_lifetime_defs(&bound_type.params); + visit::walk_test_binder_bound_type_constraint(self, bound_type) + } } // ----------------------------------------------------------------------------- diff --git a/compiler/rustc_attr_ir/src/stability.rs b/compiler/rustc_attr_ir/src/stability.rs index 1cba0b59c0f6c..8d0551e92472d 100644 --- a/compiler/rustc_attr_ir/src/stability.rs +++ b/compiler/rustc_attr_ir/src/stability.rs @@ -139,8 +139,9 @@ pub enum StabilityLevel { /// Rust release which stabilized this feature. since: StableSince, /// This is `Some` if this item allowed to be referred to on stable via unstable modules; - /// the `Symbol` is the deprecation message printed in that case. - allowed_through_unstable_modules: Option, + /// the first `Symbol` is the deprecation message printed in that case, + /// the second `Symbol` is the correct module to use. + allowed_through_unstable_modules: Option<(Symbol, Symbol)>, }, } diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index 6dbbe0bf4d0c8..29e288d858c37 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -10,6 +10,7 @@ use rustc_feature::{ACCEPTED_LANG_FEATURES, AttributeStability}; use super::prelude::*; use super::util::parse_version; +use crate::context::ExpectNameValue; use crate::diagnostics; const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ @@ -49,7 +50,7 @@ const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ #[derive(Default)] pub(crate) struct StabilityParser { - allowed_through_unstable_modules: Option, + allowed_through_unstable_modules: Option<(Symbol, Symbol)>, stability: Option<(Stability, Span)>, } @@ -93,16 +94,51 @@ impl AttributeParser for StabilityParser { ), ( &[sym::rustc_allowed_through_unstable_modules], - template!(NameValueStr: "deprecation message"), + template!(List: &[r#"message = "...", module = "..."#]), unstable!(staged_api), |this, cx, args| { - let Some(nv) = cx.expect_name_value(args, cx.attr_span, None) else { - return; - }; - let Some(value_str) = cx.expect_string_literal(nv) else { - return; - }; - this.allowed_through_unstable_modules = Some(value_str); + let Some(list) = cx.expect_list(args, cx.attr_span) else { return }; + let mut message = None; + let mut module = None; + + for item in list.mixed() { + let Some((name, value)) = item.expect_name_value(cx, item.span(), None) else { + return; + }; + let Some(value) = cx.expect_string_literal(value) else { + return; + }; + + match name.name { + sym::message => { + if message.is_some() { + cx.adcx().duplicate_key(name.span, name.name); + } else { + message = Some(value) + } + } + sym::module => { + if module.is_some() { + cx.adcx().duplicate_key(name.span, name.name); + } else { + module = Some(value) + } + } + _ => { + cx.adcx().expected_specific_argument( + name.span, + &[sym::message, sym::module], + ); + } + } + } + + let allowed_through_unstable_modules = try { (message?, module?) }; + if allowed_through_unstable_modules.is_none() { + cx.emit_err(diagnostics::RustcAtumMissingParams { span: cx.attr_span }); + } + + this.allowed_through_unstable_modules = allowed_through_unstable_modules; }, ), ]; diff --git a/compiler/rustc_attr_parsing/src/diagnostics.rs b/compiler/rustc_attr_parsing/src/diagnostics.rs index a37d56419adac..663915e39dccd 100644 --- a/compiler/rustc_attr_parsing/src/diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/diagnostics.rs @@ -1136,6 +1136,15 @@ pub(crate) struct RustcAllowedUnstablePairing { pub span: Span, } +#[derive(Diagnostic)] +#[diag( + "`rustc_allowed_through_unstable_modules` attribute must have `message` and `module` params" +)] +pub(crate) struct RustcAtumMissingParams { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag("suggestions on deprecated items are unstable")] pub(crate) struct DeprecatedItemSuggestion { diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index a8338c9e3c41f..8c9c444bd1793 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -14,7 +14,7 @@ use rustc_infer::traits::query::{ }; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{ - self, RePlaceholder, Region, RegionExt, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex, + self, RePlaceholder, Region, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex, }; use rustc_span::Span; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index c22698003f7ee..97931fc76f152 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -26,7 +26,7 @@ use rustc_middle::mir::{ }; use rustc_middle::ty::print::PrintTraitRefExt as _; use rustc_middle::ty::{ - self, PredicateKind, RegionExt, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor, Upcast, + self, PredicateKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor, Upcast, suggest_constraining_type_params, }; use rustc_mir_dataflow::move_paths::{Init, InitKind, InitLocation, MoveOutIndex, MovePathIndex}; diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index b43694596d17c..a972b37cd42d2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -15,8 +15,7 @@ use rustc_middle::bug; use rustc_middle::hir::place::PlaceBase; use rustc_middle::mir::{AnnotationSource, ConstraintCategory, ReturnConstraint}; use rustc_middle::ty::{ - self, GenericArgs, Region, RegionExt, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitor, - fold_regions, + self, GenericArgs, Region, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitor, fold_regions, }; use rustc_span::{Ident, Span, kw}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 5a1358b9a311e..1a328f62fc73e 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -12,7 +12,7 @@ use rustc_index::IndexSlice; use rustc_middle::mir::pretty::PrettyPrintMirOptions; use rustc_middle::mir::{Body, MirDumper, PassWhere, Promoted}; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{self, RegionExt, TyCtxt}; +use rustc_middle::ty::{self, TyCtxt}; use rustc_mir_dataflow::move_paths::MoveData; use rustc_mir_dataflow::points::DenseLocationMap; use rustc_session::config::MirIncludeSpans; diff --git a/compiler/rustc_borrowck/src/polonius/dump.rs b/compiler/rustc_borrowck/src/polonius/dump.rs index 2b3d8b4fdac22..5285f724b02ec 100644 --- a/compiler/rustc_borrowck/src/polonius/dump.rs +++ b/compiler/rustc_borrowck/src/polonius/dump.rs @@ -4,7 +4,7 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_index::IndexVec; use rustc_middle::mir::pretty::{MirDumper, PassWhere, PrettyPrintMirOptions}; use rustc_middle::mir::{Body, Location}; -use rustc_middle::ty::{RegionExt, RegionVid, TyCtxt}; +use rustc_middle::ty::{RegionVid, TyCtxt}; use rustc_mir_dataflow::points::PointIndex; use rustc_session::config::MirIncludeSpans; diff --git a/compiler/rustc_borrowck/src/region_infer/graphviz.rs b/compiler/rustc_borrowck/src/region_infer/graphviz.rs index 6583bc24e2015..ceb33d82deba8 100644 --- a/compiler/rustc_borrowck/src/region_infer/graphviz.rs +++ b/compiler/rustc_borrowck/src/region_infer/graphviz.rs @@ -7,7 +7,7 @@ use std::io::{self, Write}; use itertools::Itertools; use rustc_graphviz as dot; -use rustc_middle::ty::{RegionExt, UniverseIndex}; +use rustc_middle::ty::UniverseIndex; use super::*; diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index d3fc7152acc44..534cd1327bbe5 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -17,9 +17,7 @@ use rustc_middle::mir::{ TerminatorKind, }; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; -use rustc_middle::ty::{ - self, RegionExt, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex, fold_regions, -}; +use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex, fold_regions}; use rustc_mir_dataflow::points::DenseLocationMap; use rustc_span::hygiene::DesugaringKind; use rustc_span::{DUMMY_SP, Span}; diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs index e347dc2d13dfc..a154078b7ad86 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs @@ -11,7 +11,7 @@ use rustc_macros::extension; use rustc_middle::mir::{Body, ConstraintCategory}; use rustc_middle::ty::{ self, DefiningScopeKind, DefinitionSiteHiddenType, FallibleTypeFolder, Flags, GenericArg, - GenericArgsRef, OpaqueTypeKey, ProvisionalHiddenType, Region, RegionExt, RegionVid, Ty, TyCtxt, + GenericArgsRef, OpaqueTypeKey, ProvisionalHiddenType, Region, RegionVid, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitableExt, Unnormalized, fold_regions, }; use rustc_mir_dataflow::points::DenseLocationMap; diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index f845d9137f759..e20f9a646a953 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -6,8 +6,7 @@ use rustc_infer::infer::outlives::env::RegionBoundPairs; use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate}; use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound}; use rustc_middle::ty::{ - self, GenericArgKind, RegionExt, TyCtxt, TypeFoldable, TypeVisitableExt, elaborate, - fold_regions, + self, GenericArgKind, TyCtxt, TypeFoldable, TypeVisitableExt, elaborate, fold_regions, }; use rustc_span::Span; use tracing::{debug, instrument}; diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index fbde85ef6aec4..f16c811031b08 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -27,7 +27,7 @@ use rustc_middle::mir::RETURN_PLACE; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{ self, BoundVariableKind, GenericArgs, GenericArgsRef, InlineConstArgs, InlineConstArgsParts, - List, RegionExt, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, fold_regions, + List, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, fold_regions, }; use rustc_middle::{bug, span_bug}; use rustc_span::{ErrorGuaranteed, kw, sym}; diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index 88049d67964b1..d42438ba92f59 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -1850,6 +1850,17 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn fptosi_sat(&mut self, val: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { self.fptoint_sat(true, val, dest_ty) } + + fn ptrauth_resign( + &mut self, + _value: Self::Value, + _old_key: u32, + _old_discriminator: u64, + _new_key: u32, + _new_discriminator: u64, + ) -> Self::Value { + bug!("Resigning of pointers not implemented"); + } } impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs index 6bd186f1121fc..712a1c14ef8e6 100644 --- a/compiler/rustc_codegen_gcc/src/common.rs +++ b/compiler/rustc_codegen_gcc/src/common.rs @@ -323,7 +323,7 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> { cv: Scalar, layout: abi::Scalar, ty: Type<'gcc>, - _schema: Option<&PointerAuthSchema>, + _ptrauth_schema: Option, ) -> RValue<'gcc> { let bitsize = if layout.is_bool() { 1 } else { layout.size(self).bits() }; match cv { diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index 19fbe37c27b9e..8c1fc18ee7a78 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -405,7 +405,7 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { fn get_fn_addr( &self, instance: Instance<'tcx>, - _pointer_auth_schema: Option<&PointerAuthSchema>, + _ptrauth_schema: Option, ) -> RValue<'gcc> { let func_name = self.tcx.symbol_name(instance).name; diff --git a/compiler/rustc_codegen_gcc/src/int.rs b/compiler/rustc_codegen_gcc/src/int.rs index dfae4eceebe44..fe0654c665c76 100644 --- a/compiler/rustc_codegen_gcc/src/int.rs +++ b/compiler/rustc_codegen_gcc/src/int.rs @@ -375,6 +375,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { fixed_count: 3, conv: CanonAbi::C, can_unwind: false, + ptrauth_discriminator: None, }; fn_abi.adjust_for_foreign_abi(self.cx, ExternAbi::C { unwind: false }); diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index dae8b2d17e0e1..bd75e9635618b 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -1553,6 +1553,30 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let cold_inline = llvm::AttributeKind::Cold.create_attr(self.llcx); attributes::apply_to_callsite(llret, llvm::AttributePlace::Function, &[cold_inline]); } + + fn ptrauth_resign( + &mut self, + value: &'ll Value, + old_key: u32, + old_discriminator: u64, + new_key: u32, + new_discriminator: u64, + ) -> &'ll Value { + let ptr_as_int = self.ptrtoint(value, self.type_i64()); + let resigned_int = self.call_intrinsic( + "llvm.ptrauth.resign", + &[], + &[ + ptr_as_int, + self.const_i32(old_key as i32), + self.const_i64(old_discriminator as i64), + self.const_i32(new_key as i32), + self.const_i64(new_discriminator as i64), + ], + ); + + self.inttoptr(resigned_int, self.val_ty(value)) + } } impl<'ll> StaticBuilderMethods for Builder<'_, 'll, '_> { @@ -2185,8 +2209,13 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { // bundles. // Once this is resolved, we should analyze each call and skip direct calls. See the // discussion in the rust-lang issue: - let key: u32 = 0; - let discriminator: u64 = 0; + + let key: u32 = self.sess().pointer_authentication_fn_ptr_key().unwrap() as u32; + // If sess().pointer_authentication_fn_ptr_type_discrimination() is enabled, this contains + // the function pointer type discriminator; otherwise, it is None. LLVM expects a u64 here, + // so use 0 when no discriminator is present. + let discriminator = fn_abi?.ptrauth_discriminator.unwrap_or(0); + Some(llvm::OperandBundleBox::new( "ptrauth", &[self.const_u32(key), self.const_u64(discriminator)], diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index 3fe4550b6759e..8f63e409028ce 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -30,11 +30,9 @@ pub(crate) fn maybe_sign_fn_ptr<'ll, 'tcx>( cx: &CodegenCx<'ll, '_>, instance: Instance<'tcx>, llfn: &'ll llvm::Value, - schema: &PointerAuthSchema, + ptrauth_schema: PointerAuthSchema, ) -> &'ll llvm::Value { - if cx.tcx.sess.pointer_authentication_functions().is_none() { - return llfn; - } + assert!(cx.tcx.sess.pointer_authentication_functions().is_some()); // Only free functions or methods let def_id = instance.def_id(); @@ -54,7 +52,7 @@ pub(crate) fn maybe_sign_fn_ptr<'ll, 'tcx>( return llfn; } - let addr_diversity = match schema.is_address_discriminated { + let addr_diversity = match ptrauth_schema.is_address_discriminated { PointerAuthAddressDiscriminator::HardwareAddress(true) => Some(llfn), PointerAuthAddressDiscriminator::HardwareAddress(false) => None, PointerAuthAddressDiscriminator::Synthetic(val) => { @@ -63,7 +61,12 @@ pub(crate) fn maybe_sign_fn_ptr<'ll, 'tcx>( Some(unsafe { llvm::LLVMConstIntToPtr(llval, llty) }) } }; - const_ptr_auth(llfn, schema.key as u32, schema.constant_discriminator as u64, addr_diversity) + const_ptr_auth( + llfn, + ptrauth_schema.key as u32, + ptrauth_schema.constant_discriminator as u64, + addr_diversity, + ) } /* @@ -179,11 +182,11 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { &self, global_alloc: GlobalAlloc<'tcx>, need_symbol_name: bool, - schema: Option<&PointerAuthSchema>, + ptrauth_schema: Option, ) -> Result<&'ll Value, u64> { let alloc = match global_alloc { GlobalAlloc::Function { instance, .. } => { - return Ok(self.get_fn_addr(instance, schema)); + return Ok(self.get_fn_addr(instance, ptrauth_schema)); } GlobalAlloc::Static(def_id) => { assert!(self.tcx.is_static(def_id)); @@ -405,7 +408,7 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> { cv: Scalar, layout: abi::Scalar, llty: &'ll Type, - schema: Option<&PointerAuthSchema>, + ptrauth_schema: Option, ) -> &'ll Value { let bitsize = if layout.is_bool() { 1 } else { layout.size(self).bits() }; match cv { @@ -422,7 +425,7 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> { let (prov, offset) = ptr.prov_and_relative_offset(); let global_alloc = self.tcx.global_alloc(prov.alloc_id()); let base_addr_space = global_alloc.address_space(self); - let base_addr = match self.alloc_to_backend(global_alloc, false, schema) { + let base_addr = match self.alloc_to_backend(global_alloc, false, ptrauth_schema) { Ok(base_addr) => base_addr, Err(base_addr) => { let val = base_addr.wrapping_add(offset.bytes()); diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index c737fad66e573..26c6f6d0e396a 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -970,7 +970,7 @@ impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn get_fn_addr( &self, instance: Instance<'tcx>, - pointer_auth_schema: Option<&PointerAuthSchema>, + ptrauth_schema: Option, ) -> &'ll Value { // When pointer authentication metadata is provided, `get_fn_addr` will // attempt to sign the pointer using LLVM's `ConstPtrAuth` constant @@ -985,7 +985,7 @@ impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { // , and comment in // builder's `ptrauth_operand_bundle`. let llfn = get_fn(self, instance); - match pointer_auth_schema { + match ptrauth_schema { Some(schema) => common::maybe_sign_fn_ptr(self, instance, llfn, schema), None => llfn, } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 25003e071beb7..8c6998407e89e 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -4129,7 +4129,7 @@ fn add_lld_args( // `lld` as the linker. // // Note that wasm targets skip this step since the only option there anyway - // is to use LLD but the `wasm32-wasip2` target relies on a wrapper around + // is to use LLD but component-producing targets rely on a wrapper around // this, `wasm-component-ld`, which is overridden if this option is passed. if !sess.target.is_like_wasm { cmd.cc_arg("-fuse-ld=lld"); diff --git a/compiler/rustc_codegen_ssa/src/mir/retag.rs b/compiler/rustc_codegen_ssa/src/mir/retag.rs index 397fb423e8da3..a71a57f02c82a 100644 --- a/compiler/rustc_codegen_ssa/src/mir/retag.rs +++ b/compiler/rustc_codegen_ssa/src/mir/retag.rs @@ -73,7 +73,7 @@ impl<'a, 'tcx, V> RetagPlan { // the outermost `Box` is what determines the permission that gets created. ty::Adt(adt, _) if adt.is_box() => Self::visit_box(bx, layout, is_fn_entry), // Skip traversing for everything inside of `MaybeDangling` - ty::Adt(adt, _) if adt.is_maybe_dangling() => None, + _ if layout.ty.is_like_maybe_dangling() => None, _ => Self::walk_value(bx, layout, is_fn_entry), } } diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index cb0209a0ae369..0e37705ec82b5 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -667,4 +667,13 @@ pub trait BuilderMethods<'a, 'tcx>: fn zext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; fn apply_attrs_to_cleanup_callsite(&mut self, llret: Self::Value); + + fn ptrauth_resign( + &mut self, + value: Self::Value, + old_key: u32, + old_discriminator: u64, + new_key: u32, + new_discriminator: u64, + ) -> Self::Value; } diff --git a/compiler/rustc_codegen_ssa/src/traits/consts.rs b/compiler/rustc_codegen_ssa/src/traits/consts.rs index b4eba38d39c19..b45b5667be6c9 100644 --- a/compiler/rustc_codegen_ssa/src/traits/consts.rs +++ b/compiler/rustc_codegen_ssa/src/traits/consts.rs @@ -47,7 +47,7 @@ pub trait ConstCodegenMethods: BackendTypes { cv: Scalar, layout: abi::Scalar, llty: Self::Type, - schema: Option<&PointerAuthSchema>, + ptrauth_schema: Option, ) -> Self::Value; fn const_ptr_byte_offset(&self, val: Self::Value, offset: abi::Size) -> Self::Value; diff --git a/compiler/rustc_codegen_ssa/src/traits/misc.rs b/compiler/rustc_codegen_ssa/src/traits/misc.rs index add7128a2974b..3d1a931a12e83 100644 --- a/compiler/rustc_codegen_ssa/src/traits/misc.rs +++ b/compiler/rustc_codegen_ssa/src/traits/misc.rs @@ -22,7 +22,7 @@ pub trait MiscCodegenMethods<'tcx>: BackendTypes { fn get_fn_addr( &self, instance: Instance<'tcx>, - pointer_auth_schema: Option<&PointerAuthSchema>, + ptrauth_schema: Option, ) -> Self::Value; fn eh_personality(&self) -> Self::Function; fn sess(&self) -> &Session; diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 912be902b46f7..c823da68b65bd 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -440,8 +440,15 @@ fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>( typing_env: ty::TypingEnv<'tcx>, ) -> Result { let def = cid.instance.def.def_id(); - // `type const` don't have bodys - debug_assert!(!tcx.is_type_const(def), "CTFE tried to evaluate type-const: {:?}", def); + // directly represented consts don't have bodies + if cfg!(debug_assertions) + && matches!(tcx.def_kind(def), DefKind::Const { .. } | DefKind::AssocConst { .. }) + { + debug_assert!( + tcx.const_of_item(def).is_none(), + "CTFE tried to evaluate directly represented const item: {def:?}" + ); + } let is_static = tcx.is_static(def); let mut ecx = InterpCx::new( diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 2cd4caf5ba250..f388bb80b13ce 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -7,7 +7,6 @@ use std::borrow::Cow; use std::fmt::{self, Write}; use std::hash::Hash; -use std::mem; use std::num::NonZero; use either::{Left, Right}; @@ -1528,15 +1527,10 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, BackendRepr::Memory { .. } => unreachable!() } } - ty::Adt(adt, _) if adt.is_maybe_dangling() => { - let old_may_dangle = mem::replace(&mut self.may_dangle, true); - - let inner = self.ecx.project_field(val, FieldIdx::ZERO)?; - self.visit_value(&inner)?; - - self.may_dangle = old_may_dangle; - } _ => { + let old_may_dangle = self.may_dangle; + self.may_dangle |= val.layout.ty.is_like_maybe_dangling(); + // default handler try_validation!( self.walk_value(val), @@ -1546,6 +1540,8 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, Ub(InvalidVTableTrait { vtable_dyn_type, expected_dyn_type }) => InvalidMetaWrongTrait { expected_dyn_type, vtable_dyn_type }, ); + + self.may_dangle = old_may_dangle; } } diff --git a/compiler/rustc_error_codes/src/error_codes/E0789.md b/compiler/rustc_error_codes/src/error_codes/E0789.md index c7bc6cfde5134..6cf0c7243d854 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0789.md +++ b/compiler/rustc_error_codes/src/error_codes/E0789.md @@ -14,7 +14,10 @@ Erroneous code example: #![unstable(feature = "foo_module", reason = "...", issue = "123")] -#[rustc_allowed_through_unstable_modules = "deprecation message"] +#[rustc_allowed_through_unstable_modules( + message = "deprecation message", + module = "stable_module", +)] // #[stable(feature = "foo", since = "1.0")] struct Foo; // ^^^ error: `rustc_allowed_through_unstable_modules` attribute must be diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 010ecb1cd3d98..f1047e6c0bab4 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -4,12 +4,11 @@ use std::fmt::Debug; use rustc_ast as ast; use rustc_ast::NodeId; -use rustc_data_structures::fx::FxIndexMap; use rustc_error_messages::{DiagArgValue, IntoDiagArg}; use rustc_hir_id::HirId; use rustc_macros::{Decodable, Encodable, StableHash}; use rustc_span::Symbol; -use rustc_span::def_id::{DefId, LocalDefId}; +use rustc_span::def_id::DefId; use rustc_span::hygiene::MacroKind; use crate as hir; @@ -587,63 +586,6 @@ impl IntoDiagArg for Res { } } -/// The result of resolving a path before lowering to HIR, -/// with "module" segments resolved and associated item -/// segments deferred to type checking. -/// `base_res` is the resolution of the resolved part of the -/// path, `unresolved_segments` is the number of unresolved -/// segments. -/// -/// ```text -/// module::Type::AssocX::AssocY::MethodOrAssocType -/// ^~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/// base_res unresolved_segments = 3 -/// -/// ::AssocX::AssocY::MethodOrAssocType -/// ^~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~ -/// base_res unresolved_segments = 2 -/// ``` -#[derive(Copy, Clone, Debug)] -pub struct PartialRes { - base_res: Res, - unresolved_segments: usize, -} - -impl PartialRes { - #[inline] - pub fn new(base_res: Res) -> Self { - PartialRes { base_res, unresolved_segments: 0 } - } - - #[inline] - pub fn with_unresolved_segments(base_res: Res, mut unresolved_segments: usize) -> Self { - if base_res == Res::Err { - unresolved_segments = 0 - } - PartialRes { base_res, unresolved_segments } - } - - #[inline] - pub fn base_res(&self) -> Res { - self.base_res - } - - #[inline] - pub fn unresolved_segments(&self) -> usize { - self.unresolved_segments - } - - #[inline] - pub fn full_res(&self) -> Option> { - (self.unresolved_segments == 0).then_some(self.base_res) - } - - #[inline] - pub fn expect_full_res(&self) -> Res { - self.full_res().expect("unexpected unresolved segments") - } -} - /// Different kinds of symbols can coexist even if they share the same textual name. /// Therefore, they each have a separate universe (known as a "namespace"). #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)] @@ -933,43 +875,3 @@ impl Res { matches!(self, Res::Def(DefKind::Ctor(_, CtorKind::Const), _) | Res::SelfCtor(..)) } } - -/// Resolution for a lifetime appearing in a type. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub enum LifetimeRes { - /// Successfully linked the lifetime to a generic parameter. - Param { - /// Id of the generic parameter that introduced it. - param: LocalDefId, - /// Id of the introducing place. That can be: - /// - an item's id, for the item's generic parameters; - /// - a TraitRef's ref_id, identifying the `for<...>` binder; - /// - a FnPtr type's id. - /// - /// This information is used for impl-trait lifetime captures, to know when to or not to - /// capture any given lifetime. - binder: NodeId, - }, - /// Created a generic parameter for an anonymous lifetime. - Fresh { - /// Id of the generic parameter that introduced it. - /// - /// Creating the associated `LocalDefId` is the responsibility of lowering. - param: NodeId, - /// Kind of elided lifetime - kind: hir::MissingLifetimeKind, - }, - /// This variant is used for anonymous lifetimes that we did not resolve during - /// late resolution. Those lifetimes will be inferred by typechecking. - Infer, - /// `'static` lifetime. - Static, - /// Resolution failure. - Error(rustc_span::ErrorGuaranteed), - /// HACK: This is used to recover the NodeId of an elided lifetime. - ElidedAnchor { start: NodeId, end: NodeId }, -} - -// FxIndexMap is necessary because its data ends up in .rmeta files, -// so its iteration order must be consistent. See #159677 for context. -pub type DocLinkResMap = FxIndexMap<(Symbol, Namespace), Option>>; diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index fb4b61e9f4875..e23128c1a491f 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -416,21 +416,21 @@ impl<'hir> PathSegment<'hir> { #[derive(Clone, Copy, Debug, StableHash)] pub enum ConstItemRhs<'hir> { Body(BodyId), - TypeConst(&'hir ConstArg<'hir>), + Direct(&'hir ConstArg<'hir>), } impl<'hir> ConstItemRhs<'hir> { pub fn hir_id(&self) -> HirId { match self { ConstItemRhs::Body(body_id) => body_id.hir_id, - ConstItemRhs::TypeConst(ct_arg) => ct_arg.hir_id, + ConstItemRhs::Direct(ct_arg) => ct_arg.hir_id, } } pub fn span<'tcx>(&self, tcx: impl crate::intravisit::HirTyCtxt<'tcx>) -> Span { match self { ConstItemRhs::Body(body_id) => tcx.hir_body(*body_id).value.span, - ConstItemRhs::TypeConst(ct_arg) => ct_arg.span, + ConstItemRhs::Direct(ct_arg) => ct_arg.span, } } } @@ -4467,7 +4467,10 @@ impl FnHeader { pub struct TestBinderBody<'hir> { pub foralls: &'hir [TestBinderForall<'hir>], pub exists: &'hir [TestBinderExists<'hir>], + /// Constraints to be inserted directly into constraint storage to be proven pub constraints: TestBinderConstraint<'hir>, + /// Constraints declared using `where` syntax, used via `register_obligation` + pub predicates: &'hir [WherePredicate<'hir>], } #[derive(Debug, Clone, Copy, StableHash)] @@ -4492,7 +4495,17 @@ pub enum TestBinderConstraint<'hir> { And { items: &'hir [TestBinderConstraint<'hir>] }, Or { items: &'hir [TestBinderConstraint<'hir>] }, Lifetime { lhs: &'hir Lifetime, rhs: &'hir Lifetime }, - Type { lhs: &'hir Ty<'hir>, rhs: &'hir Lifetime }, + PlaceholderOutlives { lhs: &'hir Ty<'hir>, rhs: &'hir Lifetime }, + AliasOutlives { bound_type_constraint: &'hir TestBinderBoundTypeConstraint<'hir> }, +} + +#[derive(Debug, Clone, Copy, StableHash)] +pub struct TestBinderBoundTypeConstraint<'hir> { + pub span: Span, + pub hir_id: HirId, + pub params: &'hir [GenericParam<'hir>], + pub lhs: &'hir Ty<'hir>, + pub rhs: &'hir Lifetime, } #[derive(Debug, Clone, Copy, StableHash)] @@ -4910,6 +4923,7 @@ pub enum Node<'hir> { PreciseCapturingNonLifetimeArg(&'hir PreciseCapturingNonLifetimeArg), TestBinderForall(&'hir TestBinderForall<'hir>), TestBinderExists(&'hir TestBinderExists<'hir>), + TestBinderBoundTypeConstraint(&'hir TestBinderBoundTypeConstraint<'hir>), // Created by query feeding Synthetic, Err(Span), @@ -4967,6 +4981,7 @@ impl<'hir> Node<'hir> { | Node::WherePredicate(..) | Node::TestBinderForall(..) | Node::TestBinderExists(..) + | Node::TestBinderBoundTypeConstraint(..) | Node::Synthetic | Node::Err(..) => None, } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 811dccc4a0ad9..ee7b7f3efdf83 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -512,6 +512,12 @@ pub trait Visitor<'v>: Sized { ) -> Self::Result { walk_test_binder_constraint(self, constraint) } + fn visit_test_binder_bound_type_constraint( + &mut self, + bound_type: &'v TestBinderBoundTypeConstraint<'v>, + ) -> Self::Result { + walk_test_binder_bound_type_constraint(self, bound_type) + } } pub trait VisitorExt<'v>: Visitor<'v> { @@ -1082,7 +1088,7 @@ pub fn walk_const_item_rhs<'v, V: Visitor<'v>>( ) -> V::Result { match ct_rhs { ConstItemRhs::Body(body_id) => visitor.visit_nested_body(body_id), - ConstItemRhs::TypeConst(const_arg) => visitor.visit_const_arg_unambig(const_arg), + ConstItemRhs::Direct(const_arg) => visitor.visit_const_arg_unambig(const_arg), } } @@ -1581,9 +1587,11 @@ pub fn walk_test_binder_body<'v, V: Visitor<'v>>( visitor: &mut V, body: &'v TestBinderBody<'v>, ) -> V::Result { - walk_list!(visitor, visit_test_binder_forall, body.foralls); - walk_list!(visitor, visit_test_binder_exists, body.exists); - try_visit!(visitor.visit_test_binder_constraint(&body.constraints)); + let TestBinderBody { foralls, exists, constraints, predicates } = body; + walk_list!(visitor, visit_test_binder_forall, *foralls); + walk_list!(visitor, visit_test_binder_exists, *exists); + try_visit!(visitor.visit_test_binder_constraint(&constraints)); + walk_list!(visitor, visit_where_predicate, *predicates); V::Result::output() } @@ -1591,10 +1599,11 @@ pub fn walk_test_binder_forall<'v, V: Visitor<'v>>( visitor: &mut V, forall: &'v TestBinderForall<'v>, ) -> V::Result { - try_visit!(visitor.visit_id(forall.hir_id)); - try_visit!(visitor.visit_generics(forall.generics)); - try_visit!(visitor.visit_test_binder_body(forall.body)); - if let Some(assert_on_exit) = &forall.assert_on_exit { + let TestBinderForall { span: _, hir_id, generics, body, assert_on_exit } = forall; + try_visit!(visitor.visit_id(*hir_id)); + try_visit!(visitor.visit_generics(generics)); + try_visit!(visitor.visit_test_binder_body(body)); + if let Some(assert_on_exit) = &assert_on_exit { try_visit!(visitor.visit_test_binder_constraint(assert_on_exit)); } V::Result::output() @@ -1604,9 +1613,10 @@ pub fn walk_test_binder_exists<'v, V: Visitor<'v>>( visitor: &mut V, exists: &'v TestBinderExists<'v>, ) -> V::Result { - try_visit!(visitor.visit_id(exists.hir_id)); - walk_list!(visitor, visit_generic_param, exists.params); - try_visit!(visitor.visit_test_binder_body(exists.body)); + let TestBinderExists { span: _, hir_id, params, body } = exists; + try_visit!(visitor.visit_id(*hir_id)); + walk_list!(visitor, visit_generic_param, *params); + try_visit!(visitor.visit_test_binder_body(body)); V::Result::output() } @@ -1625,10 +1635,25 @@ pub fn walk_test_binder_constraint<'v, V: Visitor<'v>>( try_visit!(visitor.visit_lifetime(lhs)); try_visit!(visitor.visit_lifetime(rhs)); } - TestBinderConstraint::Type { lhs, rhs } => { + TestBinderConstraint::PlaceholderOutlives { lhs, rhs } => { try_visit!(visitor.visit_ty_unambig(lhs)); try_visit!(visitor.visit_lifetime(rhs)); } + TestBinderConstraint::AliasOutlives { bound_type_constraint } => { + try_visit!(visitor.visit_test_binder_bound_type_constraint(bound_type_constraint)); + } } V::Result::output() } + +pub fn walk_test_binder_bound_type_constraint<'v, V: Visitor<'v>>( + visitor: &mut V, + constraint: &'v TestBinderBoundTypeConstraint<'v>, +) -> V::Result { + let TestBinderBoundTypeConstraint { span: _, hir_id, params, lhs, rhs } = constraint; + try_visit!(visitor.visit_id(*hir_id)); + walk_list!(visitor, visit_generic_param, *params); + try_visit!(visitor.visit_ty_unambig(lhs)); + try_visit!(visitor.visit_lifetime(rhs)); + V::Result::output() +} diff --git a/compiler/rustc_hir_analysis/src/check/always_applicable.rs b/compiler/rustc_hir_analysis/src/check/always_applicable.rs index 60636a1164926..ca9874ac727a1 100644 --- a/compiler/rustc_hir_analysis/src/check/always_applicable.rs +++ b/compiler/rustc_hir_analysis/src/check/always_applicable.rs @@ -11,7 +11,7 @@ use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt}; use rustc_infer::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::span_bug; use rustc_middle::ty::util::CheckRegions; -use rustc_middle::ty::{self, GenericArgsRef, RegionExt, Ty, TyCtxt, TypeVisitableExt, TypingMode}; +use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt, TypingMode}; use rustc_span::sym; use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::traits::{self, ObligationCtxt}; diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 1895f586df2f0..d5bc834b831c7 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -953,10 +953,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), tcx.require_lang_item(LangItem::Sized, ty_span), ); check_where_clauses(wfcx, def_id); - - if tcx.is_type_const(def_id) { - wfcheck::check_type_const(wfcx, def_id, ty, true)?; - } + wfcheck::check_const_item(wfcx, def_id, ty); Ok(()) })); diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index e5d26cf72f9a5..d49c3b2869bd3 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -14,9 +14,9 @@ use rustc_infer::infer::{self, BoundRegionConversionTime, InferCtxt, TyCtxtInfer use rustc_infer::traits::{TraitErrors, util}; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{ - self, BottomUpFolder, GenericArgs, GenericParamDefKind, Generics, RegionExt, Ty, TyCtxt, - TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypeVisitor, - TypingMode, Unnormalized, Upcast, + self, BottomUpFolder, GenericArgs, GenericParamDefKind, Generics, Ty, TyCtxt, TypeFoldable, + TypeFolder, TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, + Unnormalized, Upcast, }; use rustc_middle::{bug, span_bug}; use rustc_span::{BytePos, DUMMY_SP, Span}; @@ -2157,12 +2157,10 @@ fn compare_type_const<'tcx>( impl_const_item: ty::AssocItem, trait_const_item: ty::AssocItem, ) -> Result<(), ErrorGuaranteed> { - let impl_is_type_const = tcx.is_type_const(impl_const_item.def_id); - let trait_type_const_span = tcx.type_const_span(trait_const_item.def_id); + let impl_is_type_const = tcx.is_type_const_syntax(impl_const_item.def_id); + let trait_is_type_const = tcx.is_type_const_syntax(trait_const_item.def_id); - if let Some(trait_type_const_span) = trait_type_const_span - && !impl_is_type_const - { + if trait_is_type_const && !impl_is_type_const { return Err(tcx .dcx() .struct_span_err( @@ -2170,10 +2168,7 @@ fn compare_type_const<'tcx>( "implementation of a `type const` must also be marked as `type const`", ) .with_span_note( - MultiSpan::from_spans(vec![ - tcx.def_span(trait_const_item.def_id), - trait_type_const_span, - ]), + tcx.def_span(trait_const_item.def_id), "trait declaration of const is marked as `type const`", ) .emit()); diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index eac3762ef9af8..9ce935c4389a5 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -89,7 +89,7 @@ use rustc_middle::query::Providers; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::print::with_types_for_signature; use rustc_middle::ty::{ - self, GenericArgs, GenericArgsRef, OutlivesClause, Region, RegionExt, Ty, TyCtxt, TypingMode, + self, GenericArgs, GenericArgsRef, OutlivesClause, Region, Ty, TyCtxt, TypingMode, }; use rustc_middle::{bug, span_bug}; use rustc_session::diagnostics::feature_err; diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 4b95f1e82cd9a..0dee9690737df 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -24,9 +24,9 @@ use rustc_middle::traits::solve::NoSolution; use rustc_middle::ty::region_constraint::{And, LeafRegionConstraint, Or}; use rustc_middle::ty::trait_def::TraitSpecializationKind; use rustc_middle::ty::{ - self, GenericArgKind, GenericArgs, GenericParamDefKind, RegionExt, Ty, TyCtxt, TypeFlags, - TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, - Unnormalized, Upcast, + self, GenericArgKind, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFlags, TypeFoldable, + TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Unnormalized, + Upcast, }; use rustc_middle::{bug, span_bug}; use rustc_session::diagnostics::feature_err; @@ -929,13 +929,9 @@ pub(crate) fn check_associated_item( let ty = tcx.type_of(def_id).instantiate_identity(); let ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(def_id)), ty); wfcx.register_wf_obligation(span, loc, ty.into()); + check_const_item(wfcx, def_id, ty); - let has_value = item.defaultness(tcx).has_value(); - if tcx.is_type_const(def_id) { - check_type_const(wfcx, def_id, ty, has_value)?; - } - - if has_value { + if item.defaultness(tcx).has_value() { let code = ObligationCauseCode::SizedConstOrStatic; wfcx.register_bound( ObligationCause::new(span, def_id, code), @@ -1264,17 +1260,17 @@ pub(crate) fn check_static_item<'tcx>( }) } +/// Runs checks common to both free consts and associated consts #[instrument(level = "debug", skip(wfcx))] -pub(super) fn check_type_const<'tcx>( +pub(super) fn check_const_item<'tcx>( wfcx: &WfCheckingCtxt<'_, 'tcx>, def_id: LocalDefId, item_ty: Ty<'tcx>, - has_value: bool, -) -> Result<(), ErrorGuaranteed> { +) { let tcx = wfcx.tcx(); let span = tcx.def_span(def_id); - if !tcx.features().const_param_ty_unchecked() { + if tcx.is_direct_const(def_id.into()) && !tcx.features().const_param_ty_unchecked() { wfcx.register_bound( ObligationCause::new(span, def_id, ObligationCauseCode::ConstParam(item_ty)), wfcx.param_env, @@ -1283,8 +1279,8 @@ pub(super) fn check_type_const<'tcx>( ); } - if has_value { - let raw_ct = tcx.const_of_item(def_id).instantiate_identity(); + if let Some(direct_rhs) = tcx.const_of_item(def_id) { + let raw_ct = direct_rhs.instantiate_identity(); let norm_ct = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(def_id)), raw_ct); wfcx.register_wf_obligation(span, Some(WellFormedLoc::Ty(def_id)), norm_ct.into()); @@ -1295,7 +1291,6 @@ pub(super) fn check_type_const<'tcx>( ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(norm_ct, item_ty)), )); } - Ok(()) } #[instrument(level = "debug", skip(tcx, impl_))] @@ -2333,17 +2328,33 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { #[instrument(level = "debug", skip(self))] pub(super) fn check_test_binder_body(&self, body: TestBinderBody<'tcx>) { - let constraints = match validate(self.tcx(), &body.constraints) { - Ok(()) => body.constraints, + let TestBinderBody { foralls, exists, constraints, predicates } = body; + if !predicates.is_empty() { + for (predicate, span) in predicates { + let cause = traits::ObligationCause::misc(span, self.body_def_id); + let obligation = Obligation::new(self.tcx(), cause, self.param_env, predicate); + self.register_obligation(obligation); + } + match self.ocx.evaluate_obligations_error_on_ambiguity() { + TraitErrors::NoErrors => (), + TraitErrors::HasErrors(errors) => { + self.infcx.err_ctxt().report_fulfillment_errors(errors); + return; + } + } + } + + let constraints = match validate(self.tcx(), &constraints) { + Ok(()) => constraints, Err(_guar) => ty::region_constraint::RegionConstraint::new_true(), }; self.infcx.register_solver_region_constraint(constraints); - for forall in body.foralls { + for forall in foralls { self.check_test_binder_forall(forall); } - for exists in body.exists { + for exists in exists { self.check_test_binder_exists(exists); } @@ -2431,8 +2442,8 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { if let Some(actual_span) = actual_span { err.span_note(actual_span, "constraint from here"); } - err.note(format!("expected: {expected:?}")); - err.note(format!("actual: {actual:?}")); + err.note(format!("expected: {expected:#?}")); + err.note(format!("actual: {actual:#?}")); err.emit(); } @@ -2446,7 +2457,25 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { let check_leaf_constraint = |expected: LeafRegionConstraint<_, _>, actual: LeafRegionConstraint<_, _>| { - if expected.clone().without_span() != actual.clone().without_span() { + if let LeafRegionConstraint::AliasTyOutlivesViaEnv(expected, expected_span) = + expected + && let LeafRegionConstraint::AliasTyOutlivesViaEnv(actual, actual_span) = actual + { + let expected_anon = self.tcx().anonymize_bound_vars(expected); + let actual_anon = self.tcx().anonymize_bound_vars(actual); + if expected_anon != actual_anon { + let mut err = self + .tcx() + .dcx() + .struct_span_err(expected_span, "forall expect clause failed"); + err.span_note(actual_span, "constraint from here"); + err.note(format!("expected: {expected:#?}")); + err.note(format!("actual: {actual:#?}")); + err.note(format!("expected_anon: {expected_anon:#?}")); + err.note(format!("actual_anon: {actual_anon:#?}")); + err.emit(); + } + } else if expected.clone().without_span() != actual.clone().without_span() { err(self.tcx(), expected.span(), expected, Some(actual.span()), actual); } }; @@ -2663,7 +2692,10 @@ struct RedundantLifetimeArgsLint<'tcx> { pub(crate) struct TestBinderBody<'tcx> { pub foralls: Vec>, pub exists: Vec>, + /// Constraints to be inserted directly into constraint storage to be proven pub constraints: SolverRegionConstraint<'tcx>, + /// Constraints declared using `where` syntax, used via `register_obligation` + pub predicates: Vec<(ty::Binder<'tcx, ty::ClauseKind<'tcx>>, Span)>, } #[derive(Clone, Debug, TypeFoldable, TypeVisitable)] diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 248e7aa583a19..2e4da8d948f07 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -34,8 +34,8 @@ use rustc_lint_defs::builtin::REPR_C_ENUMS_LARGER_THAN_INT; use rustc_middle::query::Providers; use rustc_middle::ty::util::{Discr, IntTypeExt}; use rustc_middle::ty::{ - self, AdtKind, Const, IsSuggestable, RegionExt, Ty, TyCtxt, TypeVisitableExt, TypingMode, - Unnormalized, fold_regions, + self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, TypingMode, Unnormalized, + fold_regions, }; use rustc_middle::{bug, span_bug}; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym}; @@ -327,12 +327,16 @@ impl<'tcx> ItemCtxt<'tcx> { &self, item: &hir::TestBinderBody<'tcx>, ) -> TestBinderBody<'tcx> { - let foralls = - item.foralls.iter().map(|forall| self.lower_test_binder_forall(forall)).collect(); - let exists = - item.exists.iter().map(|exists| self.lower_test_binder_exists(exists)).collect(); - let constraints = self.lower_test_binder_constraint(&item.constraints); - TestBinderBody { foralls, exists, constraints } + let hir::TestBinderBody { foralls, exists, constraints, predicates } = item; + let foralls = foralls.iter().map(|forall| self.lower_test_binder_forall(forall)).collect(); + let exists = exists.iter().map(|exists| self.lower_test_binder_exists(exists)).collect(); + let constraints = self.lower_test_binder_constraint(&constraints); + let mut clauses = Default::default(); + for predicate in *predicates { + clauses_of::where_predicate_clauses(self, predicate, &mut clauses); + } + let predicates = clauses.into_iter().map(|(c, span)| (c.kind(), span)).collect(); + TestBinderBody { foralls, exists, constraints, predicates } } #[instrument(level = "debug", skip(self), ret)] @@ -451,7 +455,7 @@ impl<'tcx> ItemCtxt<'tcx> { lhs, rhs, span, )) } - hir::TestBinderConstraint::Type { lhs, rhs } => { + hir::TestBinderConstraint::PlaceholderOutlives { lhs, rhs } => { let span = lhs.span.to(rhs.ident.span); let lhs = self.lower_ty(lhs); let rhs = self.lowerer().lower_lifetime(rhs, RegionInferReason::RegionPredicate); @@ -462,6 +466,21 @@ impl<'tcx> ItemCtxt<'tcx> { lhs, rhs, span, )) } + hir::TestBinderConstraint::AliasOutlives { + bound_type_constraint: + hir::TestBinderBoundTypeConstraint { span, hir_id, params: _, lhs, rhs }, + } => { + let bound_vars = self.tcx.late_bound_vars(*hir_id); + let &ty::Alias(_, lhs) = self.lower_ty(lhs).kind() else { + self.dcx().span_err(lhs.span, "bound type test binder constraint must be alias (it's a AliasTyOutlivesViaEnv)"); + return SolverRegionConstraint::new_true(); + }; + let rhs = self.lowerer().lower_lifetime(rhs, RegionInferReason::RegionPredicate); + SolverRegionConstraint::new_leaf(LeafRegionConstraint::AliasTyOutlivesViaEnv( + ty::Binder::bind_with_vars((lhs, rhs), bound_vars), + *span, + )) + } } } } @@ -1804,25 +1823,24 @@ fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKin fn const_of_item<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, -) -> ty::EarlyBinder<'tcx, Const<'tcx>> { +) -> Option>> { let ct_rhs = match tcx.hir_node_by_def_id(def_id) { - hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(.., ct), .. }) => *ct, - hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Const(_, ct), .. }) => { - ct.expect("no default value for trait assoc const") - } - hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(.., ct), .. }) => *ct, - _ => { - span_bug!(tcx.def_span(def_id), "`const_of_item` expected a const or assoc const item") + hir::Node::Item(&hir::Item { kind: hir::ItemKind::Const(.., ct), .. }) => ct, + hir::Node::TraitItem(&hir::TraitItem { + kind: hir::TraitItemKind::Const(_, ct), .. + }) => ct?, + hir::Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Const(.., ct), .. }) => ct, + node => { + span_bug!( + tcx.def_span(def_id), + "`const_of_item` expected a const or assoc const item, got {node:?}" + ) } }; let ct_arg = match ct_rhs { - hir::ConstItemRhs::TypeConst(ct_arg) => ct_arg, + hir::ConstItemRhs::Direct(ct_arg) => ct_arg, hir::ConstItemRhs::Body(_) => { - let e = tcx.dcx().span_delayed_bug( - tcx.def_span(def_id), - "cannot call const_of_item on a non-type_const", - ); - return ty::EarlyBinder::bind(tcx, Const::new_error(tcx, e)); + return None; } }; let icx = ItemCtxt::new(tcx, def_id); @@ -1834,8 +1852,8 @@ fn const_of_item<'tcx>( if let Err(e) = icx.check_tainted_by_errors() && !ct.references_error() { - ty::EarlyBinder::bind(tcx, Const::new_error(tcx, e)) + Some(ty::EarlyBinder::bind(tcx, Const::new_error(tcx, e))) } else { - ty::EarlyBinder::bind(tcx, ct) + Some(ty::EarlyBinder::bind(tcx, ct)) } } diff --git a/compiler/rustc_hir_analysis/src/collect/clauses_of.rs b/compiler/rustc_hir_analysis/src/collect/clauses_of.rs index 488b9a09e6106..dee835ee53cac 100644 --- a/compiler/rustc_hir_analysis/src/collect/clauses_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/clauses_of.rs @@ -7,8 +7,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::find_attr; use rustc_middle::ty::{ - self, GenericClauses, ImplTraitInTraitData, RegionExt, Ty, TyCtxt, TypeVisitable, TypeVisitor, - Upcast, + self, GenericClauses, ImplTraitInTraitData, Ty, TyCtxt, TypeVisitable, TypeVisitor, Upcast, }; use rustc_middle::{bug, span_bug}; use rustc_span::{DUMMY_SP, Ident, Span}; @@ -267,63 +266,7 @@ fn gather_explicit_clauses_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generi trace!(?clauses); // Add inline `` bounds and bounds in the where clause. for predicate in hir_generics.predicates { - match predicate.kind { - hir::WherePredicateKind::BoundPredicate(bound_pred) => { - let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty); - let bound_vars = tcx.late_bound_vars(predicate.hir_id); - - // This is a `where Ty:` (sic!). - if bound_pred.bounds.is_empty() { - if let ty::Param(_) = ty.kind() { - // We can skip the predicate because type parameters are trivially WF. - } else { - // Keep the type around in a dummy predicate. That way, it's not a complete - // noop (see #53696) and `Ty` is still checked for WF. - - let span = bound_pred.bounded_ty.span; - let clause = ty::Binder::bind_with_vars( - ty::ClauseKind::WellFormed(ty.into()), - bound_vars, - ); - clauses.insert((clause.upcast(tcx), span)); - } - } - - let mut bounds = Vec::new(); - icx.lowerer().lower_bounds( - ty, - bound_pred.bounds, - &mut bounds, - bound_vars, - PredicateFilter::All, - OverlappingAsssocItemConstraints::Allowed, - ); - clauses.extend(bounds); - } - - hir::WherePredicateKind::RegionPredicate(region_pred) => { - let r1 = icx - .lowerer() - .lower_lifetime(region_pred.lifetime, RegionInferReason::RegionPredicate); - clauses.extend(region_pred.bounds.iter().map(|bound| { - let (r2, span) = match bound { - hir::GenericBound::Outlives(lt) => ( - icx.lowerer().lower_lifetime(lt, RegionInferReason::RegionPredicate), - lt.ident.span, - ), - bound => { - span_bug!( - bound.span(), - "lifetime param bounds must be outlives, but found {bound:?}" - ) - } - }; - let clause = - ty::ClauseKind::RegionOutlives(ty::OutlivesClause(r1, r2)).upcast(tcx); - (clause, span) - })) - } - } + where_predicate_clauses(&icx, predicate, &mut clauses); } if tcx.features().generic_const_exprs() { @@ -373,6 +316,70 @@ fn gather_explicit_clauses_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generi ty::GenericClauses { parent: generics.parent, clauses: tcx.arena.alloc_from_iter(clauses) } } +pub(super) fn where_predicate_clauses<'tcx>( + icx: &ItemCtxt<'tcx>, + predicate: &hir::WherePredicate<'_>, + clauses: &mut FxIndexSet<(ty::Clause<'tcx>, Span)>, +) { + let tcx = icx.tcx; + match predicate.kind { + hir::WherePredicateKind::BoundPredicate(bound_pred) => { + let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty); + let bound_vars = tcx.late_bound_vars(predicate.hir_id); + + // This is a `where Ty:` (sic!). + if bound_pred.bounds.is_empty() { + if let ty::Param(_) = ty.kind() { + // We can skip the predicate because type parameters are trivially WF. + } else { + // Keep the type around in a dummy predicate. That way, it's not a complete + // noop (see #53696) and `Ty` is still checked for WF. + + let span = bound_pred.bounded_ty.span; + let clause = ty::Binder::bind_with_vars( + ty::ClauseKind::WellFormed(ty.into()), + bound_vars, + ); + clauses.insert((clause.upcast(tcx), span)); + } + } + + let mut bounds = Vec::new(); + icx.lowerer().lower_bounds( + ty, + bound_pred.bounds, + &mut bounds, + bound_vars, + PredicateFilter::All, + OverlappingAsssocItemConstraints::Allowed, + ); + clauses.extend(bounds); + } + + hir::WherePredicateKind::RegionPredicate(region_pred) => { + let r1 = icx + .lowerer() + .lower_lifetime(region_pred.lifetime, RegionInferReason::RegionPredicate); + clauses.extend(region_pred.bounds.iter().map(|bound| { + let (r2, span) = match bound { + hir::GenericBound::Outlives(lt) => ( + icx.lowerer().lower_lifetime(lt, RegionInferReason::RegionPredicate), + lt.ident.span, + ), + bound => { + span_bug!( + bound.span(), + "lifetime param bounds must be outlives, but found {bound:?}" + ) + } + }; + let clause = ty::ClauseKind::RegionOutlives(ty::OutlivesClause(r1, r2)).upcast(tcx); + (clause, span) + })) + } + } +} + /// Opaques have duplicated lifetimes and we need to compute bidirectional outlives clauses to /// enforce that these lifetimes stay in sync. fn compute_bidirectional_outlives_clauses<'tcx>( @@ -444,7 +451,7 @@ fn const_evaluatable_clauses_of<'tcx>( } // Skip type consts as mGCA doesn't support evaluatable clauses. - if alias_const.kind.is_type_const(self.tcx) { + if alias_const.kind.is_direct_const(self.tcx) { return; } diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index dbd210e08ea50..042b931750b71 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -33,7 +33,7 @@ use tracing::{debug, debug_span, instrument}; use crate::diagnostics; use crate::hir::definitions::PerParentDisambiguatorState; -#[extension(trait RegionExt)] +#[extension(trait ResolvedArgExt)] impl ResolvedArg { fn early(param: &GenericParam<'_>) -> ResolvedArg { ResolvedArg::EarlyBound(param.def_id) @@ -1087,7 +1087,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { fn visit_test_binder_forall( &mut self, - forall: &'tcx rustc_hir::TestBinderForall<'tcx>, + forall: &'tcx hir::TestBinderForall<'tcx>, ) -> Self::Result { let (bound_vars, binders): (FxIndexMap, Vec<_>) = forall .generics @@ -1121,7 +1121,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { fn visit_test_binder_exists( &mut self, - exists: &'tcx rustc_hir::TestBinderExists<'tcx>, + exists: &'tcx hir::TestBinderExists<'tcx>, ) -> Self::Result { let (bound_vars, binders): (FxIndexMap, Vec<_>) = exists .params @@ -1149,6 +1149,34 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { this.visit_test_binder_body(exists.body); }); } + + fn visit_test_binder_bound_type_constraint( + &mut self, + bound_type: &'tcx hir::TestBinderBoundTypeConstraint<'tcx>, + ) -> Self::Result { + let (bound_vars, binders): (FxIndexMap, Vec<_>) = bound_type + .params + .iter() + .enumerate() + .map(|(late_bound_idx, param)| { + ( + (param.def_id, ResolvedArg::late(late_bound_idx as u32, param)), + late_arg_as_bound_arg(param), + ) + }) + .unzip(); + self.record_late_bound_vars(bound_type.hir_id, binders); + let scope = Scope::Binder { + hir_id: bound_type.hir_id, + bound_vars, + s: self.scope, + scope_type: BinderScopeType::Normal, + where_bound_origin: None, + }; + self.with(scope, |this| { + intravisit::walk_test_binder_bound_type_constraint(this, bound_type); + }); + } } fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: LocalDefId) -> ObjectLifetimeDefault { diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 45254aa23896d..6ebd38195ffbe 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -87,10 +87,14 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ TraitItemKind::Const(ty, rhs) => rhs .and_then(|rhs| { ty.is_suggestable_infer_ty().then(|| { + let hir_body_id = match rhs { + ConstItemRhs::Body(body) => Some(body.hir_id), + ConstItemRhs::Direct(_) => None, + }; infer_placeholder_type( icx.lowerer(), def_id, - rhs.hir_id(), + hir_body_id, ty.span, rhs.span(tcx), item.ident, @@ -109,10 +113,14 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ ImplItemKind::Fn(_, _) => new_bound_fn_def(item.hir_id(), def_id.to_def_id()), ImplItemKind::Const(ty, rhs) => { if ty.is_suggestable_infer_ty() { + let hir_body_id = match rhs { + ConstItemRhs::Body(body) => Some(body.hir_id), + ConstItemRhs::Direct(_) => None, + }; infer_placeholder_type( icx.lowerer(), def_id, - rhs.hir_id(), + hir_body_id, ty.span, rhs.span(tcx), item.ident, @@ -137,7 +145,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ infer_placeholder_type( icx.lowerer(), def_id, - body_id.hir_id, + Some(body_id.hir_id), ty.span, tcx.hir_body(body_id).value.span, ident, @@ -157,10 +165,14 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ } ItemKind::Const(ident, _, ty, rhs) => { if ty.is_suggestable_infer_ty() { + let hir_body_id = match rhs { + ConstItemRhs::Body(body) => Some(body.hir_id), + ConstItemRhs::Direct(_) => None, + }; infer_placeholder_type( icx.lowerer(), def_id, - rhs.hir_id(), + hir_body_id, ty.span, rhs.span(tcx), ident, @@ -431,28 +443,28 @@ fn const_arg_anon_type_of<'tcx>(icx: &ItemCtxt<'tcx>, arg_hir_id: HirId, span: S fn infer_placeholder_type<'tcx>( cx: &dyn HirTyLowerer<'tcx>, def_id: LocalDefId, - hir_id: HirId, + hir_body_id: Option, ty_span: Span, body_span: Span, item_ident: Ident, kind: &'static str, ) -> Ty<'tcx> { let tcx = cx.tcx(); - // If the type is omitted on a `type const` we can't run - // type check on since that requires the const have a body - // which `type const`s don't. - let ty = if tcx.is_type_const(def_id.to_def_id()) { - if let Some(trait_item_def_id) = tcx.trait_item_of(def_id.to_def_id()) { - tcx.type_of(trait_item_def_id).instantiate_identity().skip_norm_wip() - } else { - Ty::new_error_with_message( - tcx, - ty_span, - "constant with `type const` requires an explicit type", - ) + // If the type is omitted on const with `ConstItemRhs::Direct`, we can't run type check on it, + // since that requires the const have a body, i.e. `ConstItemRhs::Body`. + let ty = match hir_body_id { + Some(hir_id) => tcx.typeck(def_id).node_type(hir_id), + None => { + if let Some(trait_item_def_id) = tcx.trait_item_of(def_id.to_def_id()) { + tcx.type_of(trait_item_def_id).instantiate_identity().skip_norm_wip() + } else { + Ty::new_error_with_message( + tcx, + ty_span, + "directly represented const requires an explicit type", + ) + } } - } else { - tcx.typeck(def_id).node_type(hir_id) }; // If this came from a free `const` or `static mut?` item, diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs index 5324b4d3552c6..1ae3fecf92096 100644 --- a/compiler/rustc_hir_analysis/src/delegation.rs +++ b/compiler/rustc_hir_analysis/src/delegation.rs @@ -7,8 +7,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{DelegationSelfTyPropagationKind, PathSegment}; use rustc_middle::ty::{ - self, EarlyBinder, RegionExt, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, - TypeVisitableExt, + self, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; use rustc_span::{ErrorGuaranteed, Span, kw}; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 9fde34f473205..219637ba4f16f 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -557,7 +557,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }); if let ty::AssocTag::Const = assoc_tag - && !self.tcx().is_type_const(assoc_item.def_id) + && !self.tcx().is_direct_const(assoc_item.def_id) && !tcx.features().generic_const_args() { if tcx.features().min_generic_const_args() { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index cfff8d1768f0e..8965767be3ed6 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -44,7 +44,7 @@ use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_middle::middle::stability::AllowUnstable; use rustc_middle::ty::{ self, Const, FnSigKind, GenericArgKind, GenericArgsRef, GenericParamDefKind, LitToConstInput, - RegionExt, Ty, TyCtxt, TypeSuperFoldable, TypeVisitableExt, TypingMode, Unnormalized, Upcast, + Ty, TyCtxt, TypeSuperFoldable, TypeVisitableExt, TypingMode, Unnormalized, Upcast, const_lit_matches_ty, fold_regions, }; use rustc_middle::{bug, span_bug}; @@ -3153,7 +3153,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { span: Span, ) -> Result<(), ErrorGuaranteed> { let tcx = self.tcx(); - if tcx.is_type_const(def_id) || tcx.features().generic_const_args() { + if tcx.is_type_const_syntax(def_id) || tcx.features().generic_const_args() { Ok(()) } else { let mut err = self.dcx().struct_span_err( diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 41f98e2fb40c0..20ef75244bb4e 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -174,7 +174,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) { } DefKind::Const { .. } if !tcx.generics_of(item_def_id).own_requires_monomorphization() - && !tcx.is_type_const(item_def_id) => + && tcx.const_of_item(item_def_id).is_none() => { // FIXME(generic_const_items): Passing empty instead of identity args is fishy but // seems to be fine for now. Revisit this! diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index a949f8e505fa7..6d1ae563a9fa2 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -218,6 +218,9 @@ impl<'a> State<'a> { Node::WherePredicate(pred) => self.print_where_predicate(pred), Node::TestBinderForall(_) => panic!("cannot print Node::TestBinderForall"), Node::TestBinderExists(_) => panic!("cannot print Node::TestBinderExists"), + Node::TestBinderBoundTypeConstraint(_) => { + panic!("cannot print Node::TestBinderBoundTypeConstraint") + } Node::Synthetic => unreachable!(), Node::Err(_) => self.word("/*ERROR*/"), } @@ -1166,7 +1169,7 @@ impl<'a> State<'a> { fn print_const_item_rhs(&mut self, ct_rhs: hir::ConstItemRhs<'_>) { match ct_rhs { hir::ConstItemRhs::Body(body_id) => self.ann.nested(self, Nested::Body(body_id)), - hir::ConstItemRhs::TypeConst(const_arg) => self.print_const_arg(const_arg), + hir::ConstItemRhs::Direct(const_arg) => self.print_const_arg(const_arg), } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index d5217ae5c31d9..3e2d35da5307d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -202,6 +202,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } steps }), + infer_closure_kind: Box::new(|closure_def_id| { + self.infer_closure_kind_for_diagnostic(closure_def_id) + }), } } } diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 05062155915d6..e59ca32aba116 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -31,9 +31,7 @@ use rustc_middle::ty::print::{ PrintTraitRefExt as _, with_crate_prefix, with_forced_trimmed_paths, with_no_visible_paths_if_doc_hidden, }; -use rustc_middle::ty::{ - self, GenericArgKind, IsSuggestable, RegionExt, Ty, TyCtxt, TypeVisitableExt, -}; +use rustc_middle::ty::{self, GenericArgKind, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::def_id::DefIdSet; use rustc_span::{ DUMMY_SP, ErrorGuaranteed, ExpnKind, FileName, Ident, MacroKind, Span, Symbol, edit_distance, diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 72886730f18c5..38839c598f913 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -81,6 +81,83 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // it's our job to process these. assert!(self.deferred_call_resolutions.borrow().is_empty()); } + + pub(crate) fn infer_closure_kind_for_diagnostic( + &self, + closure_def_id: LocalDefId, + ) -> Option<(ty::ClosureKind, Option<(Span, Place<'tcx>)>)> { + let hir_id = self.tcx.local_def_id_to_hir_id(closure_def_id); + let hir::Node::Expr(expr) = self.tcx.hir_node_by_def_id(closure_def_id) else { + return None; + }; + let hir::ExprKind::Closure(&hir::Closure { + capture_clause, + body: body_id, + explicit_captures, + .. + }) = expr.kind + else { + return None; + }; + let body = self.tcx.hir_body(body_id); + + // We cannot reliably infer the closure kind if there are nested closures whose + // captures have not yet been analyzed. + struct HasNestedClosure(bool); + impl<'v> Visitor<'v> for HasNestedClosure { + fn visit_expr(&mut self, expr: &'v hir::Expr<'v>) { + if matches!(expr.kind, hir::ExprKind::Closure(..)) { + self.0 = true; + return; + } + intravisit::walk_expr(self, expr); + } + } + let mut has_nested = HasNestedClosure(false); + has_nested.visit_body(body); + if has_nested.0 { + return None; + } + + let closure_fcx = FnCtxt::new(self, self.tcx.param_env(closure_def_id), closure_def_id); + + let mut delegate = InferBorrowKind { + fcx: &closure_fcx, + closure_def_id, + capture_information: Default::default(), + fake_reads: Default::default(), + }; + + let _ = euv::ExprUseVisitor::new(&closure_fcx, &mut delegate).consume_body(body); + + for capture in explicit_captures { + let place = closure_fcx.place_for_root_variable(closure_def_id, capture.var_hir_id); + delegate.consume(&PlaceWithHirId { hir_id: capture.var_hir_id, place }, hir_id); + } + + let (_, closure_kind, mut origin) = self + .process_collected_capture_information(capture_clause, &delegate.capture_information); + + // Bail out if a by-value capture has unresolved inference variables, since + // fallback might later resolve the type to `Copy` (making the closure `Fn`). + if closure_kind == ty::ClosureKind::FnOnce { + for (place, capture_info) in &delegate.capture_information { + if matches!(capture_info.capture_kind, ty::UpvarCapture::ByValue) + && place.ty().has_infer() + { + return None; + } + } + } + + if !enable_precise_capture(expr.span) { + if let Some((_, ref mut place)) = origin { + place.projections.clear(); + } + } + + Some((closure_kind, origin)) + } } /// Intermediate format to store the hir_id pointing to the use that resulted in the diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs index 13f0dda180be9..97aad8e6e8c04 100644 --- a/compiler/rustc_index/src/vec.rs +++ b/compiler/rustc_index/src/vec.rs @@ -197,6 +197,11 @@ impl IndexVec { pub fn append(&mut self, other: &mut Self) { self.raw.append(&mut other.raw); } + + #[inline] + pub fn debug_map_view(&self) -> IndexSliceMapView<'_, I, T> { + IndexSliceMapView(self.as_slice()) + } } /// `IndexVec` is often used as a map, so it provides some map-like APIs. @@ -220,11 +225,44 @@ impl IndexVec> { pub fn contains(&self, index: I) -> bool { self.get(index).and_then(Option::as_ref).is_some() } + + /// This debug view will skip printing `None` entries. + /// This is useful when the slice is actually like a map and `None` means + /// a value is absent under that key. + #[inline] + pub fn debug_map_view_compact(&self) -> IndexSliceMapViewCompact<'_, I, T> { + IndexSliceMapViewCompact(self.as_slice()) + } } +pub struct IndexSliceMapView<'a, I: Idx, T>(&'a IndexSlice); +pub struct IndexSliceMapViewCompact<'a, I: Idx, T>(&'a IndexSlice>); + impl fmt::Debug for IndexVec { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&self.raw, fmt) + fmt::Debug::fmt(self.as_slice(), fmt) + } +} + +impl<'a, I: Idx, T: fmt::Debug> fmt::Debug for IndexSliceMapView<'a, I, T> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut entries = fmt.debug_map(); + for (idx, val) in self.0.iter_enumerated() { + entries.entry(&idx, val); + } + entries.finish() + } +} + +impl<'a, I: Idx, T: fmt::Debug> fmt::Debug for IndexSliceMapViewCompact<'a, I, T> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut entries = fmt.debug_map(); + for (idx, val) in self.0.iter_enumerated() { + if let Some(val) = val { + entries.entry(&idx, val); + } + } + entries.finish() } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index e193f28f9738d..56fcc72bd9769 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -30,8 +30,8 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{ self, BoundVarReplacerDelegate, ConstVid, FloatVid, GenericArg, GenericArgKind, GenericArgs, GenericArgsRef, GenericParamDefKind, InferConst, OpaqueTypeKey, ProvisionalHiddenType, - PseudoCanonicalInput, RegionExt, Term, Ty, TyCtxt, TyVid, TypeFoldable, TypeFolder, - TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypingEnv, TypingMode, fold_regions, + PseudoCanonicalInput, Term, Ty, TyCtxt, TyVid, TypeFoldable, TypeFolder, TypeSuperFoldable, + TypeVisitable, TypeVisitableExt, TypingEnv, TypingMode, fold_regions, }; use rustc_span::{DUMMY_SP, Span, Symbol}; use rustc_type_ir::{CanonicalizerState, MayBeErased}; diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 42f686b39136b..cbbf5e3c91c42 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -65,8 +65,8 @@ use rustc_middle::bug; use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::outlives::{Component, push_outlives_components}; use rustc_middle::ty::{ - self, GenericArgKind, GenericArgsRef, PolyTypeOutlivesClause, Region, RegionExt, RegionVid, Ty, - TyCtxt, TypeVisitableExt, eager_resolve_vars, + self, GenericArgKind, GenericArgsRef, PolyTypeOutlivesClause, Region, RegionVid, Ty, TyCtxt, + TypeVisitableExt, eager_resolve_vars, }; use rustc_span::Span; use rustc_type_ir::region_constraint::{self, LeafRegionConstraint}; diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 7db45fde6c8d7..240b288728832 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -8,7 +8,7 @@ use rustc_data_structures::undo_log::UndoLogs; use rustc_data_structures::unify as ut; use rustc_index::IndexVec; use rustc_macros::{TypeFoldable, TypeVisitable}; -use rustc_middle::ty::{self, ReBound, ReStatic, ReVar, Region, RegionExt, RegionVid, Ty, TyCtxt}; +use rustc_middle::ty::{self, ReBound, ReStatic, ReVar, Region, RegionVid, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use tracing::{debug, instrument}; diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index c829864b02288..ebdb82e2b4fe6 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -30,6 +30,7 @@ use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore, unerased_lint_sto use rustc_metadata::EncodedMetadata; use rustc_metadata::creader::CStore; use rustc_middle::arena::Arena; +use rustc_middle::middle::resolve::{ResolverAstLowering, ResolverGlobalCtxt}; use rustc_middle::ty::{self, RegisteredTools, TyCtxt}; use rustc_middle::util::Providers; use rustc_parse::lexer::StripTokens; @@ -792,11 +793,7 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P fn resolver_for_lowering_raw<'tcx>( tcx: TyCtxt<'tcx>, (): (), -) -> ( - &'tcx Steal>, - &'tcx Steal, - &'tcx ty::ResolverGlobalCtxt, -) { +) -> (&'tcx Steal>, &'tcx Steal, &'tcx ResolverGlobalCtxt) { let arenas = WorkerLocal::new(|_| Resolver::arenas()); let _ = tcx.registered_attr_tools(()); // Uses `crate_for_resolver`. let _ = tcx.registered_lint_tools(()); // Uses `crate_for_resolver`. diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index 257b9e1db8e33..e5845e904229f 100644 --- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs +++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs @@ -17,7 +17,7 @@ use rustc_middle::ty::relate::{ structurally_relate_tys, }; use rustc_middle::ty::{ - self, RegionExt, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, + self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, Unnormalized, }; use rustc_middle::{bug, span_bug}; diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 8fe1d6561d135..08053bb2c6a60 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -10,8 +10,8 @@ use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; use rustc_middle::arena::ArenaAllocatable; use rustc_middle::bug; -use rustc_middle::metadata::{AmbigModChild, ModChild}; use rustc_middle::middle::exported_symbols::ExportedSymbol; +use rustc_middle::middle::resolve::{AmbigModChild, ModChild}; use rustc_middle::middle::stability::DeprecationEntry; use rustc_middle::queries::ExternProviders; use rustc_middle::query::LocalCrate; diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 1d9dade66a544..f55783e60da0c 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1382,20 +1382,6 @@ fn should_encode_const(def_kind: DefKind) -> bool { } } -fn should_encode_const_of_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: DefKind) -> bool { - // AssocConst ==> assoc item has value - tcx.is_type_const(def_id) - && (!matches!(def_kind, DefKind::AssocConst { .. }) || assoc_item_has_value(tcx, def_id)) -} - -fn assoc_item_has_value<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool { - let assoc_item = tcx.associated_item(def_id); - match assoc_item.container { - ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => true, - ty::AssocContainer::Trait => assoc_item.defaultness(tcx).has_value(), - } -} - impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_attrs(&mut self, def_id: LocalDefId) { let tcx = self.tcx; @@ -1632,7 +1618,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if let DefKind::AnonConst = def_kind { record!(self.tables.anon_const_kind[def_id] <- self.tcx.anon_const_kind(def_id)); } - if should_encode_const_of_item(self.tcx, def_id, def_kind) { + if let DefKind::Const { .. } | DefKind::AssocConst { .. } = def_kind { record!(self.tables.const_of_item[def_id] <- self.tcx.const_of_item(def_id)); } if tcx.impl_method_has_trait_impl_trait_tys(def_id) diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 064d906293ae8..d16839b910c4b 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -15,7 +15,7 @@ use rustc_data_structures::svh::Svh; use rustc_hir as hir; use rustc_hir::attrs::StrippedCfgItem; use rustc_hir::attrs::lang_items::LangItem; -use rustc_hir::def::{CtorKind, DefKind, DocLinkResMap, MacroKinds}; +use rustc_hir::def::{CtorKind, DefKind, MacroKinds}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIndex, DefPathHash, StableCrateId}; use rustc_hir::definitions::DefKey; use rustc_hir::{PreciseCapturingArgKind, attrs}; @@ -24,12 +24,12 @@ use rustc_index::bit_set::DenseBitSet; use rustc_macros::{ BlobDecodable, Decodable, Encodable, LazyDecodable, MetadataEncodable, TyDecodable, TyEncodable, }; -use rustc_middle::metadata::{AmbigModChild, ModChild}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::deduced_param_attrs::DeducedParamAttrs; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; use rustc_middle::middle::lib_features::FeatureStability; +use rustc_middle::middle::resolve::{AmbigModChild, DocLinkResMap, ModChild}; use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault; use rustc_middle::mir; use rustc_middle::mir::ConstValue; @@ -480,10 +480,10 @@ define_tables! { assumed_wf_types_for_rpitit: Table, Span)>>, opaque_ty_origin: Table>>, anon_const_kind: Table>, - const_of_item: Table>>>, + const_of_item: Table>>>>, associated_types_for_impl_traits_in_trait_or_impl: Table>>>, - live_args_for_alias_from_outlives_bounds: Table>>>>>, - args_known_to_outlive_alias_params: Table, Vec>)>>>>, + live_args_for_alias_from_outlives_bounds: Table>>, + args_known_to_outlive_alias_params: Table)>>>, mut_restriction: Table>, } diff --git a/compiler/rustc_metadata/src/rmeta/parameterized.rs b/compiler/rustc_metadata/src/rmeta/parameterized.rs index f19737bb936be..4eb922446b71b 100644 --- a/compiler/rustc_metadata/src/rmeta/parameterized.rs +++ b/compiler/rustc_metadata/src/rmeta/parameterized.rs @@ -104,18 +104,18 @@ trivially_parameterized_over_tcx! { rustc_hir::attrs::StrippedCfgItem, rustc_hir::attrs::lang_items::LangItem, rustc_hir::def::DefKind, - rustc_hir::def::DocLinkResMap, rustc_hir::def_id::DefId, rustc_hir::def_id::DefIndex, rustc_hir::definitions::DefKey, rustc_index::bit_set::DenseBitSet, - rustc_middle::metadata::AmbigModChild, - rustc_middle::metadata::ModChild, rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs, rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile, rustc_middle::middle::deduced_param_attrs::DeducedParamAttrs, rustc_middle::middle::exported_symbols::SymbolExportInfo, rustc_middle::middle::lib_features::FeatureStability, + rustc_middle::middle::resolve::AmbigModChild, + rustc_middle::middle::resolve::DocLinkResMap, + rustc_middle::middle::resolve::ModChild, rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault, rustc_middle::mir::ConstQualifs, rustc_middle::mir::ConstValue, diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 5995c048d8b92..3c973d7d3a5a2 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -36,18 +36,21 @@ rustc_arena::declare_arena! { rustc_hir::def_id::LocalDefId, rustc_middle::ty::DefinitionSiteHiddenType<'tcx>, >, - resolver: rustc_data_structures::steal::Steal>, + resolver: + rustc_data_structures::steal::Steal< + rustc_middle::middle::resolve::ResolverAstLowering<'tcx> + >, index_ast: rustc_index::IndexVec< rustc_span::def_id::LocalDefId, rustc_data_structures::steal::Steal<( - std::sync::Arc>, - rustc_ast::AstOwner + std::sync::Arc>, + rustc_middle::middle::resolve::AstOwner )> >, crate_alone: rustc_data_structures::steal::Steal, crate_for_resolver: rustc_data_structures::steal::Steal<(rustc_ast::Crate, rustc_ast::AttrVec)>, - resolutions: rustc_middle::ty::ResolverGlobalCtxt, + resolutions: rustc_middle::middle::resolve::ResolverGlobalCtxt, const_allocs: rustc_middle::mir::interpret::Allocation, region_scope_tree: rustc_middle::middle::region::ScopeTree, // Required for the incremental on-disk cache @@ -128,9 +131,9 @@ rustc_arena::declare_arena! { rustc_middle::ty::EarlyBinder<'tcx, Ty<'tcx>> >, external_constraints: rustc_middle::traits::solve::ExternalConstraintsData>, - doc_link_resolutions: rustc_hir::def::DocLinkResMap, + doc_link_resolutions: rustc_middle::middle::resolve::DocLinkResMap, stripped_cfg_items: rustc_hir::attrs::StrippedCfgItem, - mod_child: rustc_middle::metadata::ModChild, + mod_child: rustc_middle::middle::resolve::ModChild, features: rustc_feature::Features, specialization_graph: rustc_middle::traits::specialization_graph::Graph, crate_inherent_impls: rustc_middle::ty::CrateInherentImpls, diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index b384a7a16e54f..15188f68ccf52 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -798,6 +798,7 @@ impl<'tcx> TyCtxt<'tcx> { Node::PreciseCapturingNonLifetimeArg(_param) => node_str("parameter"), Node::TestBinderForall(_) => node_str("forall"), Node::TestBinderExists(_) => node_str("exists"), + Node::TestBinderBoundTypeConstraint(_) => node_str("test bound type constraint"), Node::Synthetic => unreachable!(), Node::Err(_) => node_str("error"), } @@ -1075,6 +1076,7 @@ impl<'tcx> TyCtxt<'tcx> { Node::PreciseCapturingNonLifetimeArg(param) => param.ident.span, Node::TestBinderForall(forall) => forall.span, Node::TestBinderExists(exists) => exists.span, + Node::TestBinderBoundTypeConstraint(bound_type) => bound_type.span, Node::Synthetic => unreachable!(), Node::Err(span) => span, } diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index f74f32d44d830..15a24ffea6700 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -352,7 +352,8 @@ impl<'tcx> TyCtxt<'tcx> { | Node::ConstArgExprField(_) | Node::OpaqueTy(_) | Node::TestBinderForall(_) - | Node::TestBinderExists(_) => { + | Node::TestBinderExists(_) + | Node::TestBinderBoundTypeConstraint(_) => { unreachable!("no sub-expr expected for {parent_node:?}") } } diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 993cb6e7769dd..48d90f9c704fc 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -77,7 +77,6 @@ pub mod hooks; pub mod ich; pub mod infer; pub mod lint; -pub mod metadata; pub mod middle; pub mod mir; pub mod mono; diff --git a/compiler/rustc_middle/src/metadata.rs b/compiler/rustc_middle/src/metadata.rs deleted file mode 100644 index 0c9b44a93a20e..0000000000000 --- a/compiler/rustc_middle/src/metadata.rs +++ /dev/null @@ -1,53 +0,0 @@ -use rustc_hir::def::Res; -use rustc_macros::{StableHash, TyDecodable, TyEncodable}; -use rustc_span::Ident; -use rustc_span::def_id::{DefId, ModId}; -use smallvec::SmallVec; - -use crate::ty; - -/// A simplified version of `ImportKind` from resolve. -/// `DefId`s here correspond to `use` and `extern crate` items themselves, not their targets. -#[derive(Clone, Copy, Debug, TyEncodable, TyDecodable, StableHash)] -pub enum Reexport { - Single(DefId), - Glob(DefId), - ExternCrate(DefId), - MacroUse, - MacroExport, -} - -impl Reexport { - pub fn id(self) -> Option { - match self { - Reexport::Single(id) | Reexport::Glob(id) | Reexport::ExternCrate(id) => Some(id), - Reexport::MacroUse | Reexport::MacroExport => None, - } - } -} - -/// This structure is supposed to keep enough data to re-create `Decl`s for other crates -/// during name resolution. Right now the bindings are not recreated entirely precisely so we may -/// need to add more data in the future to correctly support macros 2.0, for example. -/// Module child can be either a proper item or a reexport (including private imports). -/// In case of reexport all the fields describe the reexport item itself, not what it refers to. -#[derive(Debug, TyEncodable, TyDecodable, StableHash)] -pub struct ModChild { - /// Name of the item. - pub ident: Ident, - /// Resolution result corresponding to the item. - /// Local variables cannot be exported, so this `Res` doesn't need the ID parameter. - pub res: Res, - /// Visibility of the item. - pub vis: ty::Visibility, - /// Reexport chain linking this module child to its original reexported item. - /// Empty if the module child is a proper item. - pub reexport_chain: SmallVec<[Reexport; 2]>, -} - -/// Same as `ModChild`, however, it includes ambiguity error. -#[derive(Debug, TyEncodable, TyDecodable, StableHash)] -pub struct AmbigModChild { - pub main: ModChild, - pub second: ModChild, -} diff --git a/compiler/rustc_middle/src/middle/mod.rs b/compiler/rustc_middle/src/middle/mod.rs index 7967a6222c3be..924dcceb9cef8 100644 --- a/compiler/rustc_middle/src/middle/mod.rs +++ b/compiler/rustc_middle/src/middle/mod.rs @@ -34,5 +34,6 @@ pub mod lib_features { } pub mod privacy; pub mod region; +pub mod resolve; pub mod resolve_bound_vars; pub mod stability; diff --git a/compiler/rustc_middle/src/middle/resolve.rs b/compiler/rustc_middle/src/middle/resolve.rs new file mode 100644 index 0000000000000..2958048103320 --- /dev/null +++ b/compiler/rustc_middle/src/middle/resolve.rs @@ -0,0 +1,309 @@ +//! This module contains types that carry name resolution results from `rustc_resolve` to a +//! consumer in another crate (e.g. AST lowering, metadata, or a query). + +use rustc_ast::node_id::NodeMap; +use rustc_ast::{self as ast, NodeId}; +use rustc_attr_ir::StrippedCfgItem; +use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; +use rustc_data_structures::steal::Steal; +use rustc_data_structures::unord::{UnordMap, UnordSet}; +use rustc_errors::{ErrorGuaranteed, LintBuffer}; +use rustc_hir::def::{DefKind, Namespace, PerNS, Res}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, LocalModId, ModId}; +use rustc_hir::definitions::PerParentDisambiguatorState; +use rustc_hir::{MissingLifetimeKind, TraitCandidate}; +use rustc_macros::{StableHash, TyDecodable, TyEncodable}; +use rustc_span::{ExpnId, Ident, Span, Symbol}; +use smallvec::SmallVec; + +use crate::middle::privacy::EffectiveVisibilities; +use crate::ty::Visibility; + +/// The result of resolving a path before lowering to HIR, +/// with "module" segments resolved and associated item +/// segments deferred to type checking. +/// `base_res` is the resolution of the resolved part of the +/// path, `unresolved_segments` is the number of unresolved +/// segments. +/// +/// ```text +/// module::Type::AssocX::AssocY::MethodOrAssocType +/// ^~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +/// base_res unresolved_segments = 3 +/// +/// ::AssocX::AssocY::MethodOrAssocType +/// ^~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~ +/// base_res unresolved_segments = 2 +/// ``` +#[derive(Copy, Clone, Debug)] +pub struct PartialRes { + base_res: Res, + unresolved_segments: usize, +} + +impl PartialRes { + #[inline] + pub fn new(base_res: Res) -> Self { + PartialRes { base_res, unresolved_segments: 0 } + } + + #[inline] + pub fn with_unresolved_segments(base_res: Res, mut unresolved_segments: usize) -> Self { + if base_res == Res::Err { + unresolved_segments = 0 + } + PartialRes { base_res, unresolved_segments } + } + + #[inline] + pub fn base_res(&self) -> Res { + self.base_res + } + + #[inline] + pub fn unresolved_segments(&self) -> usize { + self.unresolved_segments + } + + #[inline] + pub fn full_res(&self) -> Option> { + (self.unresolved_segments == 0).then_some(self.base_res) + } + + #[inline] + pub fn expect_full_res(&self) -> Res { + self.full_res().expect("unexpected unresolved segments") + } +} + +/// Resolution for a lifetime appearing in a type. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub enum LifetimeRes { + /// Successfully linked the lifetime to a generic parameter. + Param { + /// Id of the generic parameter that introduced it. + param: LocalDefId, + /// Id of the introducing place. That can be: + /// - an item's id, for the item's generic parameters; + /// - a TraitRef's ref_id, identifying the `for<...>` binder; + /// - a FnPtr type's id. + /// + /// This information is used for impl-trait lifetime captures, to know when to or not to + /// capture any given lifetime. + binder: NodeId, + }, + /// Created a generic parameter for an anonymous lifetime. + Fresh { + /// Id of the generic parameter that introduced it. + /// + /// Creating the associated `LocalDefId` is the responsibility of lowering. + param: NodeId, + /// Kind of elided lifetime + kind: MissingLifetimeKind, + }, + /// This variant is used for anonymous lifetimes that we did not resolve during + /// late resolution. Those lifetimes will be inferred by typechecking. + Infer, + /// `'static` lifetime. + Static, + /// Resolution failure. + Error(ErrorGuaranteed), + /// HACK: This is used to recover the NodeId of an elided lifetime. + ElidedAnchor { start: NodeId, end: NodeId }, +} + +/// A simplified version of `ImportKind` from resolve. +/// `DefId`s here correspond to `use` and `extern crate` items themselves, not their targets. +#[derive(Clone, Copy, Debug, TyEncodable, TyDecodable, StableHash)] +pub enum Reexport { + Single(DefId), + Glob(DefId), + ExternCrate(DefId), + MacroUse, + MacroExport, +} + +impl Reexport { + pub fn id(self) -> Option { + match self { + Reexport::Single(id) | Reexport::Glob(id) | Reexport::ExternCrate(id) => Some(id), + Reexport::MacroUse | Reexport::MacroExport => None, + } + } +} + +/// This structure is supposed to keep enough data to re-create `Decl`s for other crates +/// during name resolution. Right now the bindings are not recreated entirely precisely so we may +/// need to add more data in the future to correctly support macros 2.0, for example. +/// Module child can be either a proper item or a reexport (including private imports). +/// In case of reexport all the fields describe the reexport item itself, not what it refers to. +#[derive(Debug, TyEncodable, TyDecodable, StableHash)] +pub struct ModChild { + /// Name of the item. + pub ident: Ident, + /// Resolution result corresponding to the item. + /// Local variables cannot be exported, so this `Res` doesn't need the ID parameter. + pub res: Res, + /// Visibility of the item. + pub vis: Visibility, + /// Reexport chain linking this module child to its original reexported item. + /// Empty if the module child is a proper item. + pub reexport_chain: SmallVec<[Reexport; 2]>, +} + +/// Same as `ModChild`, however, it includes ambiguity error. +#[derive(Debug, TyEncodable, TyDecodable, StableHash)] +pub struct AmbigModChild { + pub main: ModChild, + pub second: ModChild, +} + +#[derive(Debug, StableHash)] +pub struct ResolverGlobalCtxt { + pub visibilities_for_hashing: Vec<(LocalDefId, Visibility)>, + /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`. + pub expn_that_defined: UnordMap, + pub effective_visibilities: EffectiveVisibilities, + // FIXME: This table contains ADTs reachable from macro 2.0. + // Currently, reachability of a definition from a macro is determined by nominal visibility + // (see `compute_effective_visibilities`). This is incorrect and leads to the necessity + // of traversing ADT fields in `rustc_privacy`. Remove this workaround once the + // correct reachability logic is implemented for macros. + pub macro_reachable_adts: FxIndexMap>, + pub extern_crate_map: UnordMap, + pub maybe_unused_trait_imports: FxIndexSet, + pub module_children: LocalDefIdMap>, + pub ambig_module_children: LocalDefIdMap>, + pub glob_map: FxIndexMap>, + pub main_def: Option, + pub trait_impls: FxIndexMap>, + /// A list of proc macro LocalDefIds, written out in the order in which + /// they are declared in the static array generated by proc_macro_harness. + pub proc_macros: Vec, + /// Mapping from ident span to path span for paths that don't exist as written, but that + /// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`. + pub confused_type_with_std_module: FxIndexMap, + pub doc_link_resolutions: FxIndexMap, + pub doc_link_traits_in_scope: FxIndexMap>, + pub all_macro_rules: UnordSet, + pub stripped_cfg_items: Vec, + // Information about delegations which is used when handling recursive delegations + // and ensures easy access to delegation-only `LocalDefId`s. + pub delegation_infos: FxIndexMap, +} + +#[derive(Debug)] +pub struct PerOwnerResolverData<'tcx> { + pub node_id_to_def_id: NodeMap = Default::default(), + /// Whether lifetime elision was successful. + pub lifetime_elision_allowed: bool = false, + /// Resolutions for labels. Maps from NodeId of the break/continue expression to the NodeId of + /// their corresponding blocks or loops. + pub label_res_map: NodeMap = Default::default(), + /// Resolutions for lifetimes. + pub lifetimes_res_map: NodeMap = Default::default(), + + pub trait_map: NodeMap<&'tcx [TraitCandidate<'tcx>]> = Default::default(), + + /// Resolution for import nodes, which have multiple resolutions in different namespaces. + pub import_res: PerNS>> = Default::default(), + /// Lifetime parameters that lowering will have to introduce. + pub extra_lifetime_params_map: NodeMap> = + Default::default(), + + /// The id of the owner + pub id: NodeId, + /// The `DefId` of the owner, can't be found in `node_id_to_def_id`. + pub def_id: LocalDefId, +} + +impl<'tcx> PerOwnerResolverData<'tcx> { + pub fn new(id: NodeId, def_id: LocalDefId) -> PerOwnerResolverData<'tcx> { + PerOwnerResolverData { id, def_id, .. } + } + + /// Obtains resolution for a label with the given `NodeId`. + pub fn get_label_res(&self, id: NodeId) -> Option { + self.label_res_map.get(&id).copied() + } + + /// Obtains resolution for a lifetime with the given `NodeId`. + pub fn get_lifetime_res(&self, id: NodeId) -> Option { + self.lifetimes_res_map.get(&id).copied() + } + + /// Obtain the list of lifetimes parameters to add to an item. + /// + /// Extra lifetime parameters should only be added in places that can appear + /// as a `binder` in `LifetimeRes`. + /// + /// The extra lifetimes that appear from the parenthesized `Fn`-trait desugaring + /// should appear at the enclosing `PolyTraitRef`. + pub fn extra_lifetime_params(&self, id: NodeId) -> &[(Ident, NodeId, MissingLifetimeKind)] { + self.extra_lifetime_params_map.get(&id).map_or(&[], |v| &v[..]) + } +} + +/// Resolutions that should only be used for lowering. +/// This struct is meant to be consumed by lowering. +#[derive(Debug)] +pub struct ResolverAstLowering<'tcx> { + /// Resolutions for nodes that have a single resolution. + pub partial_res_map: NodeMap, + + pub next_node_id: NodeId, + + pub owners: NodeMap>, + + /// Lints that were emitted by the resolver and early lints. + pub lint_buffer: Steal, + + pub disambiguators: LocalDefIdMap>, +} + +#[derive(Debug, StableHash)] +pub struct DelegationInfo { + // `DefId` (either the resolution at delegation.id or item_id in case of a trait impl) for + // signature resolution, for details see + // https://github.com/rust-lang/rust/issues/118212#issuecomment-2160686914. + /// Refers to the next element in a delegation resolution chain. Usually points to the final + /// resolution, as most "chains" are just one step to a trait or an impl. + pub resolution_id: Result, +} + +#[derive(Clone, Copy, Debug, StableHash)] +pub struct MainDefinition { + pub res: Res, + pub is_import: bool, + pub span: Span, +} + +impl MainDefinition { + pub fn opt_fn_def_id(self) -> Option { + if let Res::Def(DefKind::Fn, def_id) = self.res { Some(def_id) } else { None } + } +} + +// FxIndexMap is necessary because its data ends up in .rmeta files, +// so its iteration order must be consistent. See #159677 for context. +pub type DocLinkResMap = FxIndexMap<(Symbol, Namespace), Option>>; + +/// Fragment of the AST according to "HIR owner" semantics. +/// +/// This is used to map each `LocalDefId` to its content's AST. +/// +/// This type isn't produced by name resolution but it is paired with `ResolverAstLowering` so this +/// is as good a place as any for it. +#[derive(Debug)] +pub enum AstOwner { + /// This definition does not correspond to a HIR owner. + NonOwner, + /// This definition corresponds to a nested `use` tree. + /// The `LocalDefId` points to its HIR owner. + NestedUseTree(LocalDefId), + Crate(Box), + Item(Box), + TraitItem(Box), + ImplItem(Box), + ForeignItem(Box), +} diff --git a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs index a977fe1ddc07c..beb88e981480d 100644 --- a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs +++ b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs @@ -1,4 +1,5 @@ -//! Name resolution for lifetimes and late-bound type and const variables: type declarations. +//! Name resolution for lifetimes and late-bound type and const variables (done by +//! `rustc_hir_analysis`): type declarations. use rustc_data_structures::sorted_map::SortedMap; use rustc_errors::ErrorGuaranteed; diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 51f75367f11cf..099697c68464c 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -102,7 +102,7 @@ fn deprecation_lint(is_in_effect: bool) -> &'static Lint { style = "verbose", applicability = "machine-applicable" )] -pub struct DeprecationSuggestion { +pub(crate) struct DeprecationSuggestion { #[primary_span] pub span: Span, @@ -110,7 +110,7 @@ pub struct DeprecationSuggestion { pub suggestion: Symbol, } -pub struct Deprecated { +pub(crate) struct Deprecated { pub sub: Option, pub kind: String, diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index 5794a6533bd1d..85602a7d389c5 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -65,7 +65,7 @@ use rustc_data_structures::svh::Svh; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::{ErrorGuaranteed, catch_fatal_errors}; use rustc_hir as hir; -use rustc_hir::def::{DefKind, DocLinkResMap}; +use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdSet, LocalModId}; use rustc_hir::{ItemLocalId, PreciseCapturingArgKind}; use rustc_index::IndexVec; @@ -79,7 +79,6 @@ use rustc_target::spec::PanicStrategy; use crate::infer::canonical::{self, Canonical}; use crate::lint::LintExpectation; -use crate::metadata::ModChild; use crate::middle::codegen_fn_attrs::{CodegenFnAttrs, SanitizerFnAttrs}; use crate::middle::dead_code::DeadCodeLivenessSummary; use crate::middle::debugger_visualizer::DebuggerVisualizerFile; @@ -87,6 +86,9 @@ use crate::middle::deduced_param_attrs::DeducedParamAttrs; use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; use crate::middle::lib_features::LibFeatures; use crate::middle::privacy::EffectiveVisibilities; +use crate::middle::resolve::{ + AstOwner, DocLinkResMap, ModChild, ResolverAstLowering, ResolverGlobalCtxt, +}; use crate::middle::resolve_bound_vars::{ObjectLifetimeDefault, ResolveBoundVars, ResolvedArg}; use crate::middle::stability::DeprecationEntry; use crate::mir::interpret::{ @@ -186,16 +188,16 @@ rustc_queries! { desc { "get the value of an environment variable" } } - query resolutions(_: ()) -> &'tcx ty::ResolverGlobalCtxt { + query resolutions(_: ()) -> &'tcx ResolverGlobalCtxt { desc { "getting the resolver outputs" } } query resolver_for_lowering_raw(_: ()) -> ( // Those two fields are consumed by `index_ast`. // We want them to be eventually dropped after lowering. - &'tcx Steal>, + &'tcx Steal>, &'tcx Steal, - &'tcx ty::ResolverGlobalCtxt, + &'tcx ResolverGlobalCtxt, ) { eval_always no_hash @@ -206,8 +208,8 @@ rustc_queries! { // There is only a single `ResolverAstLowering` for all owners. // We want to drop it once the whole HIR has been lowered. // We rely on reference counting to know when all definitions have been stolen. - Arc>, - ast::AstOwner, + Arc>, + AstOwner, )>> { arena_cache eval_always @@ -279,14 +281,22 @@ rustc_queries! { separate_provide_extern } - /// Returns the const of the RHS of a (free or assoc) const item, if it is a `type const`. + /// Returns the const of the RHS of a (free or assoc) const item, if it is a `type const`, or if + /// it is a directly represented `const` (i.e. a const with a `direct_const_arg!` RHS, or a + /// const that `feature(macroless_generic_const_args)` has decided is direct). /// /// When a const item is used in a type-level expression, like in equality for an assoc const /// projection, this allows us to retrieve the typesystem-appropriate representation of the /// const value. /// - /// This query will ICE if given a const that is not marked with `type const`. - query const_of_item(def_id: DefId) -> ty::EarlyBinder<'tcx, ty::Const<'tcx>> { + /// Returns `None` if the constant does not have a directly represented RHS. This does not + /// necessarily mean the constant is invalid to use in the type system, as is the case for a + /// `type const` in a trait definition without a RHS. + /// + /// # Panics + /// + /// This query will panic if the given definition isn't a const item (free or associated const). + query const_of_item(def_id: DefId) -> Option>> { desc { "computing the type-level value for `{}`", tcx.def_path_str(def_id) } cache_on_disk separate_provide_extern @@ -2157,9 +2167,9 @@ rustc_queries! { desc { "listing captured lifetimes for opaque `{}`", tcx.def_path_str(def_id) } } - /// For an opaque type or trait associated type, return the list of potentially live - /// (identity) generic args from the set of outlives bounds on that alias. Callers should - /// instantiate the returned args with the concrete args of the alias. + /// For an opaque type or trait associated type, return the indices of potentially live + /// generic args from the set of outlives bounds on that alias. Callers should use the + /// indices with the concrete args of the alias. /// ```ignore (illustrative) /// // Edition 2024: all args are captured /// fn foo<'a, 'b, T: 'static>(&'a &'b T) -> impl Sized + 'a {} @@ -2171,17 +2181,17 @@ rustc_queries! { /// - `foo` outlives `'a`, but we know that `'b: 'a` holds, so `'b` is *also* potentially live /// (and so is `T`, since `T: 'static` implies `T: 'a`) /// - `bar` outlives `'static`, so we know that no args are potentially live and we can return an empty set - /// - `baz` has no outlives bound, so return `None` and let the caller decide what to do - query live_args_for_alias_from_outlives_bounds(kind: ty::AliasTyKind<'tcx>) -> &'tcx Option>>> { + /// - `baz` has no outlives bound, so all args are potentially live + query live_args_for_alias_from_outlives_bounds(kind: ty::AliasTyKind<'tcx>) -> &'tcx rustc_index::bit_set::DenseBitSet { arena_cache desc { "identifying live args for alias `{:?}`", kind } } - /// For each region param of an alias, the identity args that are known to + /// For each region param of an alias, the indices of the identity args that are known to /// outlive it given only the alias's declared where-clauses. Used for liveness: /// these are the only args whose regions the underlying type of the alias /// could capture while satisfying an outlives bound on that param. - query args_known_to_outlive_alias_params(def_id: DefId) -> &'tcx ty::EarlyBinder<'tcx, Vec<(ty::Region<'tcx>, Vec>)>> { + query args_known_to_outlive_alias_params(def_id: DefId) -> &'tcx Vec<(usize, rustc_index::bit_set::DenseBitSet)> { arena_cache desc { "computing the args known to outlive each region param of alias `{}`", tcx.def_path_str(def_id) } separate_provide_extern diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 23c02ffcb09c4..93d4c59e75c00 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -195,6 +195,7 @@ impl_erasable_for_types_with_no_type_params! { Option, Option, Option>>, + Option>>, Option>, Option, Result<&'_ TokenStream, ()>, diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 0eea804b7cb53..af25d881f53bd 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -65,6 +65,8 @@ bitflags::bitflags! { /// Indicates whether the type is `FieldRepresentingType`. const IS_FIELD_REPRESENTING_TYPE = 1 << 13; /// Indicates whether the type is `MaybeDangling<_>`. + /// Note that this is not the only type with "maybe dangling" semantics! + /// Use `ty.is_like_maybe_dangling()` to check for that. const IS_MAYBE_DANGLING = 1 << 14; } } @@ -528,12 +530,6 @@ impl<'tcx> AdtDef<'tcx> { self.flags().contains(AdtFlags::IS_MANUALLY_DROP) } - /// Returns `true` if this is `MaybeDangling`. - #[inline] - pub fn is_maybe_dangling(self) -> bool { - self.flags().contains(AdtFlags::IS_MAYBE_DANGLING) - } - /// Returns `true` if this is `Pin`. #[inline] pub fn is_pin(self) -> bool { diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index 279a3658109bc..8eee87bdd07ca 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -138,17 +138,12 @@ impl AssocItem { self.kind.as_def_kind() } - pub fn is_type_const(&self) -> bool { - matches!(self.kind, ty::AssocKind::Const { is_type_const: true, .. }) - } - /// Whether this associated item can be constrained with an equality binding. pub fn can_have_equality_constraint(&self, tcx: TyCtxt<'_>) -> bool { match self.kind { ty::AssocKind::Type { .. } => true, - ty::AssocKind::Const { is_type_const: true, .. } => true, - ty::AssocKind::Const { is_type_const: false, .. } => { - tcx.features().generic_const_args() + ty::AssocKind::Const { .. } => { + tcx.features().generic_const_args() || tcx.is_direct_const(self.def_id) } ty::AssocKind::Fn { .. } => false, } @@ -209,9 +204,7 @@ impl AssocKind { pub fn as_def_kind(&self) -> DefKind { match self { - Self::Const { is_type_const, .. } => { - DefKind::AssocConst { is_type_const: *is_type_const } - } + &Self::Const { is_type_const, .. } => DefKind::AssocConst { is_type_const }, Self::Fn { .. } => DefKind::AssocFn, Self::Type { .. } => DefKind::AssocTy, } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 5b5656c05f10d..5ff5c05de734a 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -55,8 +55,8 @@ use crate::hir::{ProjectedMaybeOwner, ProjectedOwnerInfo}; use crate::ich::StableHashState; use crate::infer::canonical::{CanonicalParamEnvCache, CanonicalVarKind}; use crate::lint::emit_lint_base; -use crate::metadata::ModChild; use crate::middle::codegen_fn_attrs::{CodegenFnAttrs, TargetFeature}; +use crate::middle::resolve::{ModChild, ResolverAstLowering}; use crate::middle::resolve_bound_vars; use crate::mir::interpret::{self, Allocation, ConstAllocation}; use crate::mir::{Body, Local, Place, PlaceElem, ProjectionKind, Promoted}; @@ -68,7 +68,6 @@ use crate::traits::solve::{ PredefinedOpaques, }; use crate::ty::predicate::ExistentialPredicateStableCmpExt as _; -use crate::ty::region::RegionExt; use crate::ty::{ self, AdtDef, AdtDefData, AdtKind, Binder, Clause, ClausePolarity, Clauses, Const, FnSigKind, GenericArg, GenericArgs, GenericArgsRef, GenericParamDefKind, List, ListWithCachedTypeInfo, @@ -1029,15 +1028,26 @@ impl<'tcx> TyCtxt<'tcx> { self.is_lang_item(self.parent(def_id), LangItem::AsyncDropInPlace) } - pub fn type_const_span(self, def_id: DefId) -> Option { - if !self.is_type_const(def_id) { - return None; - } - Some(self.def_span(def_id)) + /// Returns true if the const is guaranteed to have a directly represented RHS. This is either + /// because it has a directly represented RHS, or is a trait definition that is marked as + /// requiring its implementation to have a directly represented RHS. + /// + /// Note: Be very careful with using this method - under `generic_const_args`, a trait can + /// declare a regular const, but an `impl` could implement it with a directly represented const + /// (a la refinement). This method would return false in such a case. + pub fn is_direct_const(self, def_id: DefId) -> bool { + debug_assert_matches!( + self.def_kind(def_id), + DefKind::Const { .. } | DefKind::AssocConst { .. } + ); + self.is_type_const_syntax(def_id) || self.const_of_item(def_id).is_some() } - /// Check if the given `def_id` is a `type const` (mgca) - pub fn is_type_const(self, def_id: impl IntoQueryKey) -> bool { + /// Check if the given `def_id` is declared with `type const` syntax (mgca) + /// + /// This is NOT the same as whether the `def_id` can be represented in/used by the type system. + /// For that, you probably want to ask `is_direct_const()` or `const_of_item().is_some()`. + pub fn is_type_const_syntax(self, def_id: impl IntoQueryKey) -> bool { let def_id = def_id.into_query_key(); match self.def_kind(def_id) { DefKind::Const { is_type_const } | DefKind::AssocConst { is_type_const } => { @@ -2878,7 +2888,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn resolver_for_lowering( self, - ) -> (&'tcx Steal>, &'tcx Steal) { + ) -> (&'tcx Steal>, &'tcx Steal) { let (resolver, krate, _) = self.resolver_for_lowering_raw(()); (resolver, krate) } diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs index 74327278dbca6..202991d3f0ada 100644 --- a/compiler/rustc_middle/src/ty/context/impl_interner.rs +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -12,8 +12,8 @@ use rustc_span::{DUMMY_SP, Span, Symbol}; use rustc_type_ir::lang_items::{SolverAdtLangItem, SolverProjectionLangItem, SolverTraitLangItem}; use rustc_type_ir::solve::CanonicalInputData; use rustc_type_ir::{ - BoundVar, CollectAndApply, DebruijnIndex, Interner, TypeFoldable, Unnormalized, VisitorResult, - search_graph, try_visit, + BoundVar, CollectAndApply, DebruijnIndex, Interner, RegionVid, TypeFoldable, Unnormalized, + VisitorResult, search_graph, try_visit, }; use crate::dep_graph::{DepKind, DepNodeIndex}; @@ -186,11 +186,26 @@ impl<'tcx> Interner for TyCtxt<'tcx> { fn type_of_opaque_hir_typeck(self, def_id: LocalDefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { self.type_of_opaque_hir_typeck(def_id) } - fn is_type_const(self, def_id: DefId) -> bool { - self.is_type_const(def_id) + fn is_direct_const(self, alias: ty::AliasConstKind<'tcx>) -> bool { + match alias { + ty::AliasConstKind::Projection { def_id } + | ty::AliasConstKind::InherentSelf { def_id } + | ty::AliasConstKind::InherentImpl { def_id } + | ty::AliasConstKind::Free { def_id } => self.is_direct_const(def_id), + ty::AliasConstKind::Anon { .. } => false, + } } - fn const_of_item(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Const<'tcx>> { - self.const_of_item(def_id) + fn const_of_item( + self, + alias: ty::AliasConstKind<'tcx>, + ) -> Option>> { + match alias { + ty::AliasConstKind::Projection { def_id } + | ty::AliasConstKind::InherentSelf { def_id } + | ty::AliasConstKind::InherentImpl { def_id } + | ty::AliasConstKind::Free { def_id } => self.const_of_item(def_id), + ty::AliasConstKind::Anon { .. } => None, + } } fn anon_const_kind(self, def_id: DefId) -> ty::AnonConstKind { self.anon_const_kind(def_id) @@ -650,6 +665,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.dcx().span_delayed_bug(DUMMY_SP, msg.to_string()) } + fn span_delayed_bug(self, span: Self::Span, msg: impl ToString) -> ErrorGuaranteed { + self.dcx().span_delayed_bug(span, msg.to_string()) + } + fn is_general_coroutine(self, coroutine_def_id: DefId) -> bool { self.is_general_coroutine(coroutine_def_id) } @@ -733,6 +752,15 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.lifetimes.re_static } + fn intern_re_var(self, rv: RegionVid) -> Region<'tcx> { + // Use a pre-interned one when possible. + self.lifetimes + .re_vars + .get(rv.as_usize()) + .copied() + .unwrap_or_else(|| self.intern_region(ty::ReVar(rv))) + } + fn intern_region(self, region_kind: RegionKind<'tcx>) -> Region<'tcx> { self.intern_region(region_kind) } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index c146e7c982de9..3d9148d6ed7ba 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -2,7 +2,6 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_hir::def_id::DefId; use rustc_type_ir::data_structures::DelayedMap; -use crate::ty::region::RegionExt; use crate::ty::{ self, Binder, BoundTy, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index bfdb89dc409f6..f5e983ab48f92 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -9,7 +9,6 @@ use rustc_type_ir::{TypeSuperVisitable as _, TypeVisitable, TypeVisitor}; use tracing::instrument; use super::{Clause, InstantiatedClauses, ParamConst, ParamTy, Ty, TyCtxt, Unnormalized}; -use crate::ty::region::RegionExt; use crate::ty::{self, ClauseKind, EarlyBinder, GenericArgsRef, Region, RegionKind, TyKind}; #[derive(Clone, Debug, TyEncodable, TyDecodable, StableHash)] @@ -152,6 +151,9 @@ impl<'tcx> rustc_type_ir::inherent::GenericsOf> for &'tcx Generics fn count(&self) -> usize { self.parent_count + self.own_params.len() } + fn param_region_def_id(self, tcx: TyCtxt<'tcx>, ebr: ty::EarlyParamRegion) -> DefId { + self.region_param(ebr, tcx).def_id + } } impl<'tcx> Generics { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 764f3b5b93318..c18bf81121377 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1090,20 +1090,6 @@ where }) } - ty::Adt(adt_def, ..) if adt_def.is_maybe_dangling() => { - Self::ty_and_layout_pointee_info_at(this.field(cx, 0), cx, offset).map(|info| { - PointeeInfo { - // Mark the pointer as raw - // (thus removing noalias/readonly/etc in case of the llvm backend) - safe: None, - // Make sure we don't assert dereferenceability of the pointer. - size: Size::ZERO, - // Preserve the alignment assertion! That is required even inside `MaybeDangling`. - align: info.align, - } - }) - } - _ => { let mut data_variant = match &this.variants { // Within the discriminant field, only the niche itself is @@ -1179,6 +1165,21 @@ where } } + // Patch result if we are a MaybeDangling-like type. + if this.ty.is_like_maybe_dangling() + && let Some(info) = result + { + result = Some(PointeeInfo { + // Mark the pointer as raw + // (thus removing noalias/readonly/etc in case of the llvm backend) + safe: None, + // Make sure we don't assert dereferenceability of the pointer. + size: Size::ZERO, + // Preserve the alignment assertion! That is required even inside `MaybeDangling`. + align: info.align, + }); + } + result } }; diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 3db521dfb5dee..cc6a8619e1e74 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -28,21 +28,17 @@ pub use intrinsic::IntrinsicDef; use rustc_abi::{ Align, FieldIdx, Integer, IntegerType, ReprFlags, ReprOptions, ScalableElt, VariantIdx, }; -use rustc_ast::node_id::NodeMap; -use rustc_ast::{self as ast, NodeId}; +use rustc_ast::{self as ast}; pub use rustc_ast_ir::{Movability, Mutability, try_visit}; use rustc_attr_ir::lang_items::LangItem; -use rustc_attr_ir::{self as attr, StrippedCfgItem, find_attr}; -use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; +use rustc_attr_ir::{self as attr, find_attr}; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::intern::Interned; use rustc_data_structures::stable_hash::{StableHash, StableHashCtxt, StableHasher}; -use rustc_data_structures::steal::Steal; -use rustc_data_structures::unord::{UnordMap, UnordSet}; -use rustc_errors::{Diag, ErrorGuaranteed, LintBuffer}; +use rustc_errors::{Diag, ErrorGuaranteed}; use rustc_hir as hir; -use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res}; -use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap}; -use rustc_hir::definitions::PerParentDisambiguatorState; +use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; +use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId}; use rustc_index::bit_set::BitMatrix; use rustc_index::{IndexVec, static_assert_size}; pub use rustc_lint_defs::RegisteredTools; @@ -54,7 +50,7 @@ use rustc_serialize::{Decodable, Encodable}; use rustc_session::config::OptLevel; use rustc_span::def_id::{LocalModId, ModId}; use rustc_span::hygiene::MacroKind; -use rustc_span::{DUMMY_SP, ExpnId, ExpnKind, Ident, Span, Symbol}; +use rustc_span::{DUMMY_SP, ExpnKind, Ident, Span, Symbol}; use rustc_target::callconv::FnAbi; pub use rustc_type_ir::data_structures::{DelayedMap, DelayedSet}; pub use rustc_type_ir::fast_reject::DeepRejectCtxt; @@ -96,8 +92,7 @@ pub use self::predicate::{ TraitRef, TypeOutlivesClause, }; pub use self::region::{ - EarlyParamRegion, LateParamRegion, LateParamRegionKind, Region, RegionExt, RegionKind, - RegionVid, + EarlyParamRegion, LateParamRegion, LateParamRegionKind, Region, RegionKind, RegionVid, }; pub use self::sty::{ Alias, AliasTy, AliasTyKind, Article, Binder, BoundConst, BoundRegion, BoundRegionKind, @@ -114,8 +109,6 @@ pub use self::typeck_results::{ UserTypeKind, }; use crate::diagnostics::{OpaqueHiddenTypeMismatch, TypeMismatchReason}; -use crate::metadata::{AmbigModChild, ModChild}; -use crate::middle::privacy::EffectiveVisibilities; use crate::mir::{Body, CoroutineLayout, CoroutineSavedLocal, MirPhase, SourceInfo}; use crate::query::{IntoQueryKey, Providers}; use crate::ty; @@ -171,135 +164,6 @@ mod visit; // Data types -#[derive(Debug, StableHash)] -pub struct ResolverGlobalCtxt { - pub visibilities_for_hashing: Vec<(LocalDefId, Visibility)>, - /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`. - pub expn_that_defined: UnordMap, - pub effective_visibilities: EffectiveVisibilities, - // FIXME: This table contains ADTs reachable from macro 2.0. - // Currently, reachability of a definition from a macro is determined by nominal visibility - // (see `compute_effective_visibilities`). This is incorrect and leads to the necessity - // of traversing ADT fields in `rustc_privacy`. Remove this workaround once the - // correct reachability logic is implemented for macros. - pub macro_reachable_adts: FxIndexMap>, - pub extern_crate_map: UnordMap, - pub maybe_unused_trait_imports: FxIndexSet, - pub module_children: LocalDefIdMap>, - pub ambig_module_children: LocalDefIdMap>, - pub glob_map: FxIndexMap>, - pub main_def: Option, - pub trait_impls: FxIndexMap>, - /// A list of proc macro LocalDefIds, written out in the order in which - /// they are declared in the static array generated by proc_macro_harness. - pub proc_macros: Vec, - /// Mapping from ident span to path span for paths that don't exist as written, but that - /// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`. - pub confused_type_with_std_module: FxIndexMap, - pub doc_link_resolutions: FxIndexMap, - pub doc_link_traits_in_scope: FxIndexMap>, - pub all_macro_rules: UnordSet, - pub stripped_cfg_items: Vec, - // Information about delegations which is used when handling recursive delegations - // and ensures easy access to delegation-only `LocalDefId`s. - pub delegation_infos: FxIndexMap, -} - -#[derive(Debug)] -pub struct PerOwnerResolverData<'tcx> { - pub node_id_to_def_id: NodeMap = Default::default(), - /// Whether lifetime elision was successful. - pub lifetime_elision_allowed: bool = false, - /// Resolutions for labels. Maps from NodeId of the break/continue expression to the NodeId of - /// their corresponding blocks or loops. - pub label_res_map: NodeMap = Default::default(), - /// Resolutions for lifetimes. - pub lifetimes_res_map: NodeMap = Default::default(), - - pub trait_map: NodeMap<&'tcx [hir::TraitCandidate<'tcx>]> = Default::default(), - - /// Resolution for import nodes, which have multiple resolutions in different namespaces. - pub import_res: hir::def::PerNS>> = Default::default(), - /// Lifetime parameters that lowering will have to introduce. - pub extra_lifetime_params_map: NodeMap> = - Default::default(), - - /// The id of the owner - pub id: ast::NodeId, - /// The `DefId` of the owner, can't be found in `node_id_to_def_id`. - pub def_id: LocalDefId, -} - -impl<'tcx> PerOwnerResolverData<'tcx> { - pub fn new(id: ast::NodeId, def_id: LocalDefId) -> PerOwnerResolverData<'tcx> { - PerOwnerResolverData { id, def_id, .. } - } - - /// Obtains resolution for a label with the given `NodeId`. - pub fn get_label_res(&self, id: ast::NodeId) -> Option { - self.label_res_map.get(&id).copied() - } - - /// Obtains resolution for a lifetime with the given `NodeId`. - pub fn get_lifetime_res(&self, id: ast::NodeId) -> Option { - self.lifetimes_res_map.get(&id).copied() - } - - /// Obtain the list of lifetimes parameters to add to an item. - /// - /// Extra lifetime parameters should only be added in places that can appear - /// as a `binder` in `LifetimeRes`. - /// - /// The extra lifetimes that appear from the parenthesized `Fn`-trait desugaring - /// should appear at the enclosing `PolyTraitRef`. - pub fn extra_lifetime_params( - &self, - id: NodeId, - ) -> &[(Ident, NodeId, hir::MissingLifetimeKind)] { - self.extra_lifetime_params_map.get(&id).map_or(&[], |v| &v[..]) - } -} - -/// Resolutions that should only be used for lowering. -/// This struct is meant to be consumed by lowering. -#[derive(Debug)] -pub struct ResolverAstLowering<'tcx> { - /// Resolutions for nodes that have a single resolution. - pub partial_res_map: NodeMap, - - pub next_node_id: ast::NodeId, - - pub owners: NodeMap>, - - /// Lints that were emitted by the resolver and early lints. - pub lint_buffer: Steal, - - pub disambiguators: LocalDefIdMap>, -} - -#[derive(Debug, StableHash)] -pub struct DelegationInfo { - // `DefId` (either the resolution at delegation.id or item_id in case of a trait impl) for signature resolution, - // for details see https://github.com/rust-lang/rust/issues/118212#issuecomment-2160686914 - /// Refers to the next element in a delegation resolution chain. - /// Usually points to the final resolution, as most "chains" are just - /// one step to a trait or an impl. - pub resolution_id: Result, -} - -#[derive(Clone, Copy, Debug, StableHash)] -pub struct MainDefinition { - pub res: Res, - pub is_import: bool, - pub span: Span, -} - -impl MainDefinition { - pub fn opt_fn_def_id(self) -> Option { - if let Res::Def(DefKind::Fn, def_id) = self.res { Some(def_id) } else { None } - } -} - #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, StableHash)] pub struct ImplTraitHeader<'tcx> { pub trait_ref: ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>, @@ -508,7 +372,7 @@ impl TyCtxt<'_> { /// Compare def-ids based on their position in def-id tree, ancestor def-ids are considered /// larger than descendant def-ids, and two different def-ids are considered unordered if /// neither of them is an ancestor of the other. - fn def_id_partial_cmp(self, lhs: DefId, rhs: DefId) -> Option { + pub fn def_id_partial_cmp(self, lhs: DefId, rhs: DefId) -> Option { // Def-ids from different crates are always unordered. if lhs.krate != rhs.krate { return None; diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs index 8d835a3d2153a..bf716e8027a0a 100644 --- a/compiler/rustc_middle/src/ty/opaque_types.rs +++ b/compiler/rustc_middle/src/ty/opaque_types.rs @@ -5,8 +5,7 @@ use tracing::{debug, instrument, trace}; use crate::diagnostics::ConstNotUsedTraitAlias; use crate::ty::{ - self, GenericArg, GenericArgKind, RegionExt, Ty, TyCtxt, TypeFoldable, TypeFolder, - TypeSuperFoldable, + self, GenericArg, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, }; pub type OpaqueTypeKey<'tcx> = rustc_type_ir::OpaqueTypeKey>; diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index f5960e65c4493..07e935e265c8b 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -24,7 +24,6 @@ use smallvec::SmallVec; use super::*; use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar}; use crate::query::{IntoQueryKey, Providers}; -use crate::ty::region::RegionExt; use crate::ty::{ ConstInt, Expr, GenericArgKind, ParamConst, ScalarInt, Term, TermKind, TraitClause, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs index 154873c435e1c..fbb40465cd5fd 100644 --- a/compiler/rustc_middle/src/ty/region.rs +++ b/compiler/rustc_middle/src/ty/region.rs @@ -1,7 +1,6 @@ -use rustc_errors::MultiSpan; use rustc_hir::def_id::DefId; -use rustc_macros::{StableHash, TyDecodable, TyEncodable, extension}; -use rustc_span::{DUMMY_SP, ErrorGuaranteed, Symbol, kw, sym}; +use rustc_macros::{StableHash, TyDecodable, TyEncodable}; +use rustc_span::{Symbol, kw}; pub use rustc_type_ir::RegionVid; use rustc_type_ir::{ LateParamRegion as IrLateParamRegion, Region as IrRegion, RegionKind as IrRegionKind, @@ -13,139 +12,6 @@ pub type Region<'tcx> = IrRegion>; pub type RegionKind<'tcx> = IrRegionKind>; pub type LateParamRegion<'tcx> = IrLateParamRegion>; -#[extension(pub trait RegionExt<'tcx>)] -impl<'tcx> Region<'tcx> { - #[inline] - fn new_early_param( - tcx: TyCtxt<'tcx>, - early_bound_region: ty::EarlyParamRegion, - ) -> Region<'tcx> { - tcx.intern_region(ty::ReEarlyParam(early_bound_region)) - } - - #[inline] - fn new_late_param(tcx: TyCtxt<'tcx>, scope: DefId, kind: LateParamRegionKind) -> Region<'tcx> { - let data = LateParamRegion { scope, kind }; - tcx.intern_region(ty::ReLateParam(data)) - } - - #[inline] - fn new_var(tcx: TyCtxt<'tcx>, v: ty::RegionVid) -> Region<'tcx> { - // Use a pre-interned one when possible. - tcx.lifetimes - .re_vars - .get(v.as_usize()) - .copied() - .unwrap_or_else(|| tcx.intern_region(ty::ReVar(v))) - } - - /// Constructs a `RegionKind::ReError` region. - #[track_caller] - fn new_error(tcx: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Region<'tcx> { - tcx.intern_region(ty::ReError(guar)) - } - - /// Constructs a `RegionKind::ReError` region and registers a delayed bug to ensure it gets - /// used. - #[track_caller] - fn new_error_misc(tcx: TyCtxt<'tcx>) -> Region<'tcx> { - Region::new_error_with_message( - tcx, - DUMMY_SP, - "RegionKind::ReError constructed but no error reported", - ) - } - - /// Constructs a `RegionKind::ReError` region and registers a delayed bug with the given `msg` - /// to ensure it gets used. - #[track_caller] - fn new_error_with_message>( - tcx: TyCtxt<'tcx>, - span: S, - msg: &'static str, - ) -> Region<'tcx> { - let reported = tcx.dcx().span_delayed_bug(span, msg); - Region::new_error(tcx, reported) - } - - /// Avoid this in favour of more specific `new_*` methods, where possible, - /// to avoid the cost of the `match`. - fn new_from_kind(tcx: TyCtxt<'tcx>, kind: RegionKind<'tcx>) -> Region<'tcx> { - match kind { - ty::ReEarlyParam(region) => Region::new_early_param(tcx, region), - ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), region) => { - Region::new_bound(tcx, debruijn, region) - } - ty::ReBound(ty::BoundVarIndexKind::Canonical, region) => { - Region::new_canonical_bound(tcx, region.var) - } - ty::ReLateParam(ty::LateParamRegion { scope, kind }) => { - Region::new_late_param(tcx, scope, kind) - } - ty::ReStatic => tcx.lifetimes.re_static, - ty::ReVar(vid) => Region::new_var(tcx, vid), - ty::RePlaceholder(region) => Region::new_placeholder(tcx, region), - ty::ReErased => tcx.lifetimes.re_erased, - ty::ReError(reported) => Region::new_error(tcx, reported), - } - } - - fn get_name(self, tcx: TyCtxt<'tcx>) -> Option { - match self.kind() { - ty::ReEarlyParam(ebr) => ebr.is_named().then_some(ebr.name), - ty::ReBound(_, br) => br.kind.get_name(tcx), - ty::ReLateParam(fr) => fr.kind.get_name(tcx), - ty::ReStatic => Some(kw::StaticLifetime), - ty::RePlaceholder(placeholder) => placeholder.bound.kind.get_name(tcx), - _ => None, - } - } - - fn get_name_or_anon(self, tcx: TyCtxt<'tcx>) -> Symbol { - match self.get_name(tcx) { - Some(name) => name, - None => sym::anon, - } - } - - /// Is this region named by the user? - fn is_named(self, tcx: TyCtxt<'tcx>) -> bool { - match self.kind() { - ty::ReEarlyParam(ebr) => ebr.is_named(), - ty::ReBound(_, br) => br.kind.is_named(tcx), - ty::ReLateParam(fr) => fr.kind.is_named(tcx), - ty::ReStatic => true, - ty::ReVar(..) => false, - ty::RePlaceholder(placeholder) => placeholder.bound.kind.is_named(tcx), - ty::ReErased => false, - ty::ReError(_) => false, - } - } - - #[inline] - fn bound_at_or_above_binder(self, index: ty::DebruijnIndex) -> bool { - match self.kind() { - ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), _) => debruijn >= index, - _ => false, - } - } - - /// Given some item `binding_item`, check if this region is a generic parameter introduced by it - /// or one of the parent generics. Returns the `DefId` of the parameter definition if so. - fn opt_param_def_id(self, tcx: TyCtxt<'tcx>, binding_item: DefId) -> Option { - match self.kind() { - ty::ReEarlyParam(ebr) => { - Some(tcx.generics_of(binding_item).region_param(ebr, tcx).def_id) - } - ty::ReLateParam(ty::LateParamRegion { - kind: ty::LateParamRegionKind::Named(def_id), - .. - }) => Some(def_id), - _ => None, - } - } -} - #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] #[derive(StableHash)] pub struct EarlyParamRegion { @@ -154,6 +20,12 @@ pub struct EarlyParamRegion { } impl EarlyParamRegion { + #[inline] + pub fn get_name(&self) -> Option { + if self.is_named() { Some(self.name) } else { None } + } + + #[inline] /// Does this early bound region have a name? Early bound regions normally /// always have names except when using anonymous lifetimes (`'_`). pub fn is_named(&self) -> bool { @@ -167,6 +39,20 @@ impl rustc_type_ir::inherent::ParamLike for EarlyParamRegion { } } +impl<'tcx> rustc_type_ir::inherent::RegionName> for EarlyParamRegion { + #[inline] + fn get_name(&self, _tcx: TyCtxt<'tcx>) -> Option { + self.get_name() + } + + #[inline] + /// Does this early bound region have a name? Early bound regions normally + /// always have names except when using anonymous lifetimes (`'_`). + fn is_named(&self, _tcx: TyCtxt<'tcx>) -> bool { + self.is_named() + } +} + impl std::fmt::Debug for EarlyParamRegion { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}/#{}", self.name, self.index) @@ -237,6 +123,24 @@ impl LateParamRegionKind { } } +impl<'tcx> rustc_type_ir::inherent::RegionName> for LateParamRegionKind { + #[inline] + fn get_name(&self, tcx: TyCtxt<'tcx>) -> Option { + self.get_name(tcx) + } + + #[inline] + fn is_named(&self, tcx: TyCtxt<'tcx>) -> bool { + self.is_named(tcx) + } +} + +impl<'tcx> rustc_type_ir::inherent::DefIdGetter> for LateParamRegionKind { + fn get_def_id(self) -> Option { + self.get_id() + } +} + // Some types are used a lot. Make sure they don't unintentionally get bigger. #[cfg(target_pointer_width = "64")] mod size_asserts { diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 013064b5cec4b..8014a52c9b4e1 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -23,7 +23,7 @@ use rustc_type_ir::{ use tracing::instrument; use ty::util::IntTypeExt; -use super::GenericParamDefKind; +use super::{AdtFlags, GenericParamDefKind}; use crate::infer::canonical::Canonical; use crate::traits::ObligationCause; use crate::ty::InferTy::*; @@ -2183,6 +2183,22 @@ impl<'tcx> Ty<'tcx> { pub fn walk(self) -> TypeWalker> { TypeWalker::new(self.into()) } + + /// Returns `true` if this is a `MaybeDangling`-like type, i.e., a type whose inner + /// references are not required to be dereferenceable and are not reborrowed. + #[inline] + pub fn is_like_maybe_dangling(self) -> bool { + match self.kind() { + ty::Adt(def, _) => { + // ManuallyDrop is "natively" like maybe-dangling so that we don't have + // to nest field types even deeper. + def.flags().contains(AdtFlags::IS_MAYBE_DANGLING) + || def.flags().contains(AdtFlags::IS_MANUALLY_DROP) + } + ty::Closure(..) | ty::Coroutine(..) | ty::CoroutineClosure(..) => true, + _ => false, + } + } } impl<'tcx> rustc_type_ir::inherent::Tys> for &'tcx ty::List> { @@ -2196,9 +2212,9 @@ impl<'tcx> rustc_type_ir::inherent::Tys> for &'tcx ty::List rustc_type_ir::inherent::Symbol> for Symbol { - fn is_kw_underscore_lifetime(self) -> bool { - self == kw::UnderscoreLifetime - } + const KW_UNDERSCORE_LIFETIME: Self = kw::UnderscoreLifetime; + const KW_STATIC_LIFETIME: Self = kw::StaticLifetime; + const SYM_ANON: Self = sym::anon; } // Some types are used a lot. Make sure they don't unintentionally get bigger. diff --git a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs index 5996073241e2c..830fdc5d75573 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs @@ -3,6 +3,7 @@ use rustc_abi::Size; use rustc_ast as ast; use rustc_hir::attrs::lang_items::LangItem; +use rustc_hir::def::DefKind; use rustc_middle::mir::interpret::{CTFE_ALLOC_SALT, Scalar}; use rustc_middle::mir::*; use rustc_middle::thir::*; @@ -71,7 +72,17 @@ pub(crate) fn as_constant_inner<'tcx>( } ExprKind::NamedConst { def_id, args, ref user_ty } => { let user_ty = user_ty.as_ref().and_then(push_cuta); - if tcx.is_type_const(def_id) { + // Under generic_const_args, `def_id` might be a regular const declared in a trait, but + // is `impl`d as a directly represented const. We do not know whether it is here, so we + // must use type system normalization for all consts under generic_const_args. + // FIXME(generic_const_args): there's a lot to consider here! `Const::Ty` uses valtrees + // and `Const::Unevaluated` does not, we should revisit this before stabilization. + if tcx.features().generic_const_args() + || matches!( + tcx.def_kind(def_id), + DefKind::Const { .. } | DefKind::AssocConst { .. } + ) && tcx.is_direct_const(def_id) + { let uneval = ty::AliasConst::new( tcx, ty::AliasConstKind::new_from_def_id( diff --git a/compiler/rustc_mir_build/src/builder/expr/into.rs b/compiler/rustc_mir_build/src/builder/expr/into.rs index 72135df46e904..d5ce1dab1b417 100644 --- a/compiler/rustc_mir_build/src/builder/expr/into.rs +++ b/compiler/rustc_mir_build/src/builder/expr/into.rs @@ -457,9 +457,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let place = b.project_deeper(&[ProjectionElem::Deref], tcx); // Current type: `MaybeUninit`. Field #1 is `ManuallyDrop`. let place = place.project_to_field(FieldIdx::from_u32(1), decls, tcx); - // Current type: `ManuallyDrop`. Field #0 is `MaybeDangling`. - let place = place.project_to_field(FieldIdx::ZERO, decls, tcx); - // Current type: `MaybeDangling`. Field #0 is `T`. + // Current type: `ManuallyDrop`. Field #0 is `T`. let place = place.project_to_field(FieldIdx::ZERO, decls, tcx); // Sanity check. assert_eq!(place.ty(decls, tcx).ty, generic_args.type_at(0)); diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index aad87a99c0036..31a760cc59829 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -17,7 +17,14 @@ pub(crate) fn thir_body<'tcx>( tcx: TyCtxt<'tcx>, owner_def: LocalDefId, ) -> Result<(&'tcx Steal>, ExprId), ErrorGuaranteed> { - debug_assert!(!tcx.is_type_const(owner_def.to_def_id()), "thir_body queried for type_const"); + if cfg!(debug_assertions) + && matches!(tcx.def_kind(owner_def), DefKind::Const { .. } | DefKind::AssocConst { .. }) + { + debug_assert!( + tcx.const_of_item(owner_def.to_def_id()).is_none(), + "thir_body queried for directly represented const item: {owner_def:?}" + ); + } let body = tcx.hir_body_owned_by(owner_def); let mut cx: ThirBuildCx<'tcx> = ThirBuildCx::new(tcx, owner_def); diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 86387f5caf325..7c6885bf8020c 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -136,11 +136,18 @@ impl<'tcx> ConstToPat<'tcx> { return self.mk_err(err, ty); }; - // FIXME(gca): This will become insufficient once associated constants can be - // implemented as `type` consts (project-const-generics#76). At that point it'll - // become necessary to just use type system normalization for all const patterns - // but that's not yet possible. - let const_value = if alias_const.kind.is_type_const(self.tcx) { + // Under generic_const_args, `alias_const` might be a regular const declared in a trait, but + // is `impl`d as a directly represented const. We do not know whether it is here, so we must + // use type system normalization for all consts under generic_const_args. + // + // We probably want to always use type system normalization on stable too, but that would be + // a breaking change (in addition to needing significant improvements to diagnostics), so + // right now, we limit this to just generic_const_args. + // + // See: https://github.com/rust-lang/project-const-generics/issues/105 + let const_value = if self.tcx.features().generic_const_args() + || alias_const.kind.is_direct_const(self.tcx) + { let Ok(normalize) = self .tcx .try_normalize_erasing_regions(self.typing_env, Unnormalized::new_wip(self.c)) diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index b7813992db5bf..4ee1abe4a1ff4 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1663,7 +1663,7 @@ impl<'v> RootCollector<'_, 'v> { let def_id = id.owner_id.to_def_id(); // Type Consts don't have bodies to evaluate // nor do they make sense as a static. - if self.tcx.is_type_const(def_id) { + if self.tcx.const_of_item(def_id).is_some() { // FIXME(mgca): Is this actually what we want? We may want to // normalize to a ValTree then convert to a const allocation and // collect that? diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs index 75f15623a9ba7..cb878f2c54878 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs @@ -435,16 +435,17 @@ where } // Finally we construct the actual value of the associated type. - let term = match goal.predicate.alias.kind { + let term = match target_item_kind { ty::AliasTermKind::ProjectionTy { .. } => { let t = cx.type_of(target_item_def_id).instantiate(cx, target_args); let t = ecx.normalize(GoalSource::Misc, goal.param_env, t)?; t.into() } - ty::AliasTermKind::ProjectionConst { .. } - if cx.is_type_const(target_item_def_id) => + ty::AliasTermKind::ProjectionConst { def_id } + if let Some(c) = + cx.const_of_item(ty::AliasConstKind::Projection { def_id }) => { - let c = cx.const_of_item(target_item_def_id).instantiate(cx, target_args); + let c = c.instantiate(cx, target_args); let c = ecx.normalize(GoalSource::Misc, goal.param_env, c)?; c.into() } diff --git a/compiler/rustc_next_trait_solver/src/solve/project_goals/free_alias.rs b/compiler/rustc_next_trait_solver/src/solve/project_goals/free_alias.rs index efc630a106ee3..4481e1bc144ac 100644 --- a/compiler/rustc_next_trait_solver/src/solve/project_goals/free_alias.rs +++ b/compiler/rustc_next_trait_solver/src/solve/project_goals/free_alias.rs @@ -37,8 +37,10 @@ where let free = self.normalize(GoalSource::Misc, goal.param_env, free)?; free.into() } - ty::AliasTermKind::FreeConst { def_id } if cx.is_type_const(def_id.into()) => { - let free = cx.const_of_item(def_id.into()).instantiate(cx, free_alias.args); + ty::AliasTermKind::FreeConst { def_id } + if let Some(free) = cx.const_of_item(ty::AliasConstKind::Free { def_id }) => + { + let free = free.instantiate(cx, free_alias.args); let free = self.normalize(GoalSource::Misc, goal.param_env, free)?; free.into() diff --git a/compiler/rustc_next_trait_solver/src/solve/project_goals/inherent.rs b/compiler/rustc_next_trait_solver/src/solve/project_goals/inherent.rs index 20c0564b0eeba..d519d1e538f1a 100644 --- a/compiler/rustc_next_trait_solver/src/solve/project_goals/inherent.rs +++ b/compiler/rustc_next_trait_solver/src/solve/project_goals/inherent.rs @@ -48,8 +48,11 @@ where let inherent = self.normalize(GoalSource::Misc, goal.param_env, inherent)?; inherent.into() } - ty::AliasTermKind::InherentConstImpl { def_id } if cx.is_type_const(def_id.into()) => { - let inherent = cx.const_of_item(def_id.into()).instantiate(cx, inherent_args); + ty::AliasTermKind::InherentConstImpl { def_id } + if let Some(inherent) = + cx.const_of_item(ty::AliasConstKind::InherentImpl { def_id }) => + { + let inherent = inherent.instantiate(cx, inherent_args); let normalized_ct = self.normalize(GoalSource::Misc, goal.param_env, inherent)?; let normalized = normalized_ct.into(); let term = ty::AliasTerm::new_from_args(cx, inherent_kind, inherent_args); diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 0f49e3c02873d..b2ad898311cc3 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -442,7 +442,7 @@ impl<'a> Parser<'a> { }) .unwrap() .node; - Ok(attr_item.meta(attr_item.path.span).unwrap()) + Ok(attr_item.meta(attr_item.span).unwrap()) } else { self.unexpected_any() }; diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 46fd2445d7c55..b252a378722f3 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2702,7 +2702,12 @@ impl<'a> Parser<'a> { let mut foralls = ThinVec::new(); let mut exists = ThinVec::new(); let mut constraints = Vec::new(); + let mut predicates = Vec::new(); self.parse_delim_comma_seq(exp!(OpenBrace), exp!(CloseBrace), |this| { + if this.check_keyword(exp!(Where)) { + predicates.push(this.parse_where_clause()?); + return Ok(()); + } match this.token.ident() { Some((Ident { name: sym::forall, .. }, IdentIsRaw::No)) => { foralls.push(this.parse_test_binder_forall()?) @@ -2710,11 +2715,12 @@ impl<'a> Parser<'a> { Some((Ident { name: sym::exists, .. }, IdentIsRaw::No)) => { exists.push(this.parse_test_binder_exists()?) } + _ => constraints.push(this.parse_test_binder_constraint()?), } Ok(()) })?; - Ok(TestBinderBody { foralls, exists, constraints }) + Ok(TestBinderBody { foralls, exists, constraints, predicates }) } pub fn parse_test_binder_forall(&mut self) -> PResult<'a, TestBinderForall> { @@ -2771,6 +2777,10 @@ impl<'a> Parser<'a> { .0; Ok(TestBinderConstraint::Or { items }) } + _ if self.check_keyword(exp!(For)) => { + let bound_type_constraint = self.parse_test_binder_bound_type_constraint()?; + Ok(TestBinderConstraint::AliasOutlives { bound_type_constraint }) + } _ if self.token.lifetime().is_some() => { let lhs = self.expect_lifetime(); self.expect(exp!(Colon))?; @@ -2787,12 +2797,54 @@ impl<'a> Parser<'a> { self.unexpected()?; } let rhs = self.expect_lifetime(); - Ok(TestBinderConstraint::Type { lhs, rhs }) + Ok(TestBinderConstraint::PlaceholderOutlives { lhs, rhs }) } _ => Err(self.dcx().struct_span_err(self.token.span, "unexpected token")), } } + fn parse_test_binder_bound_type_constraint( + &mut self, + ) -> PResult<'a, TestBinderBoundTypeConstraint> { + let lo = self.token.span; + let ast::WhereBoundPredicate { bound_generic_params, bounded_ty, bounds } = + self.parse_ty_where_predicate_kind()?; + let mut rhs = None; + for bound in bounds { + match bound { + GenericBound::Trait(poly_trait_ref) => { + self.dcx().span_err(poly_trait_ref.span, "trait bounds aren't supported here"); + } + GenericBound::Use(_, span) => { + self.dcx().span_err(span, "use bounds aren't supported here"); + } + GenericBound::Outlives(lifetime) => { + if rhs.is_some() { + self.dcx().span_err( + lifetime.ident.span, + "only one lifetime on the rhs supported", + ); + } else { + rhs = Some(lifetime); + } + } + } + } + match rhs { + Some(rhs) => Ok(TestBinderBoundTypeConstraint { + span: lo.to(self.prev_token.span), + node_id: DUMMY_NODE_ID, + params: bound_generic_params, + lhs: bounded_ty, + rhs, + }), + None => Err(self.dcx().struct_span_err( + bounded_ty.span, + "expected a single lifetime on the rhs of this constraint", + )), + } + } + fn report_invalid_macro_expansion_item(&self, args: &DelimArgs, path: Option<&Path>) { let span = args.dspan.entire(); let mut err = self.dcx().struct_span_err( diff --git a/compiler/rustc_passes/src/diagnostics.rs b/compiler/rustc_passes/src/diagnostics.rs index c343d9c7078e7..5f99c4b133597 100644 --- a/compiler/rustc_passes/src/diagnostics.rs +++ b/compiler/rustc_passes/src/diagnostics.rs @@ -6,7 +6,8 @@ use rustc_errors::{ Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee, Level, MultiSpan, msg, }; use rustc_macros::{Diagnostic, Subdiagnostic}; -use rustc_middle::ty::{MainDefinition, Ty}; +use rustc_middle::middle::resolve::MainDefinition; +use rustc_middle::ty::Ty; use rustc_span::{DUMMY_SP, Ident, Span, Symbol}; use crate::check_attr::ProcMacroKind; @@ -1164,3 +1165,20 @@ pub(crate) struct ConstFnLinkage { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag("use of deprecated import through accidentally stabilized module `{$module}`")] +pub(crate) struct RustcAtumSuggestion { + #[primary_span] + pub import_span: Span, + pub message: Symbol, + pub suggestion: Symbol, + pub module: Ident, + #[suggestion( + "{$message}", + code = "{suggestion}", + style = "verbose", + applicability = "machine-applicable" + )] + pub unstable_mod_span: Span, +} diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index ddf8bbf764e6e..68be74886a2e4 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -13,8 +13,9 @@ use rustc_crate_store::ExternCrate; use rustc_hir::Target; use rustc_hir::attrs::lang_items::{GenericRequirement, LangItem, LanguageItems}; use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_middle::middle::resolve::ResolverAstLowering; use rustc_middle::query::Providers; -use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; +use rustc_middle::ty::TyCtxt; use rustc_span::{Span, Symbol, sym}; use crate::diagnostics::{DuplicateLangItem, IncorrectCrateType, IncorrectTarget}; diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index e5f5b67912c75..de0d0a4f8a4f2 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -209,7 +209,7 @@ impl<'tcx> ReachableContext<'tcx> { } } // For `type const` we want to evaluate the RHS. - hir::ItemKind::Const(_, _, _, init @ hir::ConstItemRhs::TypeConst(_)) => { + hir::ItemKind::Const(_, _, _, init @ hir::ConstItemRhs::Direct(_)) => { self.visit_const_item_rhs(init); } hir::ItemKind::Const(_, _, _, init) => { diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 7404b466f1d54..23cc86ae6ae61 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -16,16 +16,15 @@ use rustc_hir::{ ItemKind, Path, Stability, StabilityLevel, StableSince, TraitRef, Ty, TyKind, UnstableReason, UsePath, VERSION_PLACEHOLDER, Variant, find_attr, }; -use rustc_lint_defs as lint; use rustc_lint_defs::builtin::{ DEPRECATED, DUPLICATE_FEATURES, INEFFECTIVE_UNSTABLE_TRAIT_IMPL, STABLE_FEATURES, }; use rustc_middle::hir::nested_filter; use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures}; use rustc_middle::middle::privacy::EffectiveVisibilities; -use rustc_middle::middle::stability::{AllowUnstable, Deprecated, DeprecationEntry, EvalResult}; +use rustc_middle::middle::stability::{AllowUnstable, DeprecationEntry, EvalResult}; use rustc_middle::query::{LocalCrate, Providers}; -use rustc_middle::ty::print::with_no_trimmed_paths; +use rustc_middle::span_bug; use rustc_middle::ty::{AssocContainer, TyCtxt}; use rustc_span::{Span, Symbol, sym}; use tracing::instrument; @@ -790,7 +789,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { if item_is_allowed { // The item itself is allowed; check whether the path there is also allowed. - let is_allowed_through_unstable_modules: Option = + let is_allowed_through_unstable_modules: Option<(Symbol, Symbol)> = self.tcx.lookup_stability(def_id).and_then(|stab| match stab.level { StabilityLevel::Stable { allowed_through_unstable_modules, .. } => { allowed_through_unstable_modules @@ -829,7 +828,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { }, ); } - Some(deprecation) => { + Some((message, suggestion)) => { // Call the stability check directly so that we can control which // diagnostic is emitted. let eval_result = self.tcx.eval_stability_allow_unstable( @@ -845,22 +844,19 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { ); let is_allowed = matches!(eval_result, EvalResult::Allow); if !is_allowed { - // Calculating message for lint involves calling `self.def_path_str`, - // which will by default invoke the expensive `visible_parent_map` query. - // Skip all that work if the lint is allowed anyway. - if self.tcx.lint_level_spec_at_node(DEPRECATED, id).is_allow() { - return; - } // Show a deprecation message. - let def_path = - with_no_trimmed_paths!(self.tcx.def_path_str(def_id)); - let def_kind = self.tcx.def_descr(def_id); - let diag = Deprecated { - sub: None, - kind: def_kind.to_owned(), - path: def_path, - note: Some(deprecation), - since_kind: lint::DeprecatedSinceKind::InEffect, + let [.., intrinsics_module, _intrinsic] = path.segments else { + span_bug!( + path.span, + "no module for `is_allowed_through_unstable_modules` intrinsic {path:?}" + ) + }; + let diag = diagnostics::RustcAtumSuggestion { + message, + import_span: path.span, + unstable_mod_span: { intrinsics_module.ident.span }, + module: intrinsics_module.ident, + suggestion, }; self.tcx.emit_node_span_lint( DEPRECATED, diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 5fa4db74cb279..88f057c3a6d6d 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -23,7 +23,7 @@ use rustc_hir::def::{self, *}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_index::bit_set::DenseBitSet; use rustc_metadata::creader::LoadedMacro; -use rustc_middle::metadata::{ModChild, Reexport}; +use rustc_middle::middle::resolve::{ModChild, PartialRes, Reexport}; use rustc_middle::ty::{TyCtxtFeed, Visibility}; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::{CRATE_MOD_ID, ModId}; diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 29b1773ddc5ca..4c8000c28f065 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -10,8 +10,9 @@ use rustc_hir::Target; use rustc_hir::def::DefKind; use rustc_hir::def::Namespace::{TypeNS, ValueNS}; use rustc_hir::def_id::LocalDefId; +use rustc_middle::middle::resolve::PerOwnerResolverData; use rustc_middle::span_bug; -use rustc_middle::ty::{PerOwnerResolverData, TyCtxtFeed}; +use rustc_middle::ty::TyCtxtFeed; use rustc_span::{Span, Symbol, sym}; use tracing::{debug, instrument}; diff --git a/compiler/rustc_resolve/src/diagnostics/impls.rs b/compiler/rustc_resolve/src/diagnostics/impls.rs index 9a84985bed51a..a005824e5dbfa 100644 --- a/compiler/rustc_resolve/src/diagnostics/impls.rs +++ b/compiler/rustc_resolve/src/diagnostics/impls.rs @@ -50,7 +50,7 @@ use crate::diagnostics::{ }; use crate::hygiene::Macros20NormalizedSyntaxContext; use crate::imports::{Import, ImportKind, UnresolvedImportError, import_path_to_string}; -use crate::late::{DiagMetadata, PatternSource, Rib}; +use crate::late::{ConstantRequiresType, DiagMetadata, PatternSource, Rib}; use crate::{ AmbiguityError, AmbiguityKind, AmbiguityWarning, BindingError, BindingKey, Decl, DeclKind, DelayedVisResolutionError, Finalize, ForwardGenericParamBanReason, HasGenericParams, IdentKey, @@ -1188,6 +1188,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { suggestion, current, type_span, + requires_type, } => { // let foo =... // ^^^ given this Span @@ -1224,11 +1225,23 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if is_simple_binding { ( - Some(diagnostics::AttemptToUseNonConstantValueInConstantWithSuggestion { - span: sp, - suggestion, - current, - type_span, + Some(match requires_type { + ConstantRequiresType::Usize => { + diagnostics::AttemptToUseNonConstantValueInConstantWithSuggestion::Usize { + span: sp, + suggestion, + current, + type_span, + } + } + ConstantRequiresType::No => { + diagnostics::AttemptToUseNonConstantValueInConstantWithSuggestion::Placeholder { + span: sp, + suggestion, + current, + type_span, + } + } }), Some(diagnostics::AttemptToUseNonConstantValueInConstantLabelWithSuggestion { span }), None, diff --git a/compiler/rustc_resolve/src/diagnostics/mod.rs b/compiler/rustc_resolve/src/diagnostics/mod.rs index 624f180361f5b..dfa58ab73778f 100644 --- a/compiler/rustc_resolve/src/diagnostics/mod.rs +++ b/compiler/rustc_resolve/src/diagnostics/mod.rs @@ -288,19 +288,33 @@ pub(crate) struct AttemptToUseNonConstantValueInConstant<'a> { } #[derive(Subdiagnostic)] -#[multipart_suggestion( - "consider using `{$suggestion}` instead of `{$current}`", - style = "verbose", - applicability = "has-placeholders" -)] -pub(crate) struct AttemptToUseNonConstantValueInConstantWithSuggestion<'a> { - // #[primary_span] - #[suggestion_part(code = "{suggestion} ")] - pub(crate) span: Span, - pub(crate) suggestion: &'a str, - #[suggestion_part(code = ": /* Type */")] - pub(crate) type_span: Option, - pub(crate) current: &'a str, +pub(crate) enum AttemptToUseNonConstantValueInConstantWithSuggestion<'a> { + #[multipart_suggestion( + "consider using `{$suggestion}` instead of `{$current}`", + style = "verbose", + applicability = "has-placeholders" + )] + Placeholder { + #[suggestion_part(code = "{suggestion} ")] + span: Span, + suggestion: &'a str, + #[suggestion_part(code = ": /* Type */")] + type_span: Option, + current: &'a str, + }, + #[multipart_suggestion( + "consider using `{$suggestion}` instead of `{$current}`", + style = "verbose", + applicability = "machine-applicable" + )] + Usize { + #[suggestion_part(code = "{suggestion} ")] + span: Span, + suggestion: &'a str, + #[suggestion_part(code = ": usize")] + type_span: Option, + current: &'a str, + }, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index ebcdb8603eccd..c1b3c6cd5eeba 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -4,8 +4,9 @@ use Determinacy::*; use Namespace::*; use rustc_ast::{self as ast, NodeId}; use rustc_errors::ErrorGuaranteed; -use rustc_hir::def::{DefKind, MacroKinds, Namespace, NonMacroAttrKind, PartialRes, PerNS}; +use rustc_hir::def::{DefKind, MacroKinds, Namespace, NonMacroAttrKind, PerNS}; use rustc_lint_defs::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK; +use rustc_middle::middle::resolve::PartialRes; use rustc_middle::{bug, span_bug}; use rustc_session::diagnostics::feature_err; use rustc_span::edition::Edition; @@ -1512,7 +1513,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { res_err = Some((span, CannotCaptureDynamicEnvironmentInFnItem)); } } - RibKind::ConstantItem(_, item) => { + RibKind::ConstantItem(_, item, requires_type) => { // Still doesn't deal with upvars if let Some(span) = finalize { let (span, resolution_error) = match item { @@ -1541,6 +1542,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { suggestion: "const", current: "let", type_span, + requires_type, }, ) } @@ -1551,6 +1553,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { suggestion: "let", current: kind.as_str(), type_span: None, + requires_type, }, ), }; @@ -1621,7 +1624,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } - RibKind::ConstantItem(trivial, _) => { + RibKind::ConstantItem(trivial, _, _) => { if let ConstantHasGenerics::No(cause) = trivial && !matches!(res, Res::SelfTyAlias { .. }) { @@ -1715,7 +1718,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } - RibKind::ConstantItem(trivial, _) => { + RibKind::ConstantItem(trivial, _, _) => { if let ConstantHasGenerics::No(cause) = trivial { if let Some(span) = finalize { let error = match cause { diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 388073971171b..1cda9b9139028 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -8,14 +8,14 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_data_structures::intern::Interned; use rustc_errors::{Applicability, BufferedEarlyLint, Diagnostic}; use rustc_expand::base::SyntaxExtensionKind; -use rustc_hir::def::{self, DefKind, PartialRes}; +use rustc_hir::def::{self, DefKind}; use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap}; use rustc_lint_defs::LintId; use rustc_lint_defs::builtin::{ AMBIGUOUS_GLOB_REEXPORTS, EXPORTED_PRIVATE_DEPENDENCIES, HIDDEN_GLOB_REEXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE, REDUNDANT_IMPORTS, UNUSED_IMPORTS, }; -use rustc_middle::metadata::{AmbigModChild, ModChild, Reexport}; +use rustc_middle::middle::resolve::{AmbigModChild, ModChild, PartialRes, Reexport}; use rustc_middle::span_bug; use rustc_middle::ty::Visibility; use rustc_session::diagnostics::feature_err; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 396db754f7c96..2966e3ad24a07 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -25,12 +25,13 @@ use rustc_errors::{ StashKey, Suggestions, elided_lifetime_in_path_suggestion, pluralize, }; use rustc_hir::def::Namespace::{self, *}; -use rustc_hir::def::{CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS}; +use rustc_hir::def::{CtorKind, DefKind, NonMacroAttrKind, PerNS}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::{MissingLifetimeKind, PrimTy}; use rustc_lint_defs::builtin::{ELIDED_LIFETIMES_IN_PATHS, UNUSED_LABELS}; +use rustc_middle::middle::resolve::{DelegationInfo, LifetimeRes, PartialRes}; use rustc_middle::middle::resolve_bound_vars::Set1; -use rustc_middle::ty::{AssocTag, DelegationInfo, Visibility}; +use rustc_middle::ty::{AssocTag, Visibility}; use rustc_middle::{bug, span_bug}; use rustc_session::config::ResolveDocLinks; use rustc_session::diagnostics::feature_err; @@ -80,6 +81,7 @@ enum AnonConstKind { FieldDefaultValue, InlineConst, ConstArg(IsRepeatExpr), + ArrayLength, } impl PatternSource { @@ -137,6 +139,13 @@ pub(crate) enum ConstantHasGenerics { No(NoConstantGenericsReason), } +/// Does this constant requires an specific type? +#[derive(Copy, Clone, Debug)] +pub(crate) enum ConstantRequiresType { + Usize, + No, +} + impl ConstantHasGenerics { fn force_yes_if(self, b: bool) -> Self { if b { Self::Yes } else { self } @@ -215,7 +224,9 @@ pub(crate) enum RibKind<'ra> { /// /// The item may reference generic parameters in trivial constant expressions. /// All other constants aren't allowed to use generic params at all. - ConstantItem(ConstantHasGenerics, Option<(Ident, ConstantItemKind)>), + /// + /// If the constant comes from specific contexts (like array length) it might require an specific type. + ConstantItem(ConstantHasGenerics, Option<(Ident, ConstantItemKind)>, ConstantRequiresType), /// We passed through a module item. Module(LocalModule<'ra>), @@ -1023,7 +1034,7 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc } TyKind::Array(element_ty, length) => { self.visit_ty(element_ty); - self.resolve_anon_const(length, AnonConstKind::ConstArg(IsRepeatExpr::No)); + self.resolve_anon_const(length, AnonConstKind::ArrayLength); } TyKind::DirectConstArg(expr) => self.resolve_anon_const_manual( true, @@ -1521,6 +1532,20 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc |this| visit::walk_test_binder_exists(this, exists), ); } + + fn visit_test_binder_bound_type_constraint( + &mut self, + bound_type: &'ast TestBinderBoundTypeConstraint, + ) { + self.with_generic_param_rib( + &bound_type.params, + RibKind::Normal, + bound_type.node_id, + LifetimeBinderKind::WhereBound, + bound_type.lhs.span.to(bound_type.rhs.ident.span), + |this| visit::walk_test_binder_bound_type_constraint(this, bound_type), + ); + } } impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { @@ -3028,6 +3053,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { this.with_constant_rib( IsRepeatExpr::No, ConstantHasGenerics::Yes, + ConstantRequiresType::No, Some((ConstBlockItem::IDENT, ConstantItemKind::Const)), |this| this.resolve_labeled_block(None, block.id, block), ) @@ -3306,22 +3332,31 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { &mut self, is_repeat: IsRepeatExpr, may_use_generics: ConstantHasGenerics, + requires_type: ConstantRequiresType, item: Option<(Ident, ConstantItemKind)>, f: impl FnOnce(&mut Self), ) { let f = |this: &mut Self| { - this.with_rib(ValueNS, RibKind::ConstantItem(may_use_generics, item), |this| { - this.with_rib( - TypeNS, - RibKind::ConstantItem( - may_use_generics.force_yes_if(is_repeat == IsRepeatExpr::Yes), - item, - ), - |this| { - this.with_label_rib(RibKind::ConstantItem(may_use_generics, item), f); - }, - ) - }) + this.with_rib( + ValueNS, + RibKind::ConstantItem(may_use_generics, item, requires_type), + |this| { + this.with_rib( + TypeNS, + RibKind::ConstantItem( + may_use_generics.force_yes_if(is_repeat == IsRepeatExpr::Yes), + item, + requires_type, + ), + |this| { + this.with_label_rib( + RibKind::ConstantItem(may_use_generics, item, requires_type), + f, + ); + }, + ) + }, + ) }; if let ConstantHasGenerics::No(cause) = may_use_generics { @@ -3898,9 +3933,13 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { fn resolve_static_body(&mut self, expr: &'ast Expr, item: Option<(Ident, ConstantItemKind)>) { self.with_lifetime_rib(LifetimeRibKind::elided(LifetimeRes::Infer), |this| { - this.with_constant_rib(IsRepeatExpr::No, ConstantHasGenerics::Yes, item, |this| { - this.visit_expr(expr) - }); + this.with_constant_rib( + IsRepeatExpr::No, + ConstantHasGenerics::Yes, + ConstantRequiresType::No, + item, + |this| this.visit_expr(expr), + ); }) } @@ -3911,9 +3950,13 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ) { if let Some(body) = body { self.with_lifetime_rib(LifetimeRibKind::elided(LifetimeRes::Infer), |this| { - this.with_constant_rib(IsRepeatExpr::No, ConstantHasGenerics::Yes, item, |this| { - this.visit_expr(body) - }) + this.with_constant_rib( + IsRepeatExpr::No, + ConstantHasGenerics::Yes, + ConstantRequiresType::No, + item, + |this| this.visit_expr(body), + ) }) } } @@ -5177,7 +5220,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } AnonConstKind::FieldDefaultValue => ConstantHasGenerics::Yes, AnonConstKind::InlineConst => ConstantHasGenerics::Yes, - AnonConstKind::ConstArg(_) => { + AnonConstKind::ConstArg(_) | AnonConstKind::ArrayLength => { if self.r.features.generic_const_exprs() || self.r.features.min_generic_const_args() || is_trivial_const_arg @@ -5189,7 +5232,14 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } }; - self.with_constant_rib(is_repeat_expr, may_use_generics, None, |this| { + let requires_type = match anon_const_kind { + AnonConstKind::ArrayLength | AnonConstKind::ConstArg(IsRepeatExpr::Yes) => { + ConstantRequiresType::Usize + } + _ => ConstantRequiresType::No, + }; + + self.with_constant_rib(is_repeat_expr, may_use_generics, requires_type, None, |this| { this.with_lifetime_rib(LifetimeRibKind::elided(LifetimeRes::Infer), |this| { resolve_expr(this); }); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index f5e684cb81631..d5b1457865891 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -32,8 +32,8 @@ use effective_visibilities::EffectiveVisibilitiesVisitor; use hygiene::Macros20NormalizedSyntaxContext; use imports::{Import, ImportData, ImportKind, NameResolution, PendingDecl}; use late::{ - ForwardGenericParamBanReason, HasGenericParams, PathSource, PatternSource, - UnnecessaryQualification, + ConstantRequiresType, ForwardGenericParamBanReason, HasGenericParams, PathSource, + PatternSource, UnnecessaryQualification, }; pub use macros::registered_lint_tools_ast; use macros::{MacroRulesDecl, MacroRulesScope, MacroRulesScopeRef}; @@ -53,22 +53,20 @@ use rustc_expand::base::{DeriveResolution, SyntaxExtension, SyntaxExtensionKind} use rustc_feature::{BUILTIN_ATTRIBUTES, Features}; use rustc_hir::attrs::StrippedCfgItem; use rustc_hir::def::Namespace::{self, *}; -use rustc_hir::def::{ - self, CtorOf, DefKind, DocLinkResMap, MacroKinds, NonMacroAttrKind, PartialRes, PerNS, -}; +use rustc_hir::def::{self, CtorOf, DefKind, MacroKinds, NonMacroAttrKind, PerNS}; use rustc_hir::def_id::{CRATE_DEF_ID, CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap}; use rustc_hir::definitions::{PerParentDisambiguatorState, PerParentDisambiguatorsMap}; use rustc_hir::{PrimTy, TraitCandidate, find_attr}; use rustc_index::bit_set::DenseBitSet; use rustc_lint_defs::builtin::PRIVATE_MACRO_USE; use rustc_metadata::creader::CStore; -use rustc_middle::metadata::{AmbigModChild, ModChild, Reexport}; use rustc_middle::middle::privacy::EffectiveVisibilities; -use rustc_middle::query::Providers; -use rustc_middle::ty::{ - self, DelegationInfo, MainDefinition, PerOwnerResolverData, RegisteredTools, - ResolverAstLowering, ResolverGlobalCtxt, TyCtxt, TyCtxtFeed, Visibility, +use rustc_middle::middle::resolve::{ + AmbigModChild, DelegationInfo, DocLinkResMap, MainDefinition, ModChild, PartialRes, + PerOwnerResolverData, Reexport, ResolverAstLowering, ResolverGlobalCtxt, }; +use rustc_middle::query::Providers; +use rustc_middle::ty::{self, RegisteredTools, TyCtxt, TyCtxtFeed, Visibility}; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::{LocalModId, ModId}; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency}; @@ -284,6 +282,7 @@ enum ResolutionError<'ra> { suggestion: &'static str, current: &'static str, type_span: Option, + requires_type: ConstantRequiresType, }, /// Error E0530: `X` bindings cannot shadow `Y`s. BindingShadowsSomethingUnacceptable { @@ -1993,7 +1992,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { stripped_cfg_items, delegation_infos: self.delegation_infos, }; - let ast_lowering = ty::ResolverAstLowering { + let ast_lowering = ResolverAstLowering { partial_res_map: self.partial_res_map, next_node_id: self.next_node_id, owners: self.owners, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 71333dfdaff87..8fd9c4da967dc 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -94,13 +94,15 @@ mod target_modifier_consistency_check { l: &TargetModifier, r: Option<&TargetModifier>, ) -> bool { - let mut lparsed: SanitizerSet = sess.target.options.default_sanitizers; + let mut lparsed: SanitizerSet = SanitizerSet::empty(); let lval = if l.value_name.is_empty() { None } else { Some(l.value_name.as_str()) }; parse::parse_sanitizers(&mut lparsed, lval); + let lparsed = lparsed.combine_with_defaults(sess.target.options.default_sanitizers); - let mut rparsed: SanitizerSet = sess.target.options.default_sanitizers; + let mut rparsed: SanitizerSet = SanitizerSet::empty(); let rval = r.filter(|v| !v.value_name.is_empty()).map(|v| v.value_name.as_str()); parse::parse_sanitizers(&mut rparsed, rval); + let rparsed = rparsed.combine_with_defaults(sess.target.options.default_sanitizers); // Some sanitizers need to be target modifiers, and some do not. // For now, we should mark all sanitizers as target modifiers except for these: diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index f04f40dd17168..87190e232c693 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -95,6 +95,7 @@ pub enum PointerAuthARM8_3Key { } /// Forms of extra discrimination. +#[derive(Clone, Debug, PartialEq)] pub enum PointerAuthDiscrimination { /// No additional discrimination. None, @@ -107,6 +108,7 @@ pub enum PointerAuthDiscrimination { } /// Types of address discrimination. +#[derive(Clone, Debug)] pub enum PointerAuthAddressDiscriminator { /// Enable/disable hardware address discrimination. HardwareAddress(bool), @@ -115,6 +117,7 @@ pub enum PointerAuthAddressDiscriminator { Synthetic(u64), } +#[derive(Clone, Debug)] pub struct PointerAuthSchema { pub is_address_discriminated: PointerAuthAddressDiscriminator, pub discrimination_kind: PointerAuthDiscrimination, @@ -929,7 +932,7 @@ impl Session { let more_names = self.opts.output_types.contains_key(&OutputType::LlvmAssembly) || self.opts.output_types.contains_key(&OutputType::Bitcode) // AddressSanitizer and MemorySanitizer use alloca name when reporting an issue. - || self.opts.unstable_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::MEMORY); + || self.sanitizers().intersects(SanitizerSet::ADDRESS | SanitizerSet::MEMORY); !more_names } } @@ -1178,19 +1181,36 @@ impl Session { } pub fn sanitizers(&self) -> SanitizerSet { - return self.opts.unstable_opts.sanitizer | self.target.options.default_sanitizers; + self.opts + .unstable_opts + .sanitizer + .combine_with_defaults(self.target.options.default_sanitizers) } pub fn pointer_authentication(&self) -> bool { self.pointer_auth_config.is_some() } - pub fn pointer_authentication_functions(&self) -> Option<&PointerAuthSchema> { - self.pointer_auth_config.as_ref().and_then(|cfg| cfg.function_pointers.as_ref()) + pub fn pointer_authentication_functions(&self) -> Option { + self.pointer_auth_config.as_ref().and_then(|cfg| cfg.function_pointers.clone()) + } + + pub fn pointer_authentication_init_fini(&self) -> Option { + self.pointer_auth_config.as_ref().and_then(|cfg| cfg.init_fini.clone()) } - pub fn pointer_authentication_init_fini(&self) -> Option<&PointerAuthSchema> { - self.pointer_auth_config.as_ref().and_then(|cfg| cfg.init_fini.as_ref()) + pub fn pointer_authentication_fn_ptr_type_discrimination(&self) -> bool { + self.pointer_auth_config + .as_ref() + .and_then(|cfg| cfg.function_pointers.as_ref()) + .is_some_and(|schema| schema.discrimination_kind == PointerAuthDiscrimination::Type) + } + + pub fn pointer_authentication_fn_ptr_key(&self) -> Option { + self.pointer_auth_config + .as_ref() + .and_then(|cfg| cfg.function_pointers.as_ref()) + .map(|schema| schema.key) } } @@ -1497,7 +1517,7 @@ fn validate_commandline_args_with_session_available(sess: &Session) { // Sanitizers can only be used on platforms that we know have working sanitizer codegen. let supported_sanitizers = sess.target.options.supported_sanitizers; - let mut unsupported_sanitizers = sess.opts.unstable_opts.sanitizer - supported_sanitizers; + let mut unsupported_sanitizers = sess.sanitizers() - supported_sanitizers; // Niche: if `fixed-x18`, or effectively switching on `reserved-x18` flag, is enabled // we should allow Shadow Call Stack sanitizer. if sess.opts.unstable_opts.fixed_x18 && sess.target.arch == Arch::AArch64 { @@ -1518,7 +1538,7 @@ fn validate_commandline_args_with_session_available(sess: &Session) { } // Cannot mix and match mutually-exclusive sanitizers. - if let Some((first, second)) = sess.opts.unstable_opts.sanitizer.mutually_exclusive() { + if let Some((first, second)) = sess.sanitizers().mutually_exclusive() { sess.dcx().emit_err(diagnostics::CannotMixAndMatchSanitizers { first: first.to_string(), second: second.to_string(), @@ -1526,10 +1546,7 @@ fn validate_commandline_args_with_session_available(sess: &Session) { } // Cannot enable crt-static with sanitizers on Linux - if sess.crt_static(None) - && !sess.opts.unstable_opts.sanitizer.is_empty() - && !sess.target.is_like_msvc - { + if sess.crt_static(None) && !sess.sanitizers().is_empty() && !sess.target.is_like_msvc { sess.dcx().emit_err(diagnostics::CannotEnableCrtStaticLinux); } diff --git a/compiler/rustc_structures/src/lib.rs b/compiler/rustc_structures/src/lib.rs index a7ebea5ba9943..cb5dccdfcd180 100644 --- a/compiler/rustc_structures/src/lib.rs +++ b/compiler/rustc_structures/src/lib.rs @@ -13,3 +13,6 @@ pub use crate_type::CrateType; pub use limit::Limit; pub use native_lib_kind::NativeLibKind; pub use sanitizer_set::SanitizerSet; + +#[cfg(test)] +mod tests; diff --git a/compiler/rustc_structures/src/sanitizer_set.rs b/compiler/rustc_structures/src/sanitizer_set.rs index bce77f3abc05b..a41577441de8c 100644 --- a/compiler/rustc_structures/src/sanitizer_set.rs +++ b/compiler/rustc_structures/src/sanitizer_set.rs @@ -95,6 +95,20 @@ impl SanitizerSet { .find(|&(a, b)| self.contains(*a) && self.contains(*b)) .copied() } + + /// Disable default sanitizers that are incompatible with explicitly requested ones, + /// matching Clang's `SanitizerArgs` driver logic. + pub fn combine_with_defaults(self, mut defaults: SanitizerSet) -> SanitizerSet { + for &(a, b) in Self::MUTUALLY_EXCLUSIVE { + if defaults.contains(a) && self.contains(b) { + defaults -= a; + } + if defaults.contains(b) && self.contains(a) { + defaults -= b; + } + } + self | defaults + } } /// Formats a sanitizer set as a comma separated list of sanitizers' names. diff --git a/compiler/rustc_structures/src/tests.rs b/compiler/rustc_structures/src/tests.rs new file mode 100644 index 0000000000000..3d61d5bf3331f --- /dev/null +++ b/compiler/rustc_structures/src/tests.rs @@ -0,0 +1,36 @@ +use super::*; + +#[test] +fn test_combine_with_defaults_no_conflict() { + let defaults = SanitizerSet::SHADOWCALLSTACK; + let explicit = SanitizerSet::ADDRESS; + assert_eq!( + explicit.combine_with_defaults(defaults), + SanitizerSet::ADDRESS | SanitizerSet::SHADOWCALLSTACK + ); +} + +#[test] +fn test_combine_with_defaults_safestack_address_conflict() { + let defaults = SanitizerSet::SAFESTACK; + let explicit = SanitizerSet::ADDRESS; + // SafeStack should be implicitly disabled when Address is explicitly provided. + assert_eq!(explicit.combine_with_defaults(defaults), SanitizerSet::ADDRESS); +} + +#[test] +fn test_combine_with_defaults_empty_explicit() { + let defaults = SanitizerSet::SAFESTACK; + let explicit = SanitizerSet::empty(); + assert_eq!(explicit.combine_with_defaults(defaults), SanitizerSet::SAFESTACK); +} + +#[test] +fn test_combine_with_defaults_safestack_cfi() { + let defaults = SanitizerSet::SAFESTACK; + let explicit = SanitizerSet::CFI; + assert_eq!( + explicit.combine_with_defaults(defaults), + SanitizerSet::CFI | SanitizerSet::SAFESTACK + ); +} diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index 26fedbd8a5481..14ad0eb477d5d 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -625,12 +625,15 @@ pub struct FnAbi<'a, Ty> { pub conv: CanonAbi, /// Indicates if an unwind may happen across a call to this function. pub can_unwind: bool, + /// Computed type discriminator for pointer authentication purpose. + pub ptrauth_discriminator: Option, } // Needs to be a custom impl because of the bounds on the `TyAndLayout` debug impl. impl<'a, Ty: fmt::Display> fmt::Debug for FnAbi<'a, Ty> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let FnAbi { args, ret, c_variadic, fixed_count, conv, can_unwind } = self; + let FnAbi { args, ret, c_variadic, fixed_count, conv, can_unwind, ptrauth_discriminator } = + self; f.debug_struct("FnAbi") .field("args", args) .field("ret", ret) @@ -638,6 +641,7 @@ impl<'a, Ty: fmt::Display> fmt::Debug for FnAbi<'a, Ty> { .field("fixed_count", fixed_count) .field("conv", conv) .field("can_unwind", can_unwind) + .field("ptrauth_discriminator", ptrauth_discriminator) .finish() } } @@ -950,6 +954,6 @@ mod size_asserts { use super::*; // tidy-alphabetical-start static_assert_size!(ArgAbi<'_, usize>, 56); - static_assert_size!(FnAbi<'_, usize>, 80); + static_assert_size!(FnAbi<'_, usize>, 96); // tidy-alphabetical-end } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index a1c8fd304cd94..0f192379ce7fc 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1615,6 +1615,7 @@ supported_targets! { ("armv7a-kmc-solid_asp3-eabi", armv7a_kmc_solid_asp3_eabi), ("armv7a-kmc-solid_asp3-eabihf", armv7a_kmc_solid_asp3_eabihf), + ("powerpc64-sony-ps3", powerpc64_sony_ps3), ("mipsel-sony-psp", mipsel_sony_psp), ("mipsel-sony-psx", mipsel_sony_psx), ("mipsel-unknown-none", mipsel_unknown_none), @@ -1862,6 +1863,7 @@ crate::target_spec_enum! { Nto = "nto", NuttX = "nuttx", OpenBsd = "openbsd", + Ps3 = "ps3", Psp = "psp", Psx = "psx", Qnx = "qnx", diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_sony_ps3.rs b/compiler/rustc_target/src/spec/targets/powerpc64_sony_ps3.rs new file mode 100644 index 0000000000000..41c8b3b206395 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/powerpc64_sony_ps3.rs @@ -0,0 +1,107 @@ +use crate::spec::{ + Arch, Cc, CfgAbi, CodeModel, Endian, FramePointer, LinkerFlavor, Lld, LlvmAbi, Os, + PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions, +}; + +pub(crate) fn target() -> Target { + let pre_link_args = TargetOptions::link_args( + LinkerFlavor::Gnu(Cc::No, Lld::No), + &[ + // We strictly need ELFv1 PPC64. + "-m", + "elf64ppc", + // PS3 LV2 reserves the first 64KB page for unmapped memory protection. + "--image-base=0x10000", + // Should be default, but relying on automatic behavior appears to be brittle. + "-e", + "_start", + // CellOS expects .rodata to be merged into the executable Text segment (RX) + // so there are only 2 loadable segments (RX and RW) + "--no-rosegment", + // CellOS uses 64 KB memory pages. Without this flag, `mold` might align data segments to 4 KB boundaries. + "-z", + "separate-loadable-segments", + // Prevents mold from creating a `PT_GNU_RELRO` segment that GameOS does not support. + "-z", + "norelro", + // CellOS's loader doesn't behave like `ld`. PRXs are stubbed in the binary already. + "-Bstatic", + // The following are segments that might never be referenced by the code, + // but are expected to exist by the PS3's loader. + "-u", + "sys_process_param", + "-u", + "sys_proc_prx_param", + "--undefined-glob=*_prx_header", + "--undefined-glob=*_fnid_table", + "--undefined-glob=*_name", + "--undefined-glob=*_fstub_table", + ], + ); + + Target { + // LLVM will default to a compatible ELF backend. + llvm_target: "powerpc64-sony-ps3".into(), + + metadata: TargetMetadata { + description: Some("PowerPC64 (big endian) Sony PlayStation 3 (PS3)".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(false), + }, + + // We declare pointers to be 64-bit as the PPU _is_ a 64-bit core. + // However, for all real usage the OS limits us to **32-bit pointers**. + // SDKs should therefore take this into account, specifically when handling syscalls. + pointer_width: 64, + + data_layout: "E-m:e-Fi64-i64:64-i128:128-n32:64".into(), + arch: Arch::PowerPC64, + + options: TargetOptions { + // Base PS3 hardware. + vendor: "sony".into(), + endian: Endian::Big, + os: Os::Ps3, + cfg_abi: CfgAbi::ElfV1, + llvm_abiname: LlvmAbi::ElfV1, + features: "+altivec".into(), + + // CellOS requiring ELFv1 makes LLVM's `lld` incompatible. + // See: + // - [rust-lang/rust#85589](https://github.com/rust-lang/rust/issues/85589) + // - [llvm/llvm-project#27630](https://github.com/llvm/llvm-project/issues/27630) + linker: Some("mold".into()), + linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::No), + + // CellOS _is_ case-sensitive, but the PS3's binaries vary + // in casing depending on whether they are games in `/dev_hdd0` + // or system binaries (such as PRX files). + // + // All games use the .ELF (uppercase) suffix, and Sony's own + // documentation and tools expect user app binaries to be uppercase. + exe_suffix: ".ELF".into(), + + // This limits us to 64KB of ToC, but yields smaller binaries and less assembly. + // Only becomes a problem for binaries with thousands of dependencies. + code_model: Some(CodeModel::Small), + // Prevents LLVM from emitting modern linker relaxation relocations. + relax_elf_relocations: false, + // CellOS main executables (`EBOOT.ELF`) **must be static executables** (ET_EXEC). + relocation_model: RelocModel::Static, + + // Locking defaults against future changes. + c_int_width: 32, + executables: true, + frame_pointer: FramePointer::MayOmit, + // Change this to `true` for developing kernel-mode applications. + // This target defaults to user-mode, and the kernel already handles + // this for us, so keeping it off is a performance gain. + disable_redzone: false, + + panic_strategy: PanicStrategy::Abort, + pre_link_args, + ..Default::default() + }, + } +} diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip3.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip3.rs index 9e981cd73f5a7..dea9a130e6e56 100644 --- a/compiler/rustc_target/src/spec/targets/wasm32_wasip3.rs +++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip3.rs @@ -2,38 +2,44 @@ //! `wasm32-wasip2`, then WASIp3. The main feature of WASIp3 is native async //! support in the component model itself. //! -//! Like `wasm32-wasip2` this target produces a component by default. Support -//! for `wasm32-wasip3` is very early as of the time of this writing so -//! components produced will still import WASIp2 APIs, but that's ok since it's -//! all component-model-level imports anyway. Over time the imports of the -//! standard library will change to WASIp3. +//! Like `wasm32-wasip2` this target produces a component by default. use crate::spec::{Cc, Env, LinkerFlavor, Target, add_link_args}; pub(crate) fn target() -> Target { - // As of now WASIp3 is a lightly edited wasip2 target, so start with that - // and this may grow over time as more features are supported. + // For now wasip3 is a lightly-edited wasip2 target. let mut target = super::wasm32_wasip2::target(); target.llvm_target = "wasm32-wasip3".into(); target.metadata = crate::spec::TargetMetadata { description: Some("WebAssembly".into()), - tier: Some(3), + tier: Some(2), host_tools: Some(false), std: Some(true), }; target.options.env = Env::P3; - // The `--cooperative-threading` flag to the linker dictates the ABI that's - // being used on this target which is to store the stack pointer in a - // component model intrinsic location, for example, rather than a wasm - // global. - // - // Note that this is only specified for `Cc::No`, because when `clang` is - // being used as a linker it'll already pass this. add_link_args( &mut target.pre_link_args, LinkerFlavor::WasmLld(Cc::No), - &["--cooperative-threading"], + &[ + // The `--cooperative-threading` flag to the linker dictates the ABI + // that's being used on this target which is to store the stack + // pointer in a component model intrinsic location, for example, + // rather than a wasm global. + // + // Note that this is only specified for `Cc::No`, because when + // `clang` is being used as a linker it'll already pass this. + "--cooperative-threading", + // This is used as the wasi-libc-defined symbol here is required for + // this target to function. The Rust compiler's symbol exports + // otherwise don't know about this symbol so it's manually exported + // here. + // + // Note that this additionally is only specified for `Cc::No` + // because when `clang` is used the symbol exports happen naturally + // and this isn't needed. + "--export-if-defined=__wasm_task_hook", + ], ); target diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml index 039856eeb4857..8eecfda24e557 100644 --- a/compiler/rustc_trait_selection/Cargo.toml +++ b/compiler/rustc_trait_selection/Cargo.toml @@ -12,6 +12,7 @@ rustc_crate_store = { path = "../rustc_crate_store" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_hir = { path = "../rustc_hir" } +rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } rustc_lint_defs = { path = "../rustc_lint_defs" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs index 41ed83c11bbd5..f555f0435dd8f 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs @@ -3,7 +3,6 @@ use rustc_errors::Diag; use rustc_middle::ty; -use rustc_middle::ty::RegionExt; use tracing::debug; use crate::diagnostics::ExplicitLifetimeRequired; diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs index ccbe23cf7a631..7f07fab6e8474 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs @@ -8,9 +8,7 @@ use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; use rustc_middle::bug; use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::print::{FmtPrinter, Print, PrintTraitRefExt as _, RegionHighlightMode}; -use rustc_middle::ty::{ - self, GenericArgsRef, IsSuggestable, RePlaceholder, Region, RegionExt, TyCtxt, -}; +use rustc_middle::ty::{self, GenericArgsRef, IsSuggestable, RePlaceholder, Region, TyCtxt}; use rustc_structures::Limit; use tracing::{debug, instrument}; diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs index 1d58e8518ba56..2d48b41bcb361 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs @@ -8,7 +8,7 @@ use rustc_hir::{ self as hir, AmbigArg, GenericBound, GenericParam, GenericParamKind, Item, ItemKind, Lifetime, LifetimeKind, LifetimeParamKind, MissingLifetimeKind, Node, TyKind, }; -use rustc_middle::ty::{self, RegionExt, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor}; use rustc_span::def_id::LocalDefId; use rustc_span::{Ident, Span}; use tracing::debug; diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs index 87785c403fa4e..f1be118896b01 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs @@ -10,7 +10,7 @@ use rustc_middle::hir::nested_filter; use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::print::RegionHighlightMode; -use rustc_middle::ty::{self, RegionExt, TyCtxt, TypeVisitable}; +use rustc_middle::ty::{self, TyCtxt, TypeVisitable}; use rustc_span::{Ident, Span}; use tracing::debug; diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index 7f4ca7a572988..73b98b8eda1a6 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -13,7 +13,7 @@ use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::print::RegionHighlightMode; use rustc_middle::ty::{ - self, IsSuggestable, Region, RegionExt, Ty, TyCtxt, TypeVisitableExt as _, Upcast as _, + self, IsSuggestable, Region, Ty, TyCtxt, TypeVisitableExt as _, Upcast as _, }; use rustc_span::{BytePos, ErrorGuaranteed, Span, Symbol, kw, sym}; use tracing::{debug, instrument}; diff --git a/compiler/rustc_trait_selection/src/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/mod.rs index ff0ac4fcfbe6a..58964492c4837 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/mod.rs @@ -25,6 +25,14 @@ pub struct TypeErrCtxt<'a, 'tcx> { pub diverging_fallback_has_occurred: bool, pub autoderef_steps: Box) -> Vec<(Ty<'tcx>, PredicateObligations<'tcx>)> + 'a>, + pub infer_closure_kind: Box< + dyn Fn( + rustc_hir::def_id::LocalDefId, + ) -> Option<( + ty::ClosureKind, + Option<(rustc_span::Span, rustc_middle::hir::place::Place<'tcx>)>, + )> + 'a, + >, } #[extension(pub trait InferCtxtErrorExt<'tcx>)] @@ -41,6 +49,7 @@ impl<'tcx> InferCtxt<'tcx> { debug_assert!(false, "shouldn't be using autoderef_steps outside of typeck"); vec![(ty, PredicateObligations::new())] }), + infer_closure_kind: Box::new(|_| None), } } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index e3cf38bb34c7c..7788a1bb62a09 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -899,9 +899,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } if let Ok(Some(ImplSource::UserDefined(impl_data))) = - self.enter_forall(trait_ref, |trait_ref_for_select| { - SelectionContext::new(self).select(&obligation.with(self.tcx, trait_ref_for_select)) - }) + SelectionContext::new(self).poly_select(&obligation.with(self.tcx, trait_ref)) { let impl_did = impl_data.impl_def_id; let trait_did = trait_ref.def_id(); @@ -1005,18 +1003,25 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } - let self_ty = trait_pred.self_ty().skip_binder(); + let original_self_ty = trait_pred.self_ty().skip_binder(); + let peeled_self_ty = original_self_ty.peel_refs(); + + let is_ref_to_closure = matches!(original_self_ty.kind(), ty::Ref(..)) + && matches!(peeled_self_ty.kind(), ty::Closure(..)); - let (expected_kind, trait_prefix) = + let self_ty = if is_ref_to_closure { peeled_self_ty } else { original_self_ty }; + + let (expected_kind, is_async) = if let Some(expected_kind) = self.tcx.fn_trait_kind_from_def_id(trait_pred.def_id()) { - (expected_kind, "") + (expected_kind, false) } else if let Some(expected_kind) = self.tcx.async_fn_trait_kind_from_def_id(trait_pred.def_id()) { - (expected_kind, "Async") + (expected_kind, true) } else { return None; }; + let trait_prefix = if is_async { "Async" } else { "" }; let (closure_def_id, found_args, has_self_borrows) = match *self_ty.kind() { ty::Closure(def_id, args) => { @@ -1045,7 +1050,20 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { return None; } - if let Some(found_kind) = self.closure_kind(self_ty) + let mut found_kind = self.closure_kind(self_ty); + let mut kind_origin = None; + + if found_kind.is_none() + && is_ref_to_closure + && !is_async + && let Some(local_def_id) = closure_def_id.as_local() + && let Some((inferred_kind, origin)) = (self.infer_closure_kind)(local_def_id) + { + found_kind = Some(inferred_kind); + kind_origin = origin; + } + + if let Some(found_kind) = found_kind && !found_kind.extends(expected_kind) { let mut err = self.report_closure_error( @@ -1054,7 +1072,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { found_kind, expected_kind, trait_prefix, + kind_origin, ); + self.suggest_change_mut_ref_for_closure(&mut err, &obligation); self.note_obligation_cause(&mut err, &obligation); return Some(err.emit()); } @@ -3029,6 +3049,25 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }) } + fn suggest_change_mut_ref_for_closure( + &self, + err: &mut Diag<'_>, + obligation: &PredicateObligation<'tcx>, + ) { + if let ObligationCauseCode::FunctionArg { arg_hir_id, .. } = obligation.cause.code() + && let (_, Some(root_trait_pred)) = + obligation.cause.code().peel_derives_with_predicate() + && let Node::Expr(arg) = self.tcx.hir_node(*arg_hir_id) + && let hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, _) = arg.kind + { + let mut obligation = obligation.clone(); + // Error reporting may narrow the cause span to the borrow's operand. + // Use the whole argument so `suggest_change_mut` can replace the shared borrow. + obligation.cause.span = arg.span; + self.suggest_change_mut(&obligation, err, root_trait_pred); + } + } + pub fn note_obligation_cause( &self, err: &mut Diag<'_>, @@ -3532,6 +3571,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { found_kind: ty::ClosureKind, kind: ty::ClosureKind, trait_prefix: &'static str, + kind_origin: Option<(Span, rustc_middle::hir::place::Place<'tcx>)>, ) -> Diag<'a> { let closure_span = self.tcx.def_span(closure_def_id); @@ -3547,27 +3587,30 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // Additional context information explaining why the closure only implements // a particular trait. - if let Some(typeck_results) = &self.typeck_results { - let hir_id = self.tcx.local_def_id_to_hir_id(closure_def_id.expect_local()); - match (found_kind, typeck_results.closure_kind_origins().get(hir_id)) { - (ty::ClosureKind::FnOnce, Some((span, place))) => { - err.fn_once_label = Some(ClosureFnOnceLabel { - span: *span, - place: ty::place_to_string_for_capture(self.tcx, place), - trait_prefix, - }) - } - (ty::ClosureKind::FnMut, Some((span, place))) => { - err.fn_mut_label = Some(ClosureFnMutLabel { - span: *span, - place: ty::place_to_string_for_capture(self.tcx, place), - trait_prefix, - }) - } - _ => {} + let origin = kind_origin.or_else(|| { + let typeck_results = self.typeck_results.as_ref()?; + let local_def_id = closure_def_id.as_local()?; + let hir_id = self.tcx.local_def_id_to_hir_id(local_def_id); + typeck_results.closure_kind_origins().get(hir_id).cloned() + }); + + match (found_kind, origin) { + (ty::ClosureKind::FnOnce, Some((span, place))) => { + err.fn_once_label = Some(ClosureFnOnceLabel { + span, + place: ty::place_to_string_for_capture(self.tcx, &place), + trait_prefix, + }) } + (ty::ClosureKind::FnMut, Some((span, place))) => { + err.fn_mut_label = Some(ClosureFnMutLabel { + span, + place: ty::place_to_string_for_capture(self.tcx, &place), + trait_prefix, + }) + } + _ => {} } - self.dcx().create_err(err) } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index a7f05d756af0f..b8e4521451a25 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -6039,19 +6039,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { { self.probe(|_| { let ocx = ObligationCtxt::new(self); - self.enter_forall(pred, |pred| { - let pred = ocx.normalize( - &ObligationCause::dummy(), - param_env, - Unnormalized::new_wip(pred), - ); - ocx.register_obligation(Obligation::new( - self.tcx, - ObligationCause::dummy(), - param_env, - pred, - )); - }); + ocx.register_obligation(Obligation::new( + self.tcx, + ObligationCause::dummy(), + param_env, + pred, + )); if !ocx.try_evaluate_obligations().no_errors() { // encountered errors. return; diff --git a/compiler/rustc_trait_selection/src/solve/select.rs b/compiler/rustc_trait_selection/src/solve/select.rs index b413b8b5ed9c7..53b999e4e5244 100644 --- a/compiler/rustc_trait_selection/src/solve/select.rs +++ b/compiler/rustc_trait_selection/src/solve/select.rs @@ -5,7 +5,7 @@ use rustc_infer::traits::solve::inspect::ProbeKind; use rustc_infer::traits::solve::{CandidateSource, Certainty, Goal}; use rustc_infer::traits::{ BuiltinImplSource, ImplSource, ImplSourceUserDefinedData, Obligation, ObligationCause, - Selection, SelectionError, SelectionResult, TraitObligation, + PolyTraitObligation, Selection, SelectionError, SelectionResult, }; use rustc_macros::extension; use rustc_middle::{bug, span_bug}; @@ -16,10 +16,10 @@ use crate::solve::inspect::{self, InferCtxtProofTreeExt}; #[extension(pub trait InferCtxtSelectExt<'tcx>)] impl<'tcx> InferCtxt<'tcx> { - /// Do not use this directly. This is called from [`crate::traits::SelectionContext::select`]. + /// Do not use this directly. This is called from [`crate::traits::SelectionContext::poly_select`]. fn select_in_new_trait_solver( &self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, ) -> SelectionResult<'tcx, Selection<'tcx>> { assert!(self.next_trait_solver()); diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 4593ac035dc95..7357d1738d8c3 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -32,7 +32,7 @@ use rustc_macros::TypeVisitable; use rustc_middle::query::Providers; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{ - self, BottomUpFolder, Clause, GenericArgs, GenericArgsRef, RegionExt, Ty, TyCtxt, TypeFoldable, + self, BottomUpFolder, Clause, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypingMode, Unnormalized, Upcast, }; diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 0d22ca4973511..56df5d917e108 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -349,9 +349,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { .fold_with(self) .into() } else { - infcx - .tcx - .const_of_item(def_id) + project::const_of_item_or_delayed_bug(infcx.tcx, def_id) .instantiate(infcx.tcx, free.args) .skip_norm_wip() .fold_with(self) @@ -469,7 +467,7 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx if tcx.features().generic_const_exprs() // Normalize type_const items even with feature `generic_const_exprs`. - && !matches!(ct.kind(), ty::ConstKind::Alias(_, alias_const) if alias_const.kind.is_type_const(tcx)) + && !matches!(ct.kind(), ty::ConstKind::Alias(_, alias_const) if alias_const.kind.is_direct_const(tcx)) || !needs_normalization(self.selcx.infcx, &ct) { return ct; diff --git a/compiler/rustc_trait_selection/src/traits/outlives_for_liveness.rs b/compiler/rustc_trait_selection/src/traits/outlives_for_liveness.rs index 5cba32d742f62..eb89d79474d1c 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_for_liveness.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_for_liveness.rs @@ -1,6 +1,7 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_index::bit_set::DenseBitSet; use rustc_middle::bug; use rustc_middle::ty::{ self, Flags, ImplTraitInTraitData, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, @@ -11,15 +12,15 @@ use crate::infer::outlives::test_type_match; use crate::infer::region_constraints::VerifyIfEq; use crate::regions::{region_known_to_outlive, ty_known_to_outlive}; -/// For a given alias type, this returns the set of (identity) generic args that +/// For a given alias type, this returns the set of indices into the identity generic args that /// are relevant for liveness, that can be inferred from outlives bounds on the /// alias itself, and the explicit and implicit outlives clauses of the alias. -/// Callers should instantiate the returned args with the concrete args of the alias. +/// Callers should use the indices with the concrete args of the alias. /// /// There are three cases to consider: -/// 1. If there are *no* outlives bounds, then we return None. +/// 1. If there are *no* outlives bounds, then all args are potentially live. /// 2. If there is a `'static` outlives bound, then we know that all args are -/// irrelevant, so we return an empty list. +/// irrelevant, so we return an empty set. /// 3. If there are *any* outlives bounds, then we find any args that are known /// to outlive those bounds, since those are the args whose regions the /// underlying type could capture. @@ -27,7 +28,7 @@ use crate::regions::{region_known_to_outlive, ty_known_to_outlive}; pub(crate) fn live_args_for_alias_from_outlives_bounds<'tcx>( tcx: TyCtxt<'tcx>, kind: ty::AliasTyKind<'tcx>, -) -> Option>>> { +) -> DenseBitSet { let def_id = match kind { ty::AliasTyKind::Projection { def_id } | ty::AliasTyKind::Inherent { def_id } @@ -69,7 +70,7 @@ pub(crate) fn live_args_for_alias_from_outlives_bounds<'tcx>( // If there are no outlives bounds, then all (non-bivariant) args are potentially live. if outlives_regions.is_empty() { - return None; + return DenseBitSet::new_filled(self_identity_args.len()); } // If any of the outlives bounds are `'static`, then we know the alias @@ -88,7 +89,7 @@ pub(crate) fn live_args_for_alias_from_outlives_bounds<'tcx>( // regions are going to be instantiated with free regions. if outlives_regions.contains(&tcx.lifetimes.re_static) { tracing::debug!("alias has a 'static outlives bound, so skipping visiting any regions"); - return Some(ty::EarlyBinder::bind(tcx, vec![])); + return DenseBitSet::new_empty(self_identity_args.len()); } // Okay, so we know we have some outlives bounds, and that none of them are `'static`. @@ -96,37 +97,32 @@ pub(crate) fn live_args_for_alias_from_outlives_bounds<'tcx>( // an outlives-bound region. `args_known_to_outlive_alias_params` does this // for us, and in the case of opaques only includes *captured* regions, too. - let args_known_to_outlive = - tcx.args_known_to_outlive_alias_params(def_id).as_ref().skip_binder(); + let args_known_to_outlive = tcx.args_known_to_outlive_alias_params(def_id); tracing::debug!(?args_known_to_outlive); - let mut live_args: Option>> = None; + let mut live_args = DenseBitSet::new_filled(self_identity_args.len()); for outlives_region in outlives_regions { - let Some(outlives_params) = - args_known_to_outlive.iter().find(|(r, _)| *r == outlives_region) + let Some(outlives_params) = args_known_to_outlive + .iter() + .find(|(idx, _)| self_identity_args[*idx].as_region() == Some(outlives_region)) else { continue; }; - let new_live_args = outlives_params.1.iter().copied().collect(); - match &mut live_args { - None => live_args = Some(new_live_args), - Some(prev) => *prev = prev.intersection(&new_live_args).copied().collect(), - }; + live_args.intersect(&outlives_params.1); } - live_args.map(|c| ty::EarlyBinder::bind(tcx, c.into_iter().collect())) + live_args } -/// For each region param of this alias compute the identity args that are known -/// to outlive it, given only the alias's declared where-clauses. +/// For each region param of this alias compute the indices of the identity args +/// that are known to outlive it, given only the alias's declared where-clauses. /// /// Note: for opaques (including synthetic associated types from RPITITs), /// the outlives relationships are identified in the context of the *parent*, /// since bounds and well-formed types are not lowered. -// FIXME: this likely should return a `BitSet` instead of a `Vec>` #[tracing::instrument(level = "debug", skip(tcx), ret)] pub(crate) fn args_known_to_outlive_alias_params<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, -) -> ty::EarlyBinder<'tcx, Vec<(ty::Region<'tcx>, Vec>)>> { +) -> Vec<(usize, DenseBitSet)> { match tcx.def_kind(def_id) { DefKind::OpaqueTy => args_known_to_outlive_opaque_params(tcx, def_id), DefKind::AssocTy @@ -171,7 +167,7 @@ pub(crate) fn args_known_to_outlive_alias_params<'tcx>( pub(crate) fn args_known_to_outlive_opaque_params<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, -) -> ty::EarlyBinder<'tcx, Vec<(ty::Region<'tcx>, Vec>)>> { +) -> Vec<(usize, DenseBitSet)> { let self_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id); let mut result = Vec::new(); @@ -207,7 +203,9 @@ pub(crate) fn args_known_to_outlive_opaque_params<'tcx>( // build a `Region` from the opaque region's `LocalDefId`). let generics = tcx.generics_of(def_id); let mut parent_outlives_regions = Vec::with_capacity(generics.own_params.len()); - for opaque_arg in self_identity_args[generics.parent_count..].iter() { + for (opaque_arg_idx, opaque_arg) in + self_identity_args.iter().enumerate().skip(generics.parent_count) + { let Some(opaque_region) = opaque_arg.as_region() else { continue; }; @@ -218,7 +216,7 @@ pub(crate) fn args_known_to_outlive_opaque_params<'tcx>( let parent_region = tcx.map_opaque_lifetime_to_parent_lifetime(region_def_id.expect_local()); tracing::debug!(?region_def_id, ?parent_region); - parent_outlives_regions.push((parent_region, opaque_region)); + parent_outlives_regions.push((parent_region, opaque_arg_idx)); } tracing::debug!(?parent_outlives_regions); @@ -227,9 +225,11 @@ pub(crate) fn args_known_to_outlive_opaque_params<'tcx>( // 2) *Captured Regions* // // In both cases, we need to check known outlives for the *parent* region, because that's where the param_env and wf_tys are. - for (parent_outlived_region, opaque_outlived_region) in parent_outlives_regions.iter() { - let mut opaque_outlives_args = Vec::with_capacity(self_identity_args.len()); - for parent_outlives_arg in self_identity_args[..generics.parent_count].iter() { + for (parent_outlived_region, opaque_outlived_arg_idx) in parent_outlives_regions.iter() { + let mut opaque_outlives_args = DenseBitSet::new_empty(self_identity_args.len()); + for (parent_outlived_arg_idx, parent_outlives_arg) in + self_identity_args[..generics.parent_count].iter().enumerate() + { let type_outlives = match parent_outlives_arg.kind() { // Consts don't have any non-static regions ty::GenericArgKind::Const(_) => continue, @@ -249,10 +249,10 @@ pub(crate) fn args_known_to_outlive_opaque_params<'tcx>( } // Types aren't captured, so don't need to map to the opaque - opaque_outlives_args.push(*parent_outlives_arg); + opaque_outlives_args.insert(parent_outlived_arg_idx as u32); } - for &(parent_outlives_region, opaque_region) in parent_outlives_regions.iter() { + for &(parent_outlives_region, opaque_arg_idx) in parent_outlives_regions.iter() { let region_outlives = parent_outlives_region == *parent_outlived_region || region_known_to_outlive( tcx, @@ -266,32 +266,32 @@ pub(crate) fn args_known_to_outlive_opaque_params<'tcx>( continue; } - opaque_outlives_args.push(opaque_region.into()); + opaque_outlives_args.insert(opaque_arg_idx as u32); } - result.push((*opaque_outlived_region, opaque_outlives_args)); + result.push((*opaque_outlived_arg_idx, opaque_outlives_args)); } - ty::EarlyBinder::bind(tcx, result) + result } #[tracing::instrument(level = "debug", skip(tcx), ret)] pub(crate) fn args_known_to_outlive_non_opaque_params<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, -) -> ty::EarlyBinder<'tcx, Vec<(ty::Region<'tcx>, Vec>)>> { +) -> Vec<(usize, DenseBitSet)> { let self_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id); let param_env = tcx.param_env(def_id); tracing::debug!(?param_env); let wf_tys = tcx.assumed_wf_types(def_id).iter().map(|(ty, _)| *ty).collect::>(); let mut result = Vec::new(); - for outlived_arg in self_identity_args.iter() { + for (outlived_arg_idx, outlived_arg) in self_identity_args.iter().enumerate() { let Some(outlived_region) = outlived_arg.as_region() else { continue; }; - let outliving_args = self_identity_args - .iter() - .filter(|arg| match arg.kind() { + let mut outliving_args = DenseBitSet::new_empty(self_identity_args.len()); + for (arg_idx, arg) in self_identity_args.iter().enumerate() { + let outlives = match arg.kind() { ty::GenericArgKind::Lifetime(r) => { region_known_to_outlive(tcx, def_id, param_env, &wf_tys, r, outlived_region) } @@ -299,16 +299,19 @@ pub(crate) fn args_known_to_outlive_non_opaque_params<'tcx>( ty_known_to_outlive(tcx, def_id, param_env, &wf_tys, t, outlived_region) } ty::GenericArgKind::Const(_) => false, - }) - .collect(); - result.push((outlived_region, outliving_args)); + }; + if outlives { + outliving_args.insert(arg_idx as u32); + } + } + result.push((outlived_arg_idx, outliving_args)); } - ty::EarlyBinder::bind(tcx, result) + result } /// For a param-env clause `for<'v..> ::Assoc<..>: 'bound` that -/// applies to `ty` (an alias with `alias_def_id`), returns the set of (identity) args -/// that the underlying type could possibly capture, as restricted by this clause. +/// applies to `ty` (an alias with `alias_def_id`), returns the set of indices into the +/// identity args that the underlying type could possibly capture, as restricted by this clause. /// /// As an example, let's imagine we had the following associated type definition: /// ```ignore (illustrative) @@ -338,20 +341,24 @@ pub(crate) fn args_known_to_outlive_non_opaque_params<'tcx>( /// some cases (like `for<'x, 'y, 'z> T::Assoc<'x, 'y, 'z>: 'x`) that won't /// be satisfiable today, but the logic here should hold whenever there *is*. /// -/// Returns `None` if the clause doesn't apply to `ty` or gives us no information. +/// Returns a filled set if the clause doesn't apply to `ty` or gives us no +/// information. #[tracing::instrument(level = "debug", skip(tcx), ret)] fn live_args_for_outlives_clause<'tcx>( tcx: TyCtxt<'tcx>, alias_def_id: DefId, ty: Ty<'tcx>, outlives: ty::Binder<'tcx, ty::TypeOutlivesClause<'tcx>>, -) -> Option>>> { +) -> DenseBitSet { + let clause_identity_args = ty::GenericArgs::identity_for_item(tcx, alias_def_id); + let no_restriction = || DenseBitSet::new_filled(clause_identity_args.len()); + // N.B. it's okay to skip the binder here (and in the rest of the function), // because all variables under binders do not escape let ty::Alias(_, ty::AliasTy { kind: clause_alias_kind, args: clause_args, .. }) = *outlives.skip_binder().0.kind() else { - return None; + return no_restriction(); }; let clause_def_id = match clause_alias_kind { ty::AliasTyKind::Projection { def_id } @@ -360,27 +367,28 @@ fn live_args_for_outlives_clause<'tcx>( | ty::AliasTyKind::Free { def_id } => def_id, }; if clause_def_id != alias_def_id { - return None; + return no_restriction(); } // Here, we're just using this to check if the clause *could apply* to `ty`, // but importantly we don't want to use the returned region, because that is // the "last visited" region in `ty` that matches the outlves bound. Actually, // we want *all* the identity regions in `ty` that match the outlives bound. - test_type_match::extract_verify_if_eq( + let Some(_) = test_type_match::extract_verify_if_eq( tcx, &outlives.map_bound(|ty::OutlivesClause(ty, bound)| VerifyIfEq { ty, bound }), ty, - )?; + ) else { + return no_restriction(); + }; let outlived_region = outlives.skip_binder().1; - let clause_identity_args = ty::GenericArgs::identity_for_item(tcx, alias_def_id); match outlived_region.kind() { // The underlying type must outlive `'static`, so it can't capture any of the args at all. // // Of course, you may ask: "what if the function has a `'a: 'static` bound?" See the corresponding // comment in `live_args_for_alias_from_outlives_bounds` for why we don't need to worry about that. - ty::ReStatic => Some(FxIndexSet::default()), + ty::ReStatic => DenseBitSet::new_empty(clause_identity_args.len()), ty::ReBound(_, br) => { // The bound is one of the clause's higher-ranked vars. Find the arg // positions it occupies, then (at the alias's identity level) find @@ -388,13 +396,15 @@ fn live_args_for_outlives_clause<'tcx>( // the alias's declared bounds -- only those can be captured by the // underlying type. let mut outlived_regions = Vec::new(); - for (clause_arg, identity_arg) in clause_args.iter().zip(clause_identity_args.iter()) { + for (clause_arg, (identity_arg_idx, _identity_arg)) in + clause_args.iter().zip(clause_identity_args.iter().enumerate()) + { match clause_arg.kind() { ty::GenericArgKind::Lifetime(r) => { if let ty::ReBound(_, arg_br) = r.kind() && arg_br.var == br.var { - outlived_regions.push(identity_arg.expect_region()); + outlived_regions.push(identity_arg_idx); } } ty::GenericArgKind::Type(_) | ty::GenericArgKind::Const(_) => { @@ -404,7 +414,7 @@ fn live_args_for_outlives_clause<'tcx>( // so conservatively treat the clause as giving no // restriction at all. if clause_arg.has_escaping_bound_vars() { - return None; + return no_restriction(); } } } @@ -413,7 +423,7 @@ fn live_args_for_outlives_clause<'tcx>( // The bound var doesn't appear in the args at all, so the clause // requires the underlying type to outlive *every* region, which // is equivalent to a `'static` bound. - return Some(FxIndexSet::default()); + return DenseBitSet::new_empty(clause_identity_args.len()); } // The underlying type can capture any arg that's known to outlive one @@ -421,22 +431,15 @@ fn live_args_for_outlives_clause<'tcx>( // region at any use site this clause applies to). let args_known_to_outlive = tcx.args_known_to_outlive_alias_params(alias_def_id); tracing::debug!(?outlived_regions, ?args_known_to_outlive); - let mut capturable_args = FxIndexSet::default(); - for &outlived_region in &outlived_regions { - // There's a bit of a dance here around `Earlybinder::skip_binder` - // and then later a `Earlybinder::bind`. This is because there's - // no real good way today to move the `EarlyBinder` inward - // declaratively without cloning the entire thing. + let mut capturable_args = DenseBitSet::new_empty(clause_identity_args.len()); + for &outlived_arg_idx in &outlived_regions { let (_, outliving_args) = args_known_to_outlive - .as_ref() - .skip_binder() .iter() - .find(|(region, _)| *region == outlived_region) + .find(|(arg_idx, _)| *arg_idx == outlived_arg_idx) .unwrap(); - capturable_args - .extend(outliving_args.iter().copied().map(|a| ty::EarlyBinder::bind(tcx, a))); + capturable_args.union(outliving_args); } - Some(capturable_args) + capturable_args } // A free region (e.g. `for T::Assoc<'a, 'x>: 'x`, where `'x` is free). // This is effectively the same as `for<'a, 'b> T::Assoc<'a, 'b>: 'b`, @@ -459,9 +462,9 @@ fn live_args_for_outlives_clause<'tcx>( // } // ``` // So, we conservatively treat this as giving no restriction on which args can be captured. - ty::ReEarlyParam(..) => None, + ty::ReEarlyParam(..) => no_restriction(), // Don't know that we actually hit this (maybe `ReError`), go ahead and be conservative. - _ => None, + _ => no_restriction(), } } @@ -527,59 +530,22 @@ where | ty::AliasTyKind::Opaque { def_id } | ty::AliasTyKind::Free { def_id } => def_id, }; - let mut capturable: Option< - FxIndexSet>>, - > = None; - let mut restrict = - |capturable_args: FxIndexSet>>| { - match &mut capturable { - None => capturable = Some(capturable_args), - Some(prev) => { - *prev = prev.intersection(&capturable_args).copied().collect() - } - }; - }; - - if let Some(live_args) = tcx.live_args_for_alias_from_outlives_bounds(kind) { - restrict( - live_args - .as_ref() - .skip_binder() - .iter() - .copied() - .map(|a| ty::EarlyBinder::bind(tcx, a)) - .collect(), - ); - } + let mut capturable = tcx.live_args_for_alias_from_outlives_bounds(kind).clone(); for clause in param_env.caller_bounds() { let Some(outlives) = clause.as_type_outlives_clause() else { continue; }; - if let Some(capturable_args) = - live_args_for_outlives_clause(tcx, def_id, ty, outlives) - { - restrict(capturable_args); - } + capturable.intersect(&live_args_for_outlives_clause(tcx, def_id, ty, outlives)); } tracing::debug!(?capturable); - match capturable { - Some(capturable_args) => { - for arg in capturable_args { - let arg = arg.instantiate(tcx, args).skip_norm_wip(); - arg.visit_with(self); - } - } - None => { - // Skip lifetime parameters that are not captured, since they do - // not need to be live. - let variances = tcx.opt_alias_variances(kind); - for (idx, s) in args.iter().enumerate() { - if variances.map(|variances| variances[idx]) != Some(ty::Bivariant) { - s.visit_with(self); - } - } + // Skip lifetime parameters that are not captured, since they do + // not need to be live. + let variances = tcx.opt_alias_variances(kind); + for idx in capturable.iter() { + if variances.map(|variances| variances[idx as usize]) != Some(ty::Bivariant) { + args[idx as usize].visit_with(self); } } } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 9d0daa3a8672b..f3504e96965e8 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -505,6 +505,22 @@ fn push_const_arg_has_type_obligation<'tcx>( } } +/// The old solver does not support references to non-type-consts. +/// Emit a delayed bug if there is a type system reference to a non type const, as this should have +/// already errored elsewhere. +pub fn const_of_item_or_delayed_bug<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: DefId, +) -> ty::EarlyBinder<'tcx, ty::Const<'tcx>> { + tcx.const_of_item(def_id).unwrap_or_else(|| { + let e = tcx.dcx().span_delayed_bug( + tcx.def_span(def_id), + "encountered regular consts in the old solver's const normalization", + ); + ty::EarlyBinder::bind(tcx, ty::Const::new_error(tcx, e)) + }) +} + /// Confirm and normalize the given inherent projection. // FIXME(mgca): While this supports constants, it is only used for types by default right now #[instrument(level = "debug", skip(selcx, param_env, cause, obligations))] @@ -565,7 +581,7 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>( let term = if alias_term.kind.is_type() { tcx.type_of(def_id).instantiate(tcx, args).map(Into::into) } else { - tcx.const_of_item(def_id).instantiate(tcx, args).map(Into::into) + const_of_item_or_delayed_bug(tcx, def_id).instantiate(tcx, args).map(Into::into) }; let term = selcx.infcx.resolve_vars_if_possible(term); @@ -2115,7 +2131,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( let term = if obligation.predicate.kind.is_type() { tcx.type_of(assoc_term.item.def_id).map_bound(|ty| ty.into()) } else { - tcx.const_of_item(assoc_term.item.def_id).map_bound(|ct| ct.into()) + const_of_item_or_delayed_bug(tcx, assoc_term.item.def_id).map_bound(|ct| ct.into()) }; assoc_term_own_obligations(selcx, obligation, &mut nested); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index a2785a7ca75dc..15dfd58d6b753 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -255,7 +255,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, ) -> SelectionResult<'tcx, Selection<'tcx>> { - assert!(!self.infcx.next_trait_solver()); + if self.infcx.next_trait_solver() { + return self.infcx.select_in_new_trait_solver(obligation); + } let candidate = match self.select_from_obligation(obligation) { Err(SelectionError::Overflow(OverflowError::Canonical)) => { @@ -292,10 +294,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &TraitObligation<'tcx>, ) -> SelectionResult<'tcx, Selection<'tcx>> { - if self.infcx.next_trait_solver() { - return self.infcx.select_in_new_trait_solver(obligation); - } - self.poly_select(&Obligation { cause: obligation.cause.clone(), param_env: obligation.param_env, diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index fc16b6d44c310..5fc9e57795b72 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -1088,7 +1088,8 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { ty::ConstKind::Alias(_, alias_const) => { if !c.has_escaping_bound_vars() { // Skip type consts as mGCA doesn't support evaluatable clauses - if !alias_const.kind.is_type_const(tcx) && !tcx.features().generic_const_args() + if !alias_const.kind.is_direct_const(tcx) + && !tcx.features().generic_const_args() { let predicate = ty::Binder::dummy(ty::PredicateKind::Clause( ty::ClauseKind::ConstEvaluatable(c), diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs index 03dff745210d6..c3fe949d29d64 100644 --- a/compiler/rustc_traits/src/normalize_projection_ty.rs +++ b/compiler/rustc_traits/src/normalize_projection_ty.rs @@ -108,7 +108,10 @@ fn normalize_canonicalized_free_alias<'tcx>( let normalized_term: ty::Term<'tcx> = if goal.kind.is_type() { tcx.type_of(def_id).instantiate(tcx, goal.args).skip_norm_wip().into() } else { - tcx.const_of_item(def_id).instantiate(tcx, goal.args).skip_norm_wip().into() + traits::project::const_of_item_or_delayed_bug(tcx, def_id) + .instantiate(tcx, goal.args) + .skip_norm_wip() + .into() }; ocx.register_obligations(const_arg_has_type_obligation( tcx, diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 65d589cc35aa0..318b3273219a5 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -6,6 +6,7 @@ use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{self as hir, find_attr}; use rustc_middle::bug; use rustc_middle::middle::deduced_param_attrs::DeducedParamAttrs; +use rustc_middle::ptrauth::ptrauth_compute_fn_ptr_type_discriminator_for; use rustc_middle::query::Providers; use rustc_middle::ty::layout::{ FnAbiError, HasTyCtxt, HasTypingEnv, LayoutCx, LayoutOf, TyAndLayout, fn_can_unwind, @@ -611,6 +612,11 @@ fn fn_abi_new_uncached<'tcx>( determined_fn_def_id, sig.abi(), ), + ptrauth_discriminator: if tcx.sess.pointer_authentication_fn_ptr_type_discrimination() { + Some(ptrauth_compute_fn_ptr_type_discriminator_for(tcx, sig).unwrap_or(0).into()) + } else { + None + }, }; fn_abi_adjust_for_abi(cx, &mut fn_abi, sig.abi()); debug!("fn_abi_new_uncached = {:?}", fn_abi); diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index de94087498c75..ea58041a12b77 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -2,7 +2,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_hir::definitions::{DefPathData, PerParentDisambiguatorState}; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{self as hir, ConstItemRhs, ImplItemImplKind, ItemKind}; +use rustc_hir::{self as hir, ImplItemImplKind, ItemKind}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, ImplTraitInTraitData, TyCtxt}; use rustc_middle::{bug, span_bug}; @@ -89,7 +89,7 @@ fn associated_item_from_trait_item( let name = trait_item.ident.name; let kind = match trait_item.kind { hir::TraitItemKind::Const(_, _) => { - ty::AssocKind::Const { name, is_type_const: tcx.is_type_const(owner_id.def_id) } + ty::AssocKind::Const { name, is_type_const: tcx.is_type_const_syntax(owner_id.def_id) } } hir::TraitItemKind::Fn { .. } => { ty::AssocKind::Fn { name, has_self: fn_has_self_parameter(tcx, owner_id) } @@ -106,13 +106,13 @@ fn associated_item_from_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_> let owner_id = impl_item.owner_id; let name = impl_item.ident.name; let kind = match impl_item.kind { - hir::ImplItemKind::Const(_, rhs) => { - ty::AssocKind::Const { name, is_type_const: matches!(rhs, ConstItemRhs::TypeConst(_)) } + hir::ImplItemKind::Const(..) => { + ty::AssocKind::Const { name, is_type_const: tcx.is_type_const_syntax(owner_id.def_id) } } - hir::ImplItemKind::Fn { .. } => { + hir::ImplItemKind::Fn(..) => { ty::AssocKind::Fn { name, has_self: fn_has_self_parameter(tcx, owner_id) } } - hir::ImplItemKind::Type { .. } => { + hir::ImplItemKind::Type(..) => { ty::AssocKind::Type { data: ty::AssocTypeData::Normal(name) } } }; diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index 3653b6ee3670d..66ba76bcd6474 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -5,7 +5,7 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, RegionExt, Ty, TyCtxt, Unnormalized, fold_regions}; +use rustc_middle::ty::{self, Ty, TyCtxt, Unnormalized, fold_regions}; use rustc_middle::{bug, span_bug}; use rustc_span::Span; diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index e54e8f098d175..056165d19ae04 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -6,8 +6,8 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::ty::{ - self, RegionExt, SizedTraitKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, - Unnormalized, Upcast, fold_regions, + self, SizedTraitKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, Unnormalized, + Upcast, fold_regions, }; use rustc_span::DUMMY_SP; use rustc_span::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index db867364b3585..7fc29cd8ebcf1 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -1028,7 +1028,7 @@ impl BoundRegionKind { match *self { ty::BoundRegionKind::Named(def_id) => { let name = tcx.item_name(def_id); - if name.is_kw_underscore_lifetime() { None } else { Some(name) } + if name == I::Symbol::KW_UNDERSCORE_LIFETIME { None } else { Some(name) } } ty::BoundRegionKind::NamedForPrinting(name) => Some(name), _ => None, diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index 26a4edccd0134..36cef1c13eb29 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -160,14 +160,8 @@ impl AliasConstKind { interner.alias_const_kind_from_def_id(def_id, inherent_args) } - pub fn is_type_const(self, interner: I) -> bool { - match self { - AliasConstKind::Projection { def_id } => interner.is_type_const(def_id.into()), - AliasConstKind::InherentSelf { def_id } => interner.is_type_const(def_id.into()), - AliasConstKind::InherentImpl { def_id } => interner.is_type_const(def_id.into()), - AliasConstKind::Free { def_id } => interner.is_type_const(def_id.into()), - AliasConstKind::Anon { def_id } => interner.is_type_const(def_id.into()), - } + pub fn is_direct_const(self, interner: I) -> bool { + interner.is_direct_const(self) } pub fn def_span(self, interner: I) -> I::Span { diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index b08cf4c5876a9..bf90ef707c051 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -286,6 +286,7 @@ pub trait ExprConst>: Copy + Debug + Hash + Eq + R #[rust_analyzer::prefer_underscore_import] pub trait GenericsOf> { fn count(&self) -> usize; + fn param_region_def_id(self, interner: I, ebr: I::EarlyParamRegion) -> I::DefId; } #[rust_analyzer::prefer_underscore_import] @@ -768,6 +769,17 @@ impl<'a, S: SliceLike> SliceLike for &'a S { } #[rust_analyzer::prefer_underscore_import] -pub trait Symbol: Copy + Hash + PartialEq + Eq + Debug { - fn is_kw_underscore_lifetime(self) -> bool; +pub trait Symbol: Copy + Hash + PartialEq + Eq + Debug { + const KW_UNDERSCORE_LIFETIME: Self; + const KW_STATIC_LIFETIME: Self; + const SYM_ANON: Self; +} + +pub trait RegionName: Copy + Hash + PartialEq + Eq + Debug { + fn get_name(&self, interner: I) -> Option; + fn is_named(&self, interner: I) -> bool; +} + +pub trait DefIdGetter: Copy + Hash + PartialEq + Eq + Debug { + fn get_def_id(self) -> Option; } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 1dfb34d94c0fc..31a027c15fd01 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -22,7 +22,7 @@ use crate::solve::{ use crate::visit::{Flags, TypeVisitable}; use crate::{ self as ty, AliasTermKind, BoundRegion, BoundVar, CanonicalParamEnvCache, DebruijnIndex, - Region, RegionKind, TraitRef, search_graph, + Region, RegionKind, RegionVid, TraitRef, search_graph, }; /// The central trait in the shared abstraction layer, specifying all implementation-specific @@ -211,16 +211,31 @@ pub trait Interner: /// Do not uplift, the underlying types differ between r-a and rustc. /// /// See . - type EarlyParamRegion: ParamLike; + type EarlyParamRegion: ParamLike + RegionName; /// (2026/08/13) /// Do not uplift, the underlying types differ between r-a and rustc. /// /// See . #[cfg(feature = "nightly")] - type LateParamRegionKind: Clone + Copy + Debug + PartialEq + Eq + Hash + StableHash; + type LateParamRegionKind: Clone + + Copy + + Debug + + PartialEq + + Eq + + Hash + + StableHash + + DefIdGetter + + RegionName; #[cfg(not(feature = "nightly"))] - type LateParamRegionKind: Clone + Copy + Debug + PartialEq + Eq + Hash; + type LateParamRegionKind: Clone + + Copy + + Debug + + PartialEq + + Eq + + Hash + + DefIdGetter + + RegionName; type InternedRegionKind: Interned>; @@ -266,8 +281,11 @@ pub trait Interner: self, def_id: Self::LocalOpaqueTyId, ) -> ty::EarlyBinder; - fn is_type_const(self, def_id: Self::DefId) -> bool; - fn const_of_item(self, def_id: Self::DefId) -> ty::EarlyBinder; + fn is_direct_const(self, alias: ty::AliasConstKind) -> bool; + fn const_of_item( + self, + alias: ty::AliasConstKind, + ) -> Option>; fn anon_const_kind(self, def_id: Self::DefId) -> ty::AnonConstKind; fn def_span(self, def_id: Self::DefId) -> Self::Span; @@ -491,6 +509,7 @@ pub trait Interner: fn is_impl_trait_in_trait(self, def_id: Self::DefId) -> bool; fn delay_bug(self, msg: impl ToString) -> Self::ErrorGuaranteed; + fn span_delayed_bug(self, span: Self::Span, msg: impl ToString) -> Self::ErrorGuaranteed; fn is_general_coroutine(self, coroutine_def_id: Self::CoroutineId) -> bool; fn coroutine_is_async(self, coroutine_def_id: Self::CoroutineId) -> bool; @@ -528,6 +547,8 @@ pub trait Interner: fn get_re_static_lifetime(self) -> Region; + fn intern_re_var(self, rv: RegionVid) -> Region; + fn intern_region(self, region_kind: RegionKind) -> Region; fn intern_bound_region( diff --git a/compiler/rustc_type_ir/src/sty/mod.rs b/compiler/rustc_type_ir/src/sty/mod.rs index e82d062a155a6..0dfdda6af16cc 100644 --- a/compiler/rustc_type_ir/src/sty/mod.rs +++ b/compiler/rustc_type_ir/src/sty/mod.rs @@ -24,6 +24,90 @@ pub struct Region(pub I::InternedRegionKind); // These are only the `inherent` trait methods that have been ported across impl Region { + #[inline] + pub fn new_var(interner: I, v: RegionVid) -> Self { + interner.intern_re_var(v) + } + + pub fn get_name(self, interner: I) -> Option { + match self.kind() { + RegionKind::ReEarlyParam(ebr) => ebr.get_name(interner), + RegionKind::ReBound(_, br) => br.kind.get_name(interner), + RegionKind::ReLateParam(fr) => fr.kind.get_name(interner), + RegionKind::ReStatic => Some(I::Symbol::KW_STATIC_LIFETIME), + RegionKind::RePlaceholder(placeholder) => placeholder.bound.kind.get_name(interner), + _ => None, + } + } + + pub fn get_name_or_anon(self, interner: I) -> I::Symbol { + match self.get_name(interner) { + Some(name) => name, + None => I::Symbol::SYM_ANON, + } + } + + /// Given some item `binding_item`, check if this region is a generic parameter introduced by it + /// or one of the parent generics. Returns the `DefId` of the parameter definition if so. + pub fn opt_param_def_id(self, interner: I, binding_item: I::DefId) -> Option { + match self.kind() { + RegionKind::ReEarlyParam(ebr) => { + Some(interner.generics_of(binding_item).param_region_def_id(interner, ebr)) + } + RegionKind::ReLateParam(param) => param.kind.get_def_id(), + _ => None, + } + } + + /// Is this region named by the user? + pub fn is_named(self, interner: I) -> bool { + match self.kind() { + RegionKind::ReEarlyParam(ebr) => ebr.is_named(interner), + RegionKind::ReBound(_, br) => br.kind.is_named(interner), + RegionKind::ReLateParam(fr) => fr.kind.is_named(interner), + RegionKind::ReStatic => true, + RegionKind::ReVar(..) => false, + RegionKind::RePlaceholder(placeholder) => placeholder.bound.kind.is_named(interner), + RegionKind::ReErased => false, + RegionKind::ReError(_) => false, + } + } + + /// Constructs a `RegionKind::ReError` region and registers a delayed bug to ensure it gets + /// used. + #[track_caller] + pub fn new_error_misc(interner: I) -> Self { + Self::new_error_with_message( + interner, + I::Span::dummy(), + "RegionKind::ReError constructed but no error reported", + ) + } + + /// Constructs a `RegionKind::ReError` region and registers a delayed bug with the given `msg` + /// to ensure it gets used. + #[track_caller] + pub fn new_error_with_message(interner: I, span: I::Span, msg: impl ToString) -> Self { + let reported = interner.span_delayed_bug(span, msg); + Self::new_error(interner, reported) + } + + #[inline] + pub fn new_late_param(interner: I, scope: I::DefId, kind: I::LateParamRegionKind) -> Self { + interner.intern_region(RegionKind::ReLateParam(LateParamRegion { scope, kind })) + } + + #[inline] + pub fn new_early_param(interner: I, early_bound_region: I::EarlyParamRegion) -> Self { + interner.intern_region(RegionKind::ReEarlyParam(early_bound_region)) + } + + /// Constructs a `RegionKind::ReError` region. + #[track_caller] + pub fn new_error(interner: I, guar: I::ErrorGuaranteed) -> Self { + interner.intern_region(RegionKind::ReError(guar)) + } + #[inline] pub fn new_bound(interner: I, debruijn: DebruijnIndex, bound_region: BoundRegion) -> Self { interner.intern_bound_region(debruijn, bound_region) @@ -159,6 +243,14 @@ impl Region { pub fn kind(self) -> RegionKind { self.0.get() } + + #[inline] + pub fn bound_at_or_above_binder(self, index: DebruijnIndex) -> bool { + match self.kind() { + RegionKind::ReBound(BoundVarIndexKind::Bound(debruijn), _) => debruijn >= index, + _ => false, + } + } } impl Flags for Region { diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 473f01660bdb4..8afe6806b3541 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -731,12 +731,16 @@ impl Box { let (value, allocation) = Box::take(this); let (raw, alloc) = Box::into_non_null_with_allocator(allocation); if size_of::() == size_of::() && align_of::() == align_of::() { - // ignore-tidy-undocumented-unsafe + // SAFETY: We checked that the memory requirements are the same for both types + // and `raw` is already a valid pointer for the requisite memory. let allocation = unsafe { Box::from_non_null_in(raw.cast::>(), alloc) }; Box::write(allocation, f(value)) } else { - // ignore-tidy-undocumented-unsafe - unsafe { alloc.deallocate(raw.cast(), Layout::for_value(&value)) } + if size_of::() != 0 { + // SAFETY: `raw` isn't dangling since it points to a non-zero-sized + // allocation and is never used again after this point. + unsafe { alloc.deallocate(raw.cast(), Layout::for_value(&value)) } + } Box::new_in(f(value), alloc) } } @@ -773,12 +777,16 @@ impl Box { let (raw, alloc) = Box::into_non_null_with_allocator(allocation); if size_of::() == size_of::() && align_of::() == align_of::() { let allocation = - // ignore-tidy-undocumented-unsafe + // SAFETY: We checked that the memory requirements are the same for both types + // and `raw` is already a valid pointer for the requisite memory. unsafe { Box::from_non_null_in(raw.cast::>(), alloc) }; try { Box::write(allocation, f(value)?) } } else { - // ignore-tidy-undocumented-unsafe - unsafe { alloc.deallocate(raw.cast(), Layout::for_value(&value)) } + if size_of::() != 0 { + // SAFETY: `raw` isn't dangling since it points to a non-zero-sized + // allocation and is never used again after this point. + unsafe { alloc.deallocate(raw.cast(), Layout::for_value(&value)) } + } try { Box::new_in(f(value)?, alloc) } } } @@ -923,7 +931,7 @@ impl Box<[T]> { #[stable(feature = "new_uninit", since = "1.82.0")] #[must_use] pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit]> { - // ignore-tidy-undocumented-unsafe + // SAFETY: `len` is exactly the capacity of this `RawVec`. unsafe { RawVec::with_capacity(len).into_box(len) } } @@ -947,7 +955,7 @@ impl Box<[T]> { #[stable(feature = "new_zeroed_alloc", since = "1.92.0")] #[must_use] pub fn new_zeroed_slice(len: usize) -> Box<[mem::MaybeUninit]> { - // ignore-tidy-undocumented-unsafe + // SAFETY: `len` is exactly the capacity of this `RawVec`. unsafe { RawVec::with_capacity_zeroed(len).into_box(len) } } @@ -981,7 +989,10 @@ impl Box<[T]> { }; Global.allocate(layout)?.cast() }; - // ignore-tidy-undocumented-unsafe + // SAFETY: `ptr` was just allocated with `Global` with the layout for an array of length + // `len`, and the layout creation would have failed if `len` overflowed an isize. + // `into_box` is sound to call since `len` corresponds to the length of the just-created + // `RawVec`. unsafe { Ok(RawVec::from_raw_parts_in(ptr.as_ptr(), len, Global).into_box(len)) } } @@ -1016,7 +1027,10 @@ impl Box<[T]> { }; Global.allocate_zeroed(layout)?.cast() }; - // ignore-tidy-undocumented-unsafe + // SAFETY: `ptr` was just allocated with `Global` with the layout for an array of length + // `len`, and the layout creation would have failed if `len` overflowed an isize. + // `into_box` is sound to call since `len` corresponds to the length of the just-created + // `RawVec`. unsafe { Ok(RawVec::from_raw_parts_in(ptr.as_ptr(), len, Global).into_box(len)) } } } @@ -1044,7 +1058,7 @@ impl Box<[T], A> { #[unstable(feature = "allocator_api", issue = "32838")] #[must_use] pub fn new_uninit_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit], A> { - // ignore-tidy-undocumented-unsafe + // SAFETY: `len` is exactly the capacity of this `RawVec`. unsafe { RawVec::with_capacity_in(len, alloc).into_box(len) } } @@ -1072,7 +1086,7 @@ impl Box<[T], A> { #[unstable(feature = "allocator_api", issue = "32838")] #[must_use] pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit], A> { - // ignore-tidy-undocumented-unsafe + // SAFETY: `len` is exactly the capacity of this `RawVec`. unsafe { RawVec::with_capacity_zeroed_in(len, alloc).into_box(len) } } @@ -1111,7 +1125,10 @@ impl Box<[T], A> { }; alloc.allocate(layout)?.cast() }; - // ignore-tidy-undocumented-unsafe + // SAFETY: `ptr` was just allocated with `alloc` with the layout for an array of length + // `len`, and the layout creation would have failed if `len` overflowed an isize. + // `into_box` is sound to call since `len` corresponds to the length of the just-created + // `RawVec`. unsafe { Ok(RawVec::from_raw_parts_in(ptr.as_ptr(), len, alloc).into_box(len)) } } @@ -1151,7 +1168,10 @@ impl Box<[T], A> { }; alloc.allocate_zeroed(layout)?.cast() }; - // ignore-tidy-undocumented-unsafe + // SAFETY: `ptr` was just allocated with `alloc` with the layout for an array of length + // `len`, and the layout creation would have failed if `len` overflowed an isize. + // `into_box` is sound to call since `len` corresponds to the length of the just-created + // `RawVec`. unsafe { Ok(RawVec::from_raw_parts_in(ptr.as_ptr(), len, alloc).into_box(len)) } } @@ -2013,10 +2033,15 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Box { let ptr = self.0; - // ignore-tidy-undocumented-unsafe - unsafe { - let layout = Layout::for_value_raw(ptr.as_ptr()); - if layout.size() != 0 { + // SAFETY: The construction site of the unsized box had ensured for us that the + // allocation was made with a valid layout (the size does not overflow an isize, + // possibly because the size of the type is 0). + let layout = unsafe { Layout::for_value_raw(ptr.as_ptr()) }; + if layout.size() != 0 { + // SAFETY: Any nonzero allocation would have been created with the allocator + // of this box and `layout` would fit that allocation. We also are the only ones + // responsible for doing this deallocation and know that the pointer must be valid. + unsafe { self.1.deallocate(From::from(ptr.cast()), layout); } } @@ -2568,3 +2593,11 @@ unsafe impl Allocator for Box { unsafe { (**self).shrink(ptr, old_layout, new_layout) } } } + +#[unstable(feature = "random", issue = "130703")] +impl core::random::Rng for Box { + #[inline] + fn fill_bytes(&mut self, bytes: &mut [u8]) { + (**self).fill_bytes(bytes) + } +} diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs index bef24fa822e6b..7d08991659787 100644 --- a/library/alloc/src/boxed/thin.rs +++ b/library/alloc/src/boxed/thin.rs @@ -167,7 +167,7 @@ impl Drop for ThinBox { fn drop(&mut self) { let value = self.deref_mut(); let value = value as *mut T; - // ignore-tidy-undocumented-unsafe + // SAFETY: `value` is valid for reads and writes for our `T`. unsafe { self.with_header().drop::(value); } @@ -249,7 +249,7 @@ impl WithHeader { debug_assert!(value_offset == 0 && T::IS_ZST && H::IS_ZST); layout.dangling_ptr() } else { - // ignore-tidy-undocumented-unsafe + // SAFETY: We check above that the layout size is nonzero. let ptr = unsafe { alloc::alloc(layout) }; if ptr.is_null() { alloc::handle_alloc_error(layout); @@ -265,7 +265,8 @@ impl WithHeader { let result = WithHeader(ptr, PhantomData); - // ignore-tidy-undocumented-unsafe + // SAFETY: `result.header()` promises to give us a valid place for writing + // the header, and `result.value()` promises the same for the value. unsafe { ptr::write(result.header(), header); ptr::write(result.value().cast(), value); @@ -291,7 +292,7 @@ impl WithHeader { debug_assert!(value_offset == 0 && T::IS_ZST && H::IS_ZST); layout.dangling_ptr() } else { - // ignore-tidy-undocumented-unsafe + // SAFETY: We check above that the layout size is nonzero. let ptr = unsafe { alloc::alloc(layout) }; if ptr.is_null() { return Err(core::alloc::AllocError); @@ -308,7 +309,8 @@ impl WithHeader { let result = WithHeader(ptr, PhantomData); - // ignore-tidy-undocumented-unsafe + // SAFETY: `result.header()` promises to give us a valid place for writing + // the header, and `result.value()` promises the same for the value. unsafe { ptr::write(result.header(), header); ptr::write(result.value().cast(), value); @@ -368,9 +370,10 @@ impl WithHeader { WithHeader(NonNull::new(value_ptr.cast()).unwrap(), PhantomData) } - // Safety: - // - Assumes that either `value` can be dereferenced, or is the - // `NonNull::dangling()` we use when both `T` and `H` are ZSTs. + /// # Safety + /// + /// `value` must point to an undropped owned `T`, and `self` must not be + /// accessed again after this is called. unsafe fn drop(&self, value: *mut T) { struct DropGuard { ptr: NonNull, diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 89b15a169dce0..539bf5c532552 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -160,6 +160,7 @@ #![feature(ptr_cast_slice)] #![feature(ptr_internals)] #![feature(ptr_metadata)] +#![feature(random)] #![feature(raw_os_error_ty)] #![feature(rev_into_inner)] #![feature(seek_stream_len)] diff --git a/library/alloc/src/raw_vec/mod.rs b/library/alloc/src/raw_vec/mod.rs index 250c666c70827..ffc92056cf464 100644 --- a/library/alloc/src/raw_vec/mod.rs +++ b/library/alloc/src/raw_vec/mod.rs @@ -245,11 +245,17 @@ impl RawVec { ); let me = ManuallyDrop::new(self); - // ignore-tidy-undocumented-unsafe - unsafe { - let slice = me.ptr().cast::>().cast_slice(len); - Box::from_raw_in(slice, ptr::read(&me.inner.alloc)) - } + let slice = me.ptr().cast::>().cast_slice(len); + // SAFETY: `slice` is a valid pointer for `len` `T`s, and the + // above `ManuallyDrop` ensures that the destructor of `me` which + // would free the allocation is never run. The caller upholds that + // `len` meets or exceeds the last requested capacity, ensuring that + // the layout generated when dropping the resulting `Box` fits the + // allocation the `RawVec` created. + // + // Moving the allocator out of `me.inner` is also sound since it is + // never accessed after this point. + unsafe { Box::from_raw_in(slice, ptr::read(&me.inner.alloc)) } } /// Reconstitutes a `RawVec` from a pointer, capacity, and allocator. @@ -438,7 +444,7 @@ const impl RawVecInner { fn with_capacity_in(capacity: usize, alloc: A, elem_layout: Layout) -> Self { match Self::try_allocate_in(capacity, AllocInit::Uninitialized, alloc, elem_layout) { Ok(this) => { - // ignore-tidy-undocumented-unsafe + // SAFETY: We already allocated at least `capacity`. unsafe { // Make it more obvious that a subsequent Vec::reserve(capacity) will not allocate. hint::assert_unchecked(!this.needs_to_grow(0, capacity, elem_layout)); @@ -482,7 +488,8 @@ const impl RawVecInner { // here should change to `ptr.len() / size_of::()`. Ok(Self { ptr: Unique::from(ptr.cast()), - // ignore-tidy-undocumented-unsafe + // SAFETY: We return early if `T` is a ZST, and if `capacity` would + // overflow an isize layout creation would have returned early as well. cap: unsafe { Cap::new_unchecked(capacity) }, alloc, }) @@ -554,7 +561,7 @@ const impl RawVecInner { ) -> Result, TryReserveError> { let new_layout = layout_array(cap, elem_layout)?; - // ignore-tidy-undocumented-unsafe + // SAFETY: Upheld by caller. let memory = if let Some((ptr, old_layout)) = unsafe { self.current_memory(elem_layout) } { // FIXME(const-hack): switch to `debug_assert_eq` debug_assert!(old_layout.align() == new_layout.align()); @@ -644,7 +651,7 @@ impl RawVecInner { // and could hypothetically handle differences between stride and size, but this memory // has already been allocated so we know it can't overflow and currently Rust does not // support such types. So we can do better by skipping some checks and avoid an unwrap. - // ignore-tidy-undocumented-unsafe + // SAFETY: Upheld by caller, unless the element size is 0 which is checked against. unsafe { let alloc_size = elem_layout.size().unchecked_mul(self.cap.as_inner()); let layout = Layout::from_size_align_unchecked(alloc_size, elem_layout.align()); @@ -678,7 +685,8 @@ impl RawVecInner { } if self.needs_to_grow(len, additional, elem_layout) { - // ignore-tidy-undocumented-unsafe + // SAFETY: `needs_to_grow` ensures that `len + additional` is greater than + // the current capacity, with the other preconditions upheld by our caller. unsafe { do_reserve_and_handle(self, len, additional, elem_layout); } @@ -701,7 +709,7 @@ impl RawVecInner { self.grow_amortized(len, additional, elem_layout)?; } } - // ignore-tidy-undocumented-unsafe + // SAFETY: If we've already grown, we will not need to again immediately after. unsafe { // Inform the optimizer that the reservation has succeeded or wasn't needed hint::assert_unchecked(!self.needs_to_grow(len, additional, elem_layout)); @@ -737,7 +745,7 @@ impl RawVecInner { self.grow_exact(len, additional, elem_layout)?; } } - // ignore-tidy-undocumented-unsafe + // SAFETY: If we've already grown, we will not need to again immediately after. unsafe { // Inform the optimizer that the reservation has succeeded or wasn't needed hint::assert_unchecked(!self.needs_to_grow(len, additional, elem_layout)); @@ -838,7 +846,8 @@ impl RawVecInner { /// big for LLVM to be willing to inline. /// /// # Safety - /// `cap <= self.capacity()` + /// - `cap <= self.capacity()` + /// - `elem_layout` must be valid for `self`. unsafe fn shrink_unchecked( &mut self, cap: usize, @@ -853,17 +862,20 @@ impl RawVecInner { // for the T::IS_ZST case since current_memory() will have returned // None. if cap == 0 { - // ignore-tidy-undocumented-unsafe + // SAFETY: T isn't a ZST if we're here and `ptr` is our pointer that `current_memory` + // ensures was allocated with `layout`. unsafe { self.alloc.deallocate(ptr, layout) }; self.ptr = - // ignore-tidy-undocumented-unsafe + // SAFETY: Alignment is guaranteed to be nonzero. unsafe { Unique::new_unchecked(ptr::without_provenance_mut(elem_layout.align())) }; self.cap = ZERO_CAP; } else { - // ignore-tidy-undocumented-unsafe + // SAFETY: `cap` is less than the previous capacity, which must have fit in an + // isize already for the non-ZST case. `shrink` is also sound to call since + // `current_memory` ensures `ptr` and `layout` are correct for the old allocation, + // while `new_layout` is computed with a smaller size than the old one per the + // requirement we instate on our callers. let ptr = unsafe { - // Layout cannot overflow here because it would have - // overflowed earlier when capacity was larger. let new_size = elem_layout.size().unchecked_mul(cap); let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); self.alloc diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 47ed22c156515..4741fe12ae89c 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -481,7 +481,10 @@ impl [T] { pub const fn into_vec(self: Box) -> Vec { let len = self.len(); let (b, alloc) = Box::into_raw_with_allocator(self); - // ignore-tidy-undocumented-unsafe + // SAFETY: `b` is currently allocated with `alloc` and was allocated with the + // matching layout for an array of `T * len`, the length is equal to the capacity, + // and the existence of a `Box<[T]>` is proof that the first `len` elements are + // valid `T`s. unsafe { Vec::from_raw_parts_in(b as *mut T, len, len, alloc) } } @@ -530,17 +533,24 @@ impl [T] { // If `m > 0`, there are remaining bits up to the leftmost '1'. while m > 0 { // `buf.extend(buf)`: - // ignore-tidy-undocumented-unsafe + // SAFETY: We're copying `len` elements after offsetting by `len`, + // with the previous call to `extend` ensuring that the first `len` + // elements are valid `T`s and the call to `with_capacity` ensuring + // we have `len * n` space to write the new elements. + // Each iteration of this loop doubles the number of initialised elements, + // which is tracked via `m` - when `m == 0`, we've written `most_significant_bit(n)` + // elements to the buffer. unsafe { ptr::copy_nonoverlapping::( buf.as_ptr(), (buf.as_mut_ptr()).add(buf.len()), buf.len(), ); - // `buf` has capacity of `self.len() * n`. - let buf_len = buf.len(); - buf.set_len(buf_len * 2); } + // `buf` has capacity of `self.len() * n`. + let buf_len = buf.len(); + // SAFETY: We initialised another `buf_len` elements above. + unsafe { buf.set_len(buf_len * 2) }; m >>= 1; } @@ -551,7 +561,14 @@ impl [T] { let rem_len = capacity - buf.len(); // `self.len() * rem` if rem_len > 0 { // `buf.extend(buf[0 .. rem_len])`: - // ignore-tidy-undocumented-unsafe + // SAFETY: We're copying `rem_len` elements after offsetting by `len`. The previous + // looping `copy_nonoverlapping` always doubled the number of instantiated elements, + // and so if `rem_len` was greater than `len` it would have allowed for another such + // doubling, until such time that `rem_len < len`. Thus, the space for these remaining + // `rem_len` elements must be preceded by more than `rem_len` previously-copied + // elements. + // Setting the length is correct since we've initialised the whole `capacity`-length + // space with copies of the previous `len` elements. unsafe { // This is non-overlapping since `2^expn > rem`. ptr::copy_nonoverlapping::( diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 4a9750c784fdb..b363b6862f7e5 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -2131,7 +2131,14 @@ impl String { "end of range should be a character boundary" ); - // ignore-tidy-undocumented-unsafe + if replace_with.len() > checked_range.len() { + self.reserve(replace_with.len() - checked_range.len()); + } + // SAFETY: We ensure that we're not replacing across a char boundary and + // that the new contents are valid UTF-8. The only potentially-unsound + // unwind from `splice` that would leave the string in an invalid state + // would be from an error growing the allocation, which we protect against + // by reserving it preemptively. unsafe { self.as_mut_vec() }.splice(checked_range, replace_with.bytes()); } diff --git a/library/compiler-builtins/crates/symcheck/src/main.rs b/library/compiler-builtins/crates/symcheck/src/main.rs index a88aeed40fb0d..b5d5fecd63cb6 100644 --- a/library/compiler-builtins/crates/symcheck/src/main.rs +++ b/library/compiler-builtins/crates/symcheck/src/main.rs @@ -210,6 +210,7 @@ impl Target { "nto" => Os::Nto, "nuttx" => Os::Nuttx, "openbsd" => Os::OpenBsd, + "ps3" => Os::Ps3, "psp" => Os::Psp, "psx" => Os::Psx, "qurt" => Os::Qurt, @@ -324,6 +325,7 @@ enum Os { Nto, Nuttx, OpenBsd, + Ps3, Psp, Psx, Qurt, diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index ca29cf2e19681..a99633456de0b 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -862,7 +862,10 @@ pub const fn forget(_: T); /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_allowed_through_unstable_modules = "import this function via `std::mem` instead"] +#[rustc_allowed_through_unstable_modules( + message = "import this function via the `mem` module instead", + module = "mem" +)] #[rustc_const_stable(feature = "const_transmute", since = "1.56.0")] #[rustc_diagnostic_item = "transmute"] #[rustc_nounwind] @@ -3138,7 +3141,10 @@ pub const fn ptr_metadata + PointeeSized, M>(ptr: // debug assertions; if you are writing compiler tests or code inside the standard library // that wants to avoid those debug assertions, directly call this intrinsic instead. #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_allowed_through_unstable_modules = "import this function via `std::ptr` instead"] +#[rustc_allowed_through_unstable_modules( + message = "import this function via the `ptr` module instead", + module = "ptr" +)] #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[rustc_nounwind] #[rustc_intrinsic] @@ -3149,7 +3155,10 @@ pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: us // debug assertions; if you are writing compiler tests or code inside the standard library // that wants to avoid those debug assertions, directly call this intrinsic instead. #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_allowed_through_unstable_modules = "import this function via `std::ptr` instead"] +#[rustc_allowed_through_unstable_modules( + message = "import this function via the `ptr` module instead", + module = "ptr" +)] #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[rustc_nounwind] #[rustc_intrinsic] @@ -3160,7 +3169,10 @@ pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize); // debug assertions; if you are writing compiler tests or code inside the standard library // that wants to avoid those debug assertions, directly call this intrinsic instead. #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_allowed_through_unstable_modules = "import this function via `std::ptr` instead"] +#[rustc_allowed_through_unstable_modules( + message = "import this function via the `ptr` module instead", + module = "ptr" +)] #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[rustc_nounwind] #[rustc_intrinsic] diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index 6c2f77a373393..3fb844c7c2927 100644 --- a/library/core/src/mem/manually_drop.rs +++ b/library/core/src/mem/manually_drop.rs @@ -1,7 +1,5 @@ -use crate::cmp::Ordering; -use crate::hash::{Hash, Hasher}; -use crate::marker::{Destruct, StructuralPartialEq}; -use crate::mem::MaybeDangling; +use crate::hash::Hash; +use crate::marker::Destruct; use crate::ops::{Deref, DerefMut, DerefPure}; use crate::ptr; @@ -152,11 +150,11 @@ use crate::ptr; /// [`MaybeUninit`]: crate::mem::MaybeUninit #[stable(feature = "manually_drop", since = "1.20.0")] #[lang = "manually_drop"] -#[derive(Copy, Clone, Debug, Default)] +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(transparent)] #[rustc_pub_transparent] pub struct ManuallyDrop { - value: MaybeDangling, + value: T, } impl ManuallyDrop { @@ -180,7 +178,7 @@ impl ManuallyDrop { #[inline(always)] #[rustc_no_writable] pub const fn new(value: T) -> ManuallyDrop { - ManuallyDrop { value: MaybeDangling::new(value) } + ManuallyDrop { value } } /// Extracts the value from the `ManuallyDrop` container. @@ -198,9 +196,7 @@ impl ManuallyDrop { #[rustc_const_stable(feature = "const_manually_drop", since = "1.32.0")] #[inline(always)] pub const fn into_inner(slot: ManuallyDrop) -> T { - // Cannot use `MaybeDangling::into_inner` as that does not yet have the desired semantics. - // SAFETY: We know this is a valid `T`. `slot` will not be dropped. - unsafe { (&raw const slot).cast::().read() } + slot.value } /// Takes the value from the `ManuallyDrop` container out. @@ -225,7 +221,7 @@ impl ManuallyDrop { pub const unsafe fn take(slot: &mut ManuallyDrop) -> T { // SAFETY: we are reading from a reference, which is guaranteed // to be valid for reads. - unsafe { ptr::read(slot.value.as_ref()) } + unsafe { ptr::read(&slot.value) } } } @@ -262,7 +258,7 @@ impl ManuallyDrop { // SAFETY: we are dropping the value pointed to by a mutable reference // which is guaranteed to be valid for writes. // It is up to the caller to make sure that `slot` isn't dropped again. - unsafe { ptr::drop_in_place(slot.value.as_mut()) } + unsafe { ptr::drop_in_place(&mut slot.value) } } } @@ -272,7 +268,7 @@ const impl Deref for ManuallyDrop { type Target = T; #[inline(always)] fn deref(&self) -> &T { - self.value.as_ref() + &self.value } } @@ -281,43 +277,9 @@ const impl Deref for ManuallyDrop { const impl DerefMut for ManuallyDrop { #[inline(always)] fn deref_mut(&mut self) -> &mut T { - self.value.as_mut() + &mut self.value } } #[unstable(feature = "deref_pure_trait", issue = "87121")] unsafe impl DerefPure for ManuallyDrop {} - -#[stable(feature = "manually_drop", since = "1.20.0")] -impl Eq for ManuallyDrop {} - -#[stable(feature = "manually_drop", since = "1.20.0")] -impl PartialEq for ManuallyDrop { - fn eq(&self, other: &Self) -> bool { - self.value.as_ref().eq(other.value.as_ref()) - } -} - -#[stable(feature = "manually_drop", since = "1.20.0")] -impl StructuralPartialEq for ManuallyDrop {} - -#[stable(feature = "manually_drop", since = "1.20.0")] -impl Ord for ManuallyDrop { - fn cmp(&self, other: &Self) -> Ordering { - self.value.as_ref().cmp(other.value.as_ref()) - } -} - -#[stable(feature = "manually_drop", since = "1.20.0")] -impl PartialOrd for ManuallyDrop { - fn partial_cmp(&self, other: &Self) -> Option { - self.value.as_ref().partial_cmp(other.value.as_ref()) - } -} - -#[stable(feature = "manually_drop", since = "1.20.0")] -impl Hash for ManuallyDrop { - fn hash(&self, state: &mut H) { - self.value.as_ref().hash(state); - } -} diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 5ea6cd03812f6..5d5eae5b26a19 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -953,7 +953,7 @@ impl Iterator for ReadDir { } } -/// Aborts the process if a file desceriptor is not open, if debug asserts are enabled +/// Aborts the process if a file descriptor is not open, if debug asserts are enabled /// /// Many IO syscalls can't be fully trusted about EBADF error codes because those /// might get bubbled up from a remote FUSE server rather than the file descriptor diff --git a/library/std/src/thread/lifecycle.rs b/library/std/src/thread/lifecycle.rs index d3a97bbf08fa2..11ab2190c5444 100644 --- a/library/std/src/thread/lifecycle.rs +++ b/library/std/src/thread/lifecycle.rs @@ -7,7 +7,6 @@ use super::thread::Thread; use super::{Result, spawnhook}; use crate::cell::UnsafeCell; use crate::marker::PhantomData; -use crate::mem::MaybeDangling; use crate::sync::Arc; use crate::sync::atomic::{Atomic, AtomicUsize, Ordering}; use crate::sys::{AsInner, IntoInner, thread as imp}; @@ -57,14 +56,9 @@ where Arc::new(Packet { scope: scope_data, result: UnsafeCell::new(None), _marker: PhantomData }); let their_packet = my_packet.clone(); - // Pass `f` in `MaybeDangling` because actually that closure might *run longer than the lifetime of `F`*. - // See for more details. - let f = MaybeDangling::new(f); - // The entrypoint of the Rust thread, after platform-specific thread // initialization is done. let rust_start = move || { - let f = f.into_inner(); let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| { crate::sys::backtrace::__rust_begin_short_backtrace(|| hooks.inherit_and_run()); crate::sys::backtrace::__rust_begin_short_backtrace(f) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index a729e1ebfb7bf..a85921214fe51 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -439,15 +439,6 @@ fn copy_self_contained_objects( ) }); - // wasm32-wasip3 doesn't exist in wasi-libc yet, so instead use libs - // from the wasm32-wasip2 target. Once wasi-libc supports wasip3 this - // should be deleted and the native objects should be used. - let srcdir = if target == "wasm32-wasip3" { - assert!(!srcdir.exists(), "wasip3 support is in wasi-libc, this should be updated now"); - builder.wasi_libdir(TargetSelection::from_user("wasm32-wasip2")).unwrap() - } else { - srcdir - }; for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] { copy_and_stamp( builder, @@ -2529,7 +2520,8 @@ impl CommandLineStep for Assemble { } // In addition to `rust-lld` also install `wasm-component-ld` when - // is enabled. This is used by the `wasm32-wasip2` target of Rust. + // is enabled. This is used by targets that produce WebAssembly + // components in Rust such as `wasm32-wasip{2,3}`. if builder.tool_enabled("wasm-component-ld") { let wasm_component = builder.ensure( crate::core::build_steps::tool::WasmComponentLd::for_use_by_compiler( diff --git a/src/ci/citool/Cargo.lock b/src/ci/citool/Cargo.lock index 4e0f51ee855e9..d6ffffb7b9f00 100644 --- a/src/ci/citool/Cargo.lock +++ b/src/ci/citool/Cargo.lock @@ -66,9 +66,9 @@ checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" [[package]] name = "askama" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf825125edd887a019d0a3a837dcc5499a68b0d034cc3eb594070c3e18addc" +checksum = "6024d73179f43f15ccd2b881bfea6fee7f3a46ec53f33b52210dea749ebebaa4" dependencies = [ "askama_macros", "itoa", @@ -79,9 +79,9 @@ dependencies = [ [[package]] name = "askama_derive" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1c7065972a130eafa84215f21352ae15b4a7393da48c1f5e103904490736738" +checksum = "071ee5ebf2138e3ad180e0aacf6940c2cab5e6d8333741d9925c7bee2b153f39" dependencies = [ "askama_parser", "basic-toml", @@ -92,23 +92,23 @@ dependencies = [ "rustc-hash", "serde", "serde_derive", - "syn 2.0.119", + "syn 3.0.3", ] [[package]] name = "askama_macros" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e23b1d2c4bd39a41971f6124cef4cc6fd0540913ecb90919b69ab3bbe44ae1a" +checksum = "643e1c7cbb6aec1d920332fe51a7c0d8219e273dcb8602db03f5263e4d16487b" dependencies = [ "askama_derive", ] [[package]] name = "askama_parser" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7db09fde9143e7ac4513358fb32ee32847125b63b18ea715afd487956da715da" +checksum = "2c5ae75772275d268b03ab8bdccdd12117b6169ee23256942b34e46c9f476583" dependencies = [ "rustc-hash", "serde", diff --git a/src/ci/citool/Cargo.toml b/src/ci/citool/Cargo.toml index 83d57b3294bbf..f7c3a8d9c8166 100644 --- a/src/ci/citool/Cargo.toml +++ b/src/ci/citool/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] anyhow = "1" -askama = "0.16.0" +askama = "0.16.1" clap = { version = "4.5", features = ["derive"] } csv = "1" diff = "0.1" diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile index efdbcbae63467..d753d16aff66c 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile @@ -104,6 +104,7 @@ ENV TARGETS=$TARGETS,wasm32-unknown-unknown ENV TARGETS=$TARGETS,wasm32-wasip1 ENV TARGETS=$TARGETS,wasm32-wasip1-threads ENV TARGETS=$TARGETS,wasm32-wasip2 +ENV TARGETS=$TARGETS,wasm32-wasip3 ENV TARGETS=$TARGETS,wasm32v1-none ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnux32 ENV TARGETS=$TARGETS,x86_64-fortanix-unknown-sgx diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index b9c79ab0128e9..f15c712c32b91 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -110,6 +110,7 @@ - [powerpc-unknown-linux-gnuspe](platform-support/powerpc-unknown-linux-gnuspe.md) - [powerpc-unknown-linux-muslspe](platform-support/powerpc-unknown-linux-muslspe.md) - [powerpc64-ibm-aix](platform-support/aix.md) + - [powerpc64-sony-ps3](platform-support/powerpc64-sony-ps3.md) - [powerpc64-unknown-linux-gnuelfv2](platform-support/powerpc64-unknown-linux-gnuelfv2.md) - [powerpc64-unknown-linux-musl](platform-support/powerpc64-unknown-linux-musl.md) - [powerpc64le-unknown-linux-gnu](platform-support/powerpc64le-unknown-linux-gnu.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 7518ee9fabbbc..54d9885c93955 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -218,6 +218,7 @@ target | std | notes [`wasm32-wasip1`](platform-support/wasm32-wasip1.md) | ✓ | WebAssembly with WASIp1 [`wasm32-wasip1-threads`](platform-support/wasm32-wasip1-threads.md) | ✓ | WebAssembly with WASI Preview 1 and threads [`wasm32-wasip2`](platform-support/wasm32-wasip2.md) | ✓ | WebAssembly with WASIp2 +[`wasm32-wasip3`](platform-support/wasm32-wasip3.md) | ✓ | WebAssembly with WASIp3 [`wasm32v1-none`](platform-support/wasm32v1-none.md) | * | WebAssembly limited to 1.0 features and no imports [`x86_64-apple-ios`](platform-support/apple-ios.md) | ✓ | 64-bit x86 iOS [`x86_64-apple-ios-macabi`](platform-support/apple-ios-macabi.md) | ✓ | Mac Catalyst on x86_64 @@ -388,6 +389,7 @@ target | std | host | notes [`powerpc-wrs-vxworks`](platform-support/vxworks.md) | ✓ | | [`powerpc-wrs-vxworks-spe`](platform-support/vxworks.md) | ✓ | | [`powerpc64-ibm-aix`](platform-support/aix.md) | ? | | 64-bit AIX (7.2 and newer) +[`powerpc64-sony-ps3`](platform-support/powerpc64-sony-ps3.md) | * | | PowerPC64 (BE) Sony PlayStation 3 (PS3) [`powerpc64-unknown-freebsd`](platform-support/freebsd.md) | ✓ | ✓ | PPC64 FreeBSD (ELFv2) [`powerpc64-unknown-linux-gnuelfv2`](platform-support/powerpc64-unknown-linux-gnuelfv2.md) | ✓ | ✓ | PPC64 Linux (ELFv2 ABI, kernel 3.2, glibc 2.17) [`powerpc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/powerpc64 @@ -445,7 +447,6 @@ target | std | host | notes [`thumbv8m.main-nuttx-eabihf`](platform-support/nuttx.md) | ✓ | | ARMv8M Mainline with NuttX, hardfloat [`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? | | WebAssembly [`wasm32-wali-linux-musl`](platform-support/wasm32-wali-linux.md) | ? | | WebAssembly with [WALI](https://github.com/arjunr2/WALI) -[`wasm32-wasip3`](platform-support/wasm32-wasip3.md) | ✓ | | WebAssembly with WASIp3 [`x86_64-apple-tvos`](platform-support/apple-tvos.md) | ✓ | | x86 64-bit tvOS [`x86_64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ | | x86 64-bit Apple WatchOS simulator [`x86_64-lynx-lynxos178`](platform-support/lynxos178.md) | | | x86_64 LynxOS-178 diff --git a/src/doc/rustc/src/platform-support/powerpc64-sony-ps3.md b/src/doc/rustc/src/platform-support/powerpc64-sony-ps3.md new file mode 100644 index 0000000000000..0c0c4327c355e --- /dev/null +++ b/src/doc/rustc/src/platform-support/powerpc64-sony-ps3.md @@ -0,0 +1,93 @@ +# `powerpc64-sony-ps3` + +**Tier: 3** + +Target for the Sony PlayStation 3 (shortened to "PS3"), for the PowerPC Processor Element (PPU) of the [Cell Broadband Engine Architecture (CBEA)](https://ieeexplore.ieee.org/document/5388675). + +## Target maintainers + +- [@ZephyrCodesStuff](https://github.com/ZephyrCodesStuff) (Primary developer and maintainer) +- [@RipleyTom](https://github.com/RipleyTom) (Fallback maintainer) + +## Requirements + +The target is a **big-endian PowerPC64 ELFv1** platform (the Cell Broadband Engine's PPE), and intended only for use on Sony PlayStation 3 systems, under the official operating system, "CellOS". + +The linker must support **Big-Endian PowerPC64 ELFv1**: the recommended and tested linker is [mold](https://github.com/rui314/mold). LLVM's `lld` does not correctly handle ELFv1 call relocations in freestanding `no_std` environments, making it incompatible. (See: [rust-lang/rust#85589](https://github.com/rust-lang/rust/issues/85589), [llvm/llvm-project#27630](https://github.com/llvm/llvm-project/issues/27630)) + +Resulting binaries require additional patching after linking to adhere to the PlayStation 3 operating system, in order to be bootable. An open-source patcher is available [here](https://github.com/ZephyrCodesStuff/rust-ps3/tree/main/moldier). Generally, a patcher must perform the following: + +- Rewrite the ELF OS/ABI to `0x66` (`ELFOSABI_CELLLV2`) +- Strip any GNU/Linux headers +- Add Sony-specific flags, sections (`.sys_proc_param` and `.sys_proc_prx_param`) and headers +- Add "stubs" for Sony SPRX dynamic-link libraries, by adding a section (`.lib.stub`) for CellOS to be able to link them +- Patch OPD function descriptors (in the `.opd` section) + +_**Note**: this list may not be exhaustive for all use cases, but is sufficient for producing a runnable binary. Producing a PRX dynamic library may require more/different steps._ + + +The target _fully supports_: + +- The Rust `core` features +- The Rust `alloc` feature, as the CellOS Lv2 kernel provides virtual memory allocation (`sys_memory_allocate`) on top of which a heap allocator (such as [talc](https://github.com/SFBdragon/talc)) can be implemented. +- AltiVec / VMX SIMD vector extensions (natively supported by LLVM via `+altivec`) + +## Building the target + +If `rustc` is built with this target enabled, no external C cross-compilation toolchain is strictly required to build the compiler host artifacts, but `mold` must be installed on the host system to perform linking. + +Support for using `lld` as a linker is unlikely, until support for ELFv1 is implemented on `lld`. + +## Building Rust programs + +Because this is a Tier 3 target, pre-compiled standard library artifacts (`core`, `alloc`) are not distributed via rustup. Programs must be built using a nightly toolchain with the `rust-src` component and `-Z build-std`. + +A Rust SDK ready for development exists open-sourced [here](https://github.com/Zephyrcodesstuff/rust-ps3) and is licensed `MIT OR Apache-2.0`. + +Configure your project `.cargo/config.toml`: +```toml +[target.powerpc64-sony-ps3] +linker = "mold" +rustflags = [ + "-C", "relocation-model=static", + "-C", "code-model=small", + "-C", "target-feature=+altivec", +] +``` + +**Prerequisites:** + +- A nightly Rust compiler with the `rust-src` component +- The [mold](https://github.com/rui314/mold) linker +- The [moldier](https://github.com/ZephyrCodesStuff/rust-ps3/tree/main/moldier) post-linker tool +- *(Optional)* `make_fself` or `scetool` for converting the output `.ELF` into an encrypted/signed `EBOOT.BIN` for running on real hardware. + +**Build process:** + +```bash +# Compile the binary +cargo +nightly build \ + --target powerpc64-sony-ps3 \ + -Z build-std=core,alloc \ + --release + +# Patch the linked executable +moldier patch target/powerpc64-sony-ps3/release/my_program.ELF + +# (Optional) Sign the binary for official hardware +make_fself "target/powerpc64-sony-ps3/release/my_program.ELF" "target/powerpc64-sony-ps3/release/my_program.BIN" +``` + +## Testing + +The target fully supports running binaries (once they're patched), both on official hardware and on [open-source emulators](https://github.com/rpcs3/rpcs3). + +As official firmware for the system forbids running unsigned code, the system must first be jailbroken in order to run binaries. This is not optional. + +Emulators do not impose any requirement regarding codesigning, thus testing on emulators is straightforward. + +Debugging is fully possible, either via debug firmware APIs on the official hardware, or on emulators via either their integrated debuggers, or a GDB server the emulator provides. + +## Cross-compilation toolchains and C code + +The target fully supports C/C++ code. Any compiler capable of producing binaries for a PowerPC64 big-endian processor can produce code to be embedded into the Rust program. diff --git a/src/doc/rustc/src/platform-support/wasm32-unknown-emscripten.md b/src/doc/rustc/src/platform-support/wasm32-unknown-emscripten.md index 0d15097468b17..fcf6e42be224b 100644 --- a/src/doc/rustc/src/platform-support/wasm32-unknown-emscripten.md +++ b/src/doc/rustc/src/platform-support/wasm32-unknown-emscripten.md @@ -25,14 +25,15 @@ does not (easily) support interop with C/C++ code. Please refer to the [wasm-bindgen](https://crates.io/crates/wasm-bindgen) crate in case you want to interoperate with JavaScript with this target. -Like Emscripten, the WASI targets [`wasm32-wasip1`](./wasm32-wasip1.md) and -[`wasm32-wasip2`](./wasm32-wasip2.md) also provide access to the host environment, -support interop with C/C++ (and other languages), and support most of the Rust -standard library. While the WASI targets are portable across different hosts -(web and non-web), WASI has no standard way of accessing web APIs, whereas -Emscripten has the ability to run arbitrary JS from WASM and access many web APIs. -If you are only targeting the web and need to access web APIs, the -`wasm32-unknown-emscripten` target may be preferable. +Like Emscripten, the WASI targets [`wasm32-wasip1`](./wasm32-wasip1.md), +[`wasm32-wasip2`](./wasm32-wasip2.md), and +[`wasm32-wasip3`](./wasm32-wasip3.md), also provide access to the host +environment, support interop with C/C++ (and other languages), and support most +of the Rust standard library. While the WASI targets are portable across +different hosts (web and non-web), WASI has no standard way of accessing web +APIs, whereas Emscripten has the ability to run arbitrary JS from WASM and +access many web APIs. If you are only targeting the web and need to access web +APIs, the `wasm32-unknown-emscripten` target may be preferable. ## Target maintainers diff --git a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md index 3dc608e704308..362bf6f255d9d 100644 --- a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md +++ b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md @@ -15,8 +15,9 @@ but many parts of the standard library do not work and return errors. For example `println!` does nothing, `std::fs` always return errors, and `std::thread::spawn` will panic. There is no means by which this can be overridden. For a WebAssembly target that more fully supports the standard -library see the [`wasm32-wasip1`](./wasm32-wasip1.md) or -[`wasm32-wasip2`](./wasm32-wasip2.md) targets. +library see the [`wasm32-wasip1`](./wasm32-wasip1.md), +[`wasm32-wasip2`](./wasm32-wasip2.md), or +[`wasm32-wasip3`](./wasm32-wasip3.md), targets. The `wasm32-unknown-unknown` target has full support for the `core` and `alloc` crates. It additionally supports the `HashMap` type in the `std` crate, although diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip3.md b/src/doc/rustc/src/platform-support/wasm32-wasip3.md index e8063a1bdcfed..4807adc0c2982 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wasip3.md +++ b/src/doc/rustc/src/platform-support/wasm32-wasip3.md @@ -1,42 +1,49 @@ # `wasm32-wasip3` -**Tier: 3** +**Tier: 2** The `wasm32-wasip3` target is the next stage of evolution of the [`wasm32-wasip2`](./wasm32-wasip2.md) target. The `wasm32-wasip3` target enables the Rust standard library to use WASIp3 APIs to implement various pieces of functionality. WASIp3 brings native async support over WASIp2, which integrates -well with Rust's `async` ecosystem. - -> **Note**: As of 2025-10-01 WASIp3 has not yet been approved by the WASI -> subgroup of the WebAssembly Community Group. Development is expected to -> conclude in late 2025 or early 2026. Until then the Rust standard library -> won't actually use WASIp3 APIs on the `wasm32-wasip3` target as they are not -> yet stable and would reduce the stability of this target. Once WASIp3 is -> approved, however, the standard library will update to use WASIp3 natively. - -> **Note**: This target does not yet build as of 2025-10-01 due to and update -> needed in the `libc` crate. Using it will require a `[patch]` for now. - -> **Note**: Until the standard library is fully migrated to use the `wasip3` -> crate then components produced for `wasm32-wasip3` may import WASIp2 APIs. -> This is considered a transitionary phase until fully support of libstd is -> implemented. +well with Rust's `async` ecosystem. Additionally a future release of Rust's +`wasm32-wasip3` target will support cooperative threading and `std::thread` +APIs. + +The original proposal for adding this target can be found in +[rust-lang/compiler-team#1001] and this target is first available on stable in +Rust 1.100.0. A notable major change from historical WebAssembly targets is that +the ABI of this target is slightly different. The linear memory shadow stack +pointer is stored in a component model task context slot instead of a +WebAssembly` global`. Additionally the base pointer of TLS is managed +differently than other targets. These changes are made to enable cooperative +multithreading on this target. + +> **Note**: As of 2026-09-03 cooperative multithreading is not yet supported on +> this target in Rust. The component model specification and library support +> work for this is in-development and not yet complete, but it's expected to be +> complete before the end of the year. Before that time spawning a thread via +> `std::thread` will return an error. Note though that this support can be +> tested through the [instructions below](#testing-cooperative-multithreading). + +[rust-lang/compiler-team#1001]: https://github.com/rust-lang/compiler-team/issues/1001 ## Target maintainers [@alexcrichton](https://github.com/alexcrichton) +[@yoshuawuyts](https://github.com/yoshuawuyts) ## Requirements -This target is cross-compiled. The target supports `std` fully. +This target is cross-compiled. The target supports `std` fully. This target +requires LLVM 23 to be used and additionally requires `wasi-sdk-34`-or-later if +you're building it locally or linking with this externally. ## Platform requirements -The WebAssembly runtime should support both WASIp2 and WASIp3. Runtimes also -are required to support components since this target outputs a component as -opposed to a core wasm module. Two example runtimes for WASIp3 are [Wasmtime] -and [Jco]. +WebAssembly runtimes that want to execute components compiled for this target +must support WASI 0.3.0 and the requisite required component model features +(notably async). Two example runtimes for WASIp3 are [Wasmtime] and [Jco]. [Wasmtime]: https://wasmtime.dev/ [Jco]: https://github.com/bytecodealliance/jco @@ -44,14 +51,14 @@ and [Jco]. ## Building the target To build this target first acquire a copy of -[`wasi-sdk`](https://github.com/WebAssembly/wasi-sdk/). At this time version 22 +[`wasi-sdk`](https://github.com/WebAssembly/wasi-sdk/). At this time version 34 is the minimum needed. Next configure the `WASI_SDK_PATH` environment variable to point to where this is installed. For example: ```text -export WASI_SDK_PATH=/path/to/wasi-sdk-22.0 +export WASI_SDK_PATH=/path/to/wasi-sdk-34.0 ``` Next be sure to enable LLD when building Rust from source as LLVM's `wasm-ld` @@ -81,3 +88,91 @@ It's recommended to conditionally compile code for this target with: The default set of WebAssembly features enabled for compilation is currently the same as [`wasm32-unknown-unknown`](./wasm32-unknown-unknown.md). See the documentation there for more information. + +## Testing Cooperative Multithreading + +The [component model specification][spec] is in the process of adding intrinsics +to support cooperative multithreading in a component guest. These intrinsics can +be found in the [explainer] and are all gated by the 🧵 emoji. Support for +cooperative multithreading is a work-in-progress and not yet complete, but the +adventurous can configure this target to go ahead and test things out. + +The majority of changes necessary to get cooperative multithreading lie within +Rust's [wasi-libc dependency][wasi-libc]. This means that to test cooperative +multithreading a different build than the default wasi-libc needs to be used. +Starting with [wasi-sdk-34] there is a temporary sysroot which contains support +for a wasip3 target that has multithreading enabled in wasi-libc. To test out +the `wasm32-wasip3` Rust target with threads your compilation needs to be +configured to use this sysroot. + +An example of doing this is this program: + +```rust +fn main() { + std::thread::spawn(|| { + println!("hi"); + }) + .join() + .unwrap(); +} +``` + +is compiled and run by default as: + +```console +$ rustc foo.rs --target wasm32-wasip3 +$ wasmtime foo.wasm + +thread 'main' (1) panicked at library/std/src/thread/functions.rs:131:29: +failed to spawn thread: Os { code: 58, kind: Unsupported, message: "Not supported" } +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +Error: failed to run main module `foo.wasm` + +... +``` + +which shows that by default threads cannot be spawned. By configuring a custom +sysroot to be used, however: + +```console +$ rustc foo.rs --target wasm32-wasip3 \ + -Clink-self-contained=n \ + -Clinker=$WASI_SDK_PATH/bin/wasm32-wasip3-clang \ + -Clink-arg=--sysroot=$WASI_SDK_PATH/share/wasi-sysroot/experimental-coop-threads \ + -Clink-arg=-Wl,--export=cabi_realloc +$ wasmtime -W component-model-threading foo.wasm +hi +``` + +Here `-Clink-self-contained=n` avoids the vendored files in the standard library +which come from a build of wasi-libc incompatible with cooperative +multithreading. The `-Clinker` flag changes to use `clang` to be able to pass a +custom `--sysroot` argument and follow its logic for startup objects. The +`--sysroot` flag then points to the experimental sysroot for coop threads and +`--export` is required right now as a minor workaround. + +When compiling with Cargo you can use these environment variables: + +```console +$ export CARGO_TARGET_WASM32_WASIP3_LINKER=$WASI_SDK_PATH/bin/wasm32-wasip3-clang +$ export CARGO_TARGET_WASM32_WASIP3_RUNNER='wasmtime -W component-model-threading' +$ export CARGO_TARGET_WASM32_WASIP3_RUSTFLAGS="\ + -Clink-self-contained=n \ + -Clink-arg=--sysroot=$WASI_SDK_PATH/share/wasi-sysroot/experimental-coop-threads \ + -Clink-arg=-Wl,--export=cabi_realloc" +$ cargo run --target wasm32-wasip3 +hi +``` + +Standard synchronization primitives in `std::thread` and `std::sync` should all +work on this target with cooperative multithreading. Should you run into any +issues please don't hesitate to file an issue and cc the target maintainers. + +Note that it is currently intended that by the end of 2026 this support will all +be enabled by default and this section of the documentation will be deleted +since working with threads should "just work". + +[spec]: https://github.com/webassembly/component-model +[explainer]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/Explainer.md +[wasi-libc]: https://github.com/webassembly/wasi-libc +[wasi-sdk-34]: https://github.com/WebAssembly/wasi-sdk/releases/tag/wasi-sdk-34 diff --git a/src/etc/gdb_providers.py b/src/etc/gdb_providers.py index a6ef59738c8c7..9c50d7e472000 100644 --- a/src/etc/gdb_providers.py +++ b/src/etc/gdb_providers.py @@ -330,7 +330,7 @@ def cast_to_internal(node): for i in xrange(0, length + 1): if height > 0: - child_ptr = edges[i]["value"]["value"][ZERO_FIELD] + child_ptr = edges[i]["value"]["value"] for child in children_of_node(child_ptr, height - 1): yield child if i < length: @@ -338,12 +338,12 @@ def cast_to_internal(node): key_type_size = keys.type.sizeof val_type_size = vals.type.sizeof key = ( - keys[i]["value"]["value"][ZERO_FIELD] + keys[i]["value"]["value"] if key_type_size > 0 else gdb.parse_and_eval("()") ) val = ( - vals[i]["value"]["value"][ZERO_FIELD] + vals[i]["value"]["value"] if val_type_size > 0 else gdb.parse_and_eval("()") ) diff --git a/src/etc/htmldocck.py b/src/etc/htmldocck.py index 46a3a1602ac71..6011492ed27c9 100755 --- a/src/etc/htmldocck.py +++ b/src/etc/htmldocck.py @@ -624,8 +624,16 @@ def check_command(c, cache): def check(target, commands): cache = CachedFiles(target) + run_commands = 0 for c in commands: check_command(c, cache) + run_commands += 1 + if run_commands == 0 and os.environ.get("IS_RMAKE") is None: + stderr( + "\nNo check, move this file in `rustdoc-ui` testsuite if you want to check " + + "it doesn't crash" + ) + raise SystemExit(1) if __name__ == "__main__": diff --git a/src/etc/natvis/libcore.natvis b/src/etc/natvis/libcore.natvis index 4e2f09743a031..20ce1cae447cf 100644 --- a/src/etc/natvis/libcore.natvis +++ b/src/etc/natvis/libcore.natvis @@ -35,9 +35,9 @@ - {value.__0} + {value} - value.__0 + value diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 1da46d9f6328a..19600ff2bb63e 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -10,7 +10,7 @@ path = "lib.rs" [dependencies] # tidy-alphabetical-start arrayvec = { version = "0.7", default-features = false } -askama = { version = "0.16.0", default-features = false, features = ["alloc", "config", "derive"] } +askama = { version = "0.16.1", default-features = false, features = ["alloc", "config", "derive"] } base64 = "0.21.7" indexmap = { version = "2", features = ["serde"] } itertools = "0.15" diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 04c54e134b48e..db63dbaa24663 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -685,6 +685,7 @@ fn human_readable_target_os(os: Symbol) -> Option<&'static str> { Nto => "QNX SDP 7.x", NuttX => "NuttX", OpenBsd => "OpenBSD", + Ps3 => "Play Station 3", Psp => "Play Station Portable", Psx => "Play Station 1", Qnx => "QNX SDP 8.0+", diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 784a80ef02cd2..2b1a37cbcda30 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -45,11 +45,10 @@ use rustc_hir::def::{CtorKind, DefKind, MacroKinds, Res}; use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LOCAL_CRATE, LocalDefId}; use rustc_hir::{PredicateOrigin, find_attr}; use rustc_hir_analysis::{lower_const_arg_for_rustdoc, lower_ty}; -use rustc_middle::metadata::Reexport; +use rustc_middle::middle::resolve::Reexport; use rustc_middle::middle::resolve_bound_vars as rbv; use rustc_middle::ty::{ - self, AdtKind, GenericArgsRef, RegionExt, Ty, TyCtxt, TypeVisitableExt, TypingMode, - Unnormalized, + self, AdtKind, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt, TypingMode, Unnormalized, }; use rustc_middle::{bug, span_bug}; use rustc_span::ExpnKind; @@ -354,7 +353,7 @@ pub(crate) fn clean_const_item_rhs<'tcx>( ) -> ConstantKind { match ct_rhs { hir::ConstItemRhs::Body(body) => ConstantKind::Local { def_id: parent, body }, - hir::ConstItemRhs::TypeConst(ct) => clean_const(ct), + hir::ConstItemRhs::Direct(ct) => clean_const(ct), } } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 47b701e3c42d7..7a99ce8d39e9c 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -451,7 +451,7 @@ impl Item { // were never supposed to work at all. let stab = self.stability(tcx)?; if let rustc_hir::StabilityLevel::Stable { - allowed_through_unstable_modules: Some(note), + allowed_through_unstable_modules: Some((note, _)), .. } = stab.level { @@ -2534,7 +2534,7 @@ mod size_asserts { static_assert_size!(GenericParamDef, 40); static_assert_size!(Generics, 16); static_assert_size!(Item, 8); - static_assert_size!(ItemInner, 136); + static_assert_size!(ItemInner, 144); static_assert_size!(ItemKind, 48); static_assert_size!(PathSegment, 32); static_assert_size!(Type, 32); diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs index 35e254c754d68..c04438d69007b 100644 --- a/src/librustdoc/passes/lint/redundant_explicit_links.rs +++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs @@ -3,8 +3,9 @@ use std::ops::Range; use rustc_ast::NodeId; use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level, SuggestionStyle}; use rustc_hir::HirId; -use rustc_hir::def::{DefKind, DocLinkResMap, Namespace, Res}; +use rustc_hir::def::{DefKind, Namespace, Res}; use rustc_lint::Applicability; +use rustc_middle::middle::resolve::DocLinkResMap; use rustc_resolve::rustdoc::pulldown_cmark::{ BrokenLink, BrokenLinkCallback, CowStr, Event, LinkType, OffsetIter, Parser, Tag, }; diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml index d83ebdcce2149..1dee95965ebd1 100644 --- a/src/tools/clippy/Cargo.toml +++ b/src/tools/clippy/Cargo.toml @@ -39,7 +39,7 @@ serde_json = "1.0.122" walkdir = "2.3" itertools = "0.15" pulldown-cmark = { version = "0.11", default-features = false, features = ["html"] } -askama = { version = "0.16.0", default-features = false, features = ["alloc", "config", "derive"] } +askama = { version = "0.16.1", default-features = false, features = ["alloc", "config", "derive"] } [dev-dependencies.toml] version = "1.1" diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index 6230349651026..919b9b8ba8368 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -965,7 +965,7 @@ fn get_const_hir_value<'tcx>( }; match ct_rhs { ConstItemRhs::Body(body_id) => Some((tcx.typeck(did), tcx.hir_body(body_id).value)), - ConstItemRhs::TypeConst(ct_arg) => match ct_arg.kind { + ConstItemRhs::Direct(ct_arg) => match ct_arg.kind { ConstArgKind::Anon(anon_const) => Some((tcx.typeck(did), tcx.hir_body(anon_const.body).value)), _ => None, }, diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index bcdc7754da6fa..8ca6d08e325f7 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -1187,7 +1187,7 @@ pub fn is_zero_integer_const(cx: &LateContext<'_>, expr: &Expr<'_>, ctxt: Syntax pub fn const_item_rhs_to_expr<'tcx>(tcx: TyCtxt<'tcx>, ct_rhs: ConstItemRhs<'tcx>) -> Option<&'tcx Expr<'tcx>> { match ct_rhs { ConstItemRhs::Body(body_id) => Some(tcx.hir_body(body_id).value), - ConstItemRhs::TypeConst(const_arg) => match const_arg.kind { + ConstItemRhs::Direct(const_arg) => match const_arg.kind { ConstArgKind::Anon(anon) => Some(tcx.hir_body(anon.body).value), ConstArgKind::Struct(..) | ConstArgKind::Tup(..) diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 217ff1ecd664d..5ba7c0496e906 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -2791,7 +2791,8 @@ pub fn expr_use_sites<'tcx>( | Node::TyPat(_) | Node::WherePredicate(_) | Node::TestBinderForall(_) - | Node::TestBinderExists(_) => { + | Node::TestBinderExists(_) + | Node::TestBinderBoundTypeConstraint(_) => { // This shouldn't be possible to hit; the inner iterator should have // been moved to the end before we hit any of these nodes. debug_assert!(false, "found {parent:?} which is after the final use node"); diff --git a/src/tools/compiletest/src/runtest/rustdoc.rs b/src/tools/compiletest/src/runtest/rustdoc.rs index bee5c86ce62ed..03371e2f745c0 100644 --- a/src/tools/compiletest/src/runtest/rustdoc.rs +++ b/src/tools/compiletest/src/runtest/rustdoc.rs @@ -1,10 +1,19 @@ use super::{DocKind, TestCx, remove_and_create_dir_all}; use crate::util::ArgFileCommand; +fn has_test_flag(flags: &[String]) -> bool { + flags.iter().any(|s| s == "--test") +} + impl TestCx<'_> { pub(super) fn run_rustdoc_html_test(&self) { assert!(self.variant.revision.is_none(), "revisions not supported in this test suite"); + if has_test_flag(&self.props.compile_flags) || has_test_flag(&self.props.doc_flags) { + panic!( + "If you want to check `--test`, put this test into `rustdoc-ui` testsuite instead", + ); + } let out_dir = self.output_base_dir(); remove_and_create_dir_all(&out_dir).unwrap_or_else(|e| { panic!("failed to remove and recreate output directory `{out_dir}`: {e}") diff --git a/src/tools/generate-copyright/Cargo.toml b/src/tools/generate-copyright/Cargo.toml index 91236ff6c6040..b7c60266f98ca 100644 --- a/src/tools/generate-copyright/Cargo.toml +++ b/src/tools/generate-copyright/Cargo.toml @@ -8,7 +8,7 @@ description = "Produces a manifest of all the copyrighted materials in the Rust [dependencies] anyhow = "1.0.65" -askama = "0.16.0" +askama = "0.16.1" cargo_metadata = "0.21" serde = { version = "1.0.147", features = ["derive"] } serde_json = "1.0.85" diff --git a/src/tools/miri/tests/fail/async-shared-mutable.stack.stderr b/src/tools/miri/tests/fail/async-shared-mutable.stack.stderr index bdd004d5da99f..4435541bc0a1c 100644 --- a/src/tools/miri/tests/fail/async-shared-mutable.stack.stderr +++ b/src/tools/miri/tests/fail/async-shared-mutable.stack.stderr @@ -9,12 +9,8 @@ LL | *x = 1; help: was created by a Unique retag at offsets [RANGE] --> tests/fail/async-shared-mutable.rs:LL:CC | -LL | / core::future::poll_fn(move |_| { -LL | | *x = 1; -LL | | Poll::<()>::Pending -LL | | }) -LL | | .await - | |______________^ +LL | let x = &mut 0u8; + | ^^^^^^^^ help: was later invalidated at offsets [RANGE] by a SharedReadOnly retag --> tests/fail/async-shared-mutable.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/async-shared-mutable.tree.stderr b/src/tools/miri/tests/fail/async-shared-mutable.tree.stderr index f9e75082758dd..bbb62a7e27b2b 100644 --- a/src/tools/miri/tests/fail/async-shared-mutable.tree.stderr +++ b/src/tools/miri/tests/fail/async-shared-mutable.tree.stderr @@ -10,12 +10,8 @@ LL | *x = 1; help: the accessed tag was created here, in the initial state Reserved --> tests/fail/async-shared-mutable.rs:LL:CC | -LL | / core::future::poll_fn(move |_| { -LL | | *x = 1; -LL | | Poll::<()>::Pending -LL | | }) -LL | | .await - | |______________^ +LL | let x = &mut 0u8; + | ^^^^^^^^ help: the accessed tag later transitioned to Unique due to a child write access at offsets [RANGE] --> tests/fail/async-shared-mutable.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/unaligned_pointers/maybe_dangling_unalighed.stderr b/src/tools/miri/tests/fail/unaligned_pointers/maybe_dangling_unalighed.stderr index 190976c4f046f..594c91352d796 100644 --- a/src/tools/miri/tests/fail/unaligned_pointers/maybe_dangling_unalighed.stderr +++ b/src/tools/miri/tests/fail/unaligned_pointers/maybe_dangling_unalighed.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: constructing invalid value of type std::mem::MaybeDangling<&u16>: encountered an unaligned reference (required ALIGN byte alignment but found ALIGN) +error: Undefined Behavior: constructing invalid value of type std::mem::MaybeDangling<&u16>: at .0, encountered an unaligned reference (required ALIGN byte alignment but found ALIGN) --> tests/fail/unaligned_pointers/maybe_dangling_unalighed.rs:LL:CC | LL | transmute::, MaybeDangling<&u16>>(unaligned) diff --git a/src/tools/miri/tests/fail/validity/maybe_dangling_null.stderr b/src/tools/miri/tests/fail/validity/maybe_dangling_null.stderr index 041a6b1b96e0c..da8c88e16a1fe 100644 --- a/src/tools/miri/tests/fail/validity/maybe_dangling_null.stderr +++ b/src/tools/miri/tests/fail/validity/maybe_dangling_null.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: constructing invalid value of type std::mem::MaybeDangling<&u8>: encountered a null reference +error: Undefined Behavior: constructing invalid value of type std::mem::MaybeDangling<&u8>: at .0, encountered a null reference --> tests/fail/validity/maybe_dangling_null.rs:LL:CC | LL | unsafe { transmute::, MaybeDangling<&u8>>(null) }; diff --git a/src/tools/miri/tests/fail/validity/maybe_dangling_ref_too_big.stderr b/src/tools/miri/tests/fail/validity/maybe_dangling_ref_too_big.stderr index f0966586d4dc7..2c82b2719e711 100644 --- a/src/tools/miri/tests/fail/validity/maybe_dangling_ref_too_big.stderr +++ b/src/tools/miri/tests/fail/validity/maybe_dangling_ref_too_big.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: constructing invalid value of type std::mem::MaybeDangling<&i8>: encountered a reference that is too close to the end of the address space for a pointee of 1 bytes +error: Undefined Behavior: constructing invalid value of type std::mem::MaybeDangling<&i8>: at .0, encountered a reference that is too close to the end of the address space for a pointee of 1 bytes --> tests/fail/validity/maybe_dangling_ref_too_big.rs:LL:CC | LL | let _x: MaybeDangling<&i8> = unsafe { transmute(usize::MAX) }; diff --git a/src/tools/miri/tests/pass/both_borrows/maybe_dangling.rs b/src/tools/miri/tests/pass/both_borrows/maybe_dangling.rs index 028dcef8fa2d3..2d37344d24072 100644 --- a/src/tools/miri/tests/pass/both_borrows/maybe_dangling.rs +++ b/src/tools/miri/tests/pass/both_borrows/maybe_dangling.rs @@ -14,6 +14,7 @@ fn main() { reference(); write_through_shared_ref(); large(); + closure(); } fn boxy() { @@ -64,3 +65,16 @@ fn large() { // Used to be rejected due to faulty logic for the "does this fit the address space" check. let _x: MaybeDangling<&i8> = unsafe { mem::transmute(usize::MAX - 127) }; } + +// A closure acts like MaybeDangling. +fn closure() { + fn invoke(f: impl FnOnce()) { + // The closure has captured a reference that will be freed while `invoke` runs. + f() + } + + let p = Box::leak(Box::new(0i32)); + invoke(move || { + drop(unsafe { Box::from_raw(p) }); + }); +} diff --git a/src/tools/miri/tests/pass/generators.rs b/src/tools/miri/tests/pass/generators.rs new file mode 100644 index 0000000000000..c5ab3fcb8e28f --- /dev/null +++ b/src/tools/miri/tests/pass/generators.rs @@ -0,0 +1,115 @@ +//@edition: 2024 +//@revisions: stack tree tree_implicit_writes +//@[tree_implicit_writes]compile-flags: -Zmiri-tree-borrows -Zmiri-tree-borrows-implicit-writes +//@[tree]compile-flags: -Zmiri-tree-borrows + +#![feature(gen_blocks)] + +fn main() { + basic(); + iterate(); + movable_gen(); + movable_gen2(); +} + +fn basic() { + gen fn foo() -> i32 { + yield 42; + for i in 5..10 { + if i % 2 == 0 { + continue; + } + yield i * 2; + } + } + + let v = foo().collect::>(); + assert_eq!(v, &[42, 10, 14, 18]); +} + +fn iterate() { + fn foo() -> impl Iterator { + gen { + yield 42; + for x in 3..6 { + yield x + } + } + } + + fn moved() -> impl Iterator { + let mut x = "foo".to_string(); + gen move { + yield 42; + if x == "foo" { + return; + } + x.clear(); + for x in 3..6 { + yield x + } + } + } + + let mut iter = foo(); + assert_eq!(iter.next(), Some(42)); + assert_eq!(iter.next(), Some(3)); + assert_eq!(iter.next(), Some(4)); + assert_eq!(iter.next(), Some(5)); + assert_eq!(iter.next(), None); + // `gen` blocks are fused + assert_eq!(iter.next(), None); + + let mut iter = moved(); + assert_eq!(iter.next(), Some(42)); + assert_eq!(iter.next(), None); +} + +/// Ensure a generator can reborrow from a reference it captured. +/// Regression test for . +pub fn movable_gen() { + fn make_gen(r: &mut u8) -> impl Iterator { + gen move { + let a = r; + *a = 1; + yield 1; + *a = 2; + } + } + + let mut a = 1; + let mut i = make_gen(&mut a); + assert_eq!(i.next(), Some(1)); + let mut j = i; + assert_eq!(j.next(), None); +} + +/// Regression test for . +fn movable_gen2() { + // a struct that has a drop flag and contains a reference + struct DropMut(&'static mut T); + impl Drop for DropMut { + fn drop(&mut self) { + drop(unsafe { Box::from_raw(self.0) }); + } + } + + let mut a = gen { + let b = DropMut(Box::leak(Box::new(1))); + + // create a drop flag on `b` + let c; + if true { + c = b; // and ensure it's set to false + } else { + c = DropMut(Box::leak(Box::new(2))); + } + + *c.0 = 3; + 4.yield; + *c.0 = 5; + }; + let _ = a.next(); + let mut d = a; + let _ = d.next(); +} diff --git a/src/tools/miri/tests/pass/stacked_borrows/stack-printing.stdout b/src/tools/miri/tests/pass/stacked_borrows/stack-printing.stdout index 296339e738455..838733078209d 100644 --- a/src/tools/miri/tests/pass/stacked_borrows/stack-printing.stdout +++ b/src/tools/miri/tests/pass/stacked_borrows/stack-printing.stdout @@ -1,6 +1,6 @@ 0..1: [ SharedReadWrite ] 0..1: [ SharedReadWrite ] 0..1: [ SharedReadWrite ] -0..1: [ SharedReadWrite Unique Unique Unique Unique Unique Unique Unique ] -0..1: [ SharedReadWrite Disabled Disabled Disabled Disabled Disabled Disabled Disabled SharedReadOnly ] +0..1: [ SharedReadWrite Unique Unique Unique Unique Unique ] +0..1: [ SharedReadWrite Disabled Disabled Disabled Disabled Disabled SharedReadOnly ] 0..1: [ unknown-bottom(..) ] diff --git a/src/tools/run-make-support/src/external_deps/htmldocck.rs b/src/tools/run-make-support/src/external_deps/htmldocck.rs index 621d386d85f71..50fd77be678cb 100644 --- a/src/tools/run-make-support/src/external_deps/htmldocck.rs +++ b/src/tools/run-make-support/src/external_deps/htmldocck.rs @@ -9,5 +9,6 @@ use crate::source_root; pub fn htmldocck() -> Command { let mut python = python_command(); python.arg(source_root().join("src/etc/htmldocck.py")); + python.env("IS_RMAKE", "1"); python } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs index 1672e8e7930e3..c314b3f37c04d 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs @@ -114,7 +114,7 @@ const KNOWN_ARCH: [&str; 20] = [ const KNOWN_ENV: [&str; 7] = ["eabihf", "gnu", "gnueabihf", "msvc", "relibc", "sgx", "uclibc"]; -const KNOWN_OS: [&str; 20] = [ +const KNOWN_OS: [&str; 21] = [ "cuda", "dragonfly", "emscripten", @@ -128,6 +128,7 @@ const KNOWN_OS: [&str; 20] = [ "netbsd", "none", "openbsd", + "ps3", "psp", "redox", "solaris", diff --git a/tests/assembly-llvm/targets/targets-elf.rs b/tests/assembly-llvm/targets/targets-elf.rs index 49bced1dd5bd2..beefbdb889940 100644 --- a/tests/assembly-llvm/targets/targets-elf.rs +++ b/tests/assembly-llvm/targets/targets-elf.rs @@ -403,6 +403,9 @@ //@ revisions: msp430_none_elf //@ [msp430_none_elf] compile-flags: --target msp430-none-elf //@ [msp430_none_elf] needs-llvm-components: msp430 +//@ revisions: powerpc64_sony_ps3 +//@ [powerpc64_sony_ps3] compile-flags: --target powerpc64-sony-ps3 +//@ [powerpc64_sony_ps3] needs-llvm-components: powerpc //@ revisions: powerpc64_unknown_freebsd //@ [powerpc64_unknown_freebsd] compile-flags: --target powerpc64-unknown-freebsd //@ [powerpc64_unknown_freebsd] needs-llvm-components: powerpc diff --git a/tests/codegen-llvm/maybe_dangling_refs.rs b/tests/codegen-llvm/maybe_dangling_refs.rs index 07493ecac79c5..5d097151db4d7 100644 --- a/tests/codegen-llvm/maybe_dangling_refs.rs +++ b/tests/codegen-llvm/maybe_dangling_refs.rs @@ -7,7 +7,7 @@ #![crate_type = "lib"] #![feature(maybe_dangling)] -use std::mem::MaybeDangling; +use std::mem::{ManuallyDrop, MaybeDangling}; // CHECK: define {{(dso_local )?}}noundef nonnull ptr @f(ptr noundef nonnull %x) unnamed_addr #[no_mangle] @@ -15,6 +15,12 @@ pub fn f(x: MaybeDangling>) -> MaybeDangling> { x } +// CHECK: define {{(dso_local )?}}noundef nonnull ptr @f2(ptr noundef nonnull %x) unnamed_addr +#[no_mangle] +pub fn f2(x: ManuallyDrop>) -> ManuallyDrop> { + x +} + // CHECK: define {{(dso_local )?}}noundef nonnull ptr @g(ptr noundef nonnull %x) unnamed_addr #[no_mangle] pub fn g(x: MaybeDangling<&u8>) -> MaybeDangling<&u8> { diff --git a/tests/mir-opt/building/write_box_via_move.box_new.CleanupPostBorrowck.after.mir b/tests/mir-opt/building/write_box_via_move.box_new.CleanupPostBorrowck.after.mir index 0050151e89b1b..158a1ea103a63 100644 --- a/tests/mir-opt/building/write_box_via_move.box_new.CleanupPostBorrowck.after.mir +++ b/tests/mir-opt/building/write_box_via_move.box_new.CleanupPostBorrowck.after.mir @@ -23,7 +23,7 @@ fn box_new(_1: T) -> Box<[T; 1024]> { _4 = move _2; StorageLive(_5); _5 = copy _1; - ((((*_4).1: std::mem::ManuallyDrop<[T; 1024]>).0: std::mem::MaybeDangling<[T; 1024]>).0: [T; 1024]) = [move _5; 1024]; + (((*_4).1: std::mem::ManuallyDrop<[T; 1024]>).0: [T; 1024]) = [move _5; 1024]; StorageDead(_5); _3 = move _4; drop(_4) -> [return: bb2, unwind: bb5]; diff --git a/tests/mir-opt/building/write_box_via_move.vec_macro.CleanupPostBorrowck.after.mir b/tests/mir-opt/building/write_box_via_move.vec_macro.CleanupPostBorrowck.after.mir index 2410e4d31b486..d2f67cd6932c2 100644 --- a/tests/mir-opt/building/write_box_via_move.vec_macro.CleanupPostBorrowck.after.mir +++ b/tests/mir-opt/building/write_box_via_move.vec_macro.CleanupPostBorrowck.after.mir @@ -12,7 +12,7 @@ fn vec_macro() -> Vec { } bb1: { - ((((*_2).1: std::mem::ManuallyDrop<[i32; 8]>).0: std::mem::MaybeDangling<[i32; 8]>).0: [i32; 8]) = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32, const 6_i32, const 7_i32]; + (((*_2).1: std::mem::ManuallyDrop<[i32; 8]>).0: [i32; 8]) = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32, const 6_i32, const 7_i32]; _1 = move _2; drop(_2) -> [return: bb2, unwind: bb4]; } diff --git a/tests/mir-opt/coroutine/unwind_in_vec.build-{closure#0}.built.after.mir b/tests/mir-opt/coroutine/unwind_in_vec.build-{closure#0}.built.after.mir index fc75f261ea01b..6b9927949ffe2 100644 --- a/tests/mir-opt/coroutine/unwind_in_vec.build-{closure#0}.built.after.mir +++ b/tests/mir-opt/coroutine/unwind_in_vec.build-{closure#0}.built.after.mir @@ -91,7 +91,7 @@ yields () bb6: { StorageDead(_19); - ((((*_5).1: std::mem::ManuallyDrop<[std::string::String; 5]>).0: std::mem::MaybeDangling<[std::string::String; 5]>).0: [std::string::String; 5]) = [move _6, move _9, move _12, move _15, move _18]; + (((*_5).1: std::mem::ManuallyDrop<[std::string::String; 5]>).0: [std::string::String; 5]) = [move _6, move _9, move _12, move _15, move _18]; drop(_18) -> [return: bb7, unwind: bb25, drop: bb15]; } diff --git a/tests/mir-opt/issue_62289.test.ElaborateDrops.after.panic-abort.mir b/tests/mir-opt/issue_62289.test.ElaborateDrops.after.panic-abort.mir index afee76707e8a4..e8efb9b7c3483 100644 --- a/tests/mir-opt/issue_62289.test.ElaborateDrops.after.panic-abort.mir +++ b/tests/mir-opt/issue_62289.test.ElaborateDrops.after.panic-abort.mir @@ -55,7 +55,7 @@ fn test() -> Option> { _11 = copy ((_5 as Continue).0: u32); _4 = copy _11; StorageDead(_11); - ((((*_3).1: std::mem::ManuallyDrop<[u32; 1]>).0: std::mem::MaybeDangling<[u32; 1]>).0: [u32; 1]) = [move _4]; + (((*_3).1: std::mem::ManuallyDrop<[u32; 1]>).0: [u32; 1]) = [move _4]; StorageDead(_4); _2 = move _3; goto -> bb7; diff --git a/tests/mir-opt/issue_62289.test.ElaborateDrops.after.panic-unwind.mir b/tests/mir-opt/issue_62289.test.ElaborateDrops.after.panic-unwind.mir index d44db1eb1c8c6..4da1eed4484bb 100644 --- a/tests/mir-opt/issue_62289.test.ElaborateDrops.after.panic-unwind.mir +++ b/tests/mir-opt/issue_62289.test.ElaborateDrops.after.panic-unwind.mir @@ -55,7 +55,7 @@ fn test() -> Option> { _11 = copy ((_5 as Continue).0: u32); _4 = copy _11; StorageDead(_11); - ((((*_3).1: std::mem::ManuallyDrop<[u32; 1]>).0: std::mem::MaybeDangling<[u32; 1]>).0: [u32; 1]) = [move _4]; + (((*_3).1: std::mem::ManuallyDrop<[u32; 1]>).0: [u32; 1]) = [move _4]; StorageDead(_4); _2 = move _3; goto -> bb7; diff --git a/tests/mir-opt/pre-codegen/loops.vec_move.runtime-optimized.after.mir b/tests/mir-opt/pre-codegen/loops.vec_move.runtime-optimized.after.mir index a49688ae891de..cad38c437e3c3 100644 --- a/tests/mir-opt/pre-codegen/loops.vec_move.runtime-optimized.after.mir +++ b/tests/mir-opt/pre-codegen/loops.vec_move.runtime-optimized.after.mir @@ -3,327 +3,309 @@ fn vec_move(_1: Vec) -> () { debug v => _1; let mut _0: (); + let mut _21: std::vec::IntoIter; let mut _22: std::vec::IntoIter; - let mut _23: std::vec::IntoIter; - let mut _24: &mut std::vec::IntoIter; - let mut _25: std::option::Option; - let mut _26: isize; - let _28: (); + let mut _23: &mut std::vec::IntoIter; + let mut _24: std::option::Option; + let mut _25: isize; + let _27: (); scope 1 { - debug iter => _23; - let _27: impl Sized; + debug iter => _22; + let _26: impl Sized; scope 2 { - debug x => _27; + debug x => _26; } } scope 3 (inlined as IntoIterator>::into_iter) { debug self => _1; - let _3: std::mem::ManuallyDrop>; - let mut _4: *const std::alloc::Global; - let mut _8: usize; - let mut _10: *mut impl Sized; - let mut _11: *const impl Sized; - let mut _12: usize; - let _29: &std::vec::Vec; - let mut _30: &std::mem::ManuallyDrop>; - let mut _31: &alloc::raw_vec::RawVec; - let mut _32: &std::mem::ManuallyDrop>; - let _33: &std::vec::Vec; - let mut _34: &std::mem::ManuallyDrop>; - let _35: &std::vec::Vec; - let mut _36: &std::mem::ManuallyDrop>; - let mut _37: &alloc::raw_vec::RawVec; - let mut _38: &std::mem::ManuallyDrop>; + let _2: std::mem::ManuallyDrop>; + let mut _3: *const std::alloc::Global; + let mut _7: usize; + let mut _9: *mut impl Sized; + let mut _10: *const impl Sized; + let mut _11: usize; + let _28: &std::vec::Vec; + let mut _29: &std::mem::ManuallyDrop>; + let mut _30: &alloc::raw_vec::RawVec; + let mut _31: &std::mem::ManuallyDrop>; + let _32: &std::vec::Vec; + let mut _33: &std::mem::ManuallyDrop>; + let _34: &std::vec::Vec; + let mut _35: &std::mem::ManuallyDrop>; + let mut _36: &alloc::raw_vec::RawVec; + let mut _37: &std::mem::ManuallyDrop>; scope 4 { - debug me => _3; + debug me => _2; scope 5 { - debug alloc => const ManuallyDrop:: {{ value: MaybeDangling::(std::alloc::Global) }}; - let _6: std::ptr::NonNull; + debug alloc => const ManuallyDrop:: {{ value: std::alloc::Global }}; + let _5: std::ptr::NonNull; scope 6 { - debug buf => _6; - let _7: *mut impl Sized; + debug buf => _5; + let _6: *mut impl Sized; scope 7 { - debug begin => _7; + debug begin => _6; scope 8 { - debug end => _11; - let _20: usize; + debug end => _10; + let _19: usize; scope 9 { - debug cap => _20; + debug cap => _19; } - scope 45 (inlined > as Deref>::deref) { - debug self => _38; - scope 46 (inlined MaybeDangling::>::as_ref) { - } - } - scope 47 (inlined alloc::raw_vec::RawVec::::capacity) { + scope 39 (inlined > as Deref>::deref) { debug self => _37; - let mut _39: &alloc::raw_vec::RawVecInner; - scope 48 (inlined std::mem::size_of::) { + } + scope 40 (inlined alloc::raw_vec::RawVec::::capacity) { + debug self => _36; + let mut _38: &alloc::raw_vec::RawVecInner; + scope 41 (inlined std::mem::size_of::) { } - scope 49 (inlined alloc::raw_vec::RawVecInner::capacity) { - debug self => _39; + scope 42 (inlined alloc::raw_vec::RawVecInner::capacity) { + debug self => _38; debug elem_size => const ::SIZE; - let mut _21: core::num::niche_types::UsizeNoHighBit; - scope 50 (inlined core::num::niche_types::UsizeNoHighBit::as_inner) { - debug self => _21; + let mut _20: core::num::niche_types::UsizeNoHighBit; + scope 43 (inlined core::num::niche_types::UsizeNoHighBit::as_inner) { + debug self => _20; } } } } - scope 29 (inlined > as Deref>::deref) { - debug self => _34; - scope 30 (inlined MaybeDangling::>::as_ref) { - } - } - scope 31 (inlined Vec::::len) { + scope 25 (inlined > as Deref>::deref) { debug self => _33; - let mut _13: bool; - scope 32 { + } + scope 26 (inlined Vec::::len) { + debug self => _32; + let mut _12: bool; + scope 27 { } } - scope 33 (inlined std::ptr::mut_ptr::::wrapping_byte_add) { - debug self => _7; - debug count => _12; - let mut _14: *mut u8; - let mut _18: *mut u8; - let mut _19: *const impl Sized; - scope 34 (inlined std::ptr::mut_ptr::::cast::) { - debug self => _7; + scope 28 (inlined std::ptr::mut_ptr::::wrapping_byte_add) { + debug self => _6; + debug count => _11; + let mut _13: *mut u8; + let mut _17: *mut u8; + let mut _18: *const impl Sized; + scope 29 (inlined std::ptr::mut_ptr::::cast::) { + debug self => _6; } - scope 35 (inlined std::ptr::mut_ptr::::wrapping_add) { - debug self => _14; - debug count => _12; - let mut _15: isize; - scope 36 (inlined std::ptr::mut_ptr::::wrapping_offset) { - debug self => _14; - debug count => _15; + scope 30 (inlined std::ptr::mut_ptr::::wrapping_add) { + debug self => _13; + debug count => _11; + let mut _14: isize; + scope 31 (inlined std::ptr::mut_ptr::::wrapping_offset) { + debug self => _13; + debug count => _14; + let mut _15: *const u8; let mut _16: *const u8; - let mut _17: *const u8; } } - scope 37 (inlined std::ptr::mut_ptr::::with_metadata_of::) { - debug self => _18; - debug meta => _19; - scope 38 (inlined std::ptr::metadata::) { - debug ptr => _19; + scope 32 (inlined std::ptr::mut_ptr::::with_metadata_of::) { + debug self => _17; + debug meta => _18; + scope 33 (inlined std::ptr::metadata::) { + debug ptr => _18; } - scope 39 (inlined std::ptr::from_raw_parts_mut::) { + scope 34 (inlined std::ptr::from_raw_parts_mut::) { } } } - scope 40 (inlined > as Deref>::deref) { - debug self => _36; - scope 41 (inlined MaybeDangling::>::as_ref) { - } - } - scope 42 (inlined Vec::::len) { + scope 35 (inlined > as Deref>::deref) { debug self => _35; - let mut _9: bool; - scope 43 { + } + scope 36 (inlined Vec::::len) { + debug self => _34; + let mut _8: bool; + scope 37 { } } - scope 44 (inlined #[track_caller] std::ptr::mut_ptr::::add) { - debug self => _7; - debug count => _8; + scope 38 (inlined #[track_caller] std::ptr::mut_ptr::::add) { + debug self => _6; + debug count => _7; } } - scope 28 (inlined NonNull::::as_ptr) { - debug self => _6; - } - } - scope 20 (inlined > as Deref>::deref) { - debug self => _32; - scope 21 (inlined MaybeDangling::>::as_ref) { + scope 24 (inlined NonNull::::as_ptr) { + debug self => _5; } } - scope 22 (inlined alloc::raw_vec::RawVec::::non_null) { + scope 17 (inlined > as Deref>::deref) { debug self => _31; - scope 23 (inlined alloc::raw_vec::RawVecInner::non_null::) { - let mut _5: std::ptr::NonNull; - scope 24 (inlined std::ptr::Unique::::cast::) { - scope 25 (inlined NonNull::::cast::) { - scope 26 (inlined NonNull::::as_ptr) { + } + scope 18 (inlined alloc::raw_vec::RawVec::::non_null) { + debug self => _30; + scope 19 (inlined alloc::raw_vec::RawVecInner::non_null::) { + let mut _4: std::ptr::NonNull; + scope 20 (inlined std::ptr::Unique::::cast::) { + scope 21 (inlined NonNull::::cast::) { + scope 22 (inlined NonNull::::as_ptr) { } } } - scope 27 (inlined std::ptr::Unique::::as_non_null_ptr) { + scope 23 (inlined std::ptr::Unique::::as_non_null_ptr) { } } } } - scope 12 (inlined > as Deref>::deref) { - debug self => _30; - scope 13 (inlined MaybeDangling::>::as_ref) { - } - } - scope 14 (inlined Vec::::allocator) { + scope 11 (inlined > as Deref>::deref) { debug self => _29; - scope 15 (inlined alloc::raw_vec::RawVec::::allocator) { - scope 16 (inlined alloc::raw_vec::RawVecInner::allocator) { + } + scope 12 (inlined Vec::::allocator) { + debug self => _28; + scope 13 (inlined alloc::raw_vec::RawVec::::allocator) { + scope 14 (inlined alloc::raw_vec::RawVecInner::allocator) { } } } - scope 17 (inlined #[track_caller] std::ptr::read::) { - debug src => _4; + scope 15 (inlined #[track_caller] std::ptr::read::) { + debug src => _3; } - scope 18 (inlined ManuallyDrop::::new) { + scope 16 (inlined ManuallyDrop::::new) { debug value => const std::alloc::Global; - scope 19 (inlined MaybeDangling::::new) { - } } } scope 10 (inlined ManuallyDrop::>::new) { debug value => _1; - let mut _2: std::mem::MaybeDangling>; - scope 11 (inlined MaybeDangling::>::new) { - } } } bb0: { - StorageLive(_22); - StorageLive(_11); - StorageLive(_20); - StorageLive(_5); - StorageLive(_17); - StorageLive(_3); - StorageLive(_2); - _2 = MaybeDangling::>(copy _1); - _3 = ManuallyDrop::> { value: move _2 }; - StorageDead(_2); + StorageLive(_21); + StorageLive(_10); + StorageLive(_19); StorageLive(_4); - // DBG: _30 = &_3; - // DBG: _29 = &((_3.0: std::mem::MaybeDangling>).0: std::vec::Vec); - _4 = &raw const (((((_3.0: std::mem::MaybeDangling>).0: std::vec::Vec).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).2: std::alloc::Global); - StorageDead(_4); + StorageLive(_16); + StorageLive(_2); + _2 = ManuallyDrop::> { value: copy _1 }; + StorageLive(_3); + // DBG: _29 = &_2; + // DBG: _28 = &(_2.0: std::vec::Vec); + _3 = &raw const ((((_2.0: std::vec::Vec).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).2: std::alloc::Global); + StorageDead(_3); + StorageLive(_5); + // DBG: _31 = &_2; + // DBG: _30 = &((_2.0: std::vec::Vec).0: alloc::raw_vec::RawVec); + _4 = copy (((((_2.0: std::vec::Vec).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique).0: std::ptr::NonNull); + _5 = copy _4 as std::ptr::NonNull (Transmute); StorageLive(_6); - // DBG: _32 = &_3; - // DBG: _31 = &(((_3.0: std::mem::MaybeDangling>).0: std::vec::Vec).0: alloc::raw_vec::RawVec); - _5 = copy ((((((_3.0: std::mem::MaybeDangling>).0: std::vec::Vec).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique).0: std::ptr::NonNull); - _6 = copy _5 as std::ptr::NonNull (Transmute); - StorageLive(_7); - _7 = copy _5 as *mut impl Sized (Transmute); + _6 = copy _4 as *mut impl Sized (Transmute); switchInt(const ::IS_ZST) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_10); - StorageLive(_8); - // DBG: _36 = &_3; - // DBG: _35 = &((_3.0: std::mem::MaybeDangling>).0: std::vec::Vec); - _8 = copy (((_3.0: std::mem::MaybeDangling>).0: std::vec::Vec).1: usize); StorageLive(_9); - _9 = Le(copy _8, const ::MAX_SLICE_LEN); - assume(move _9); - StorageDead(_9); - _10 = Offset(copy _7, copy _8); - _11 = copy _10 as *const impl Sized (PtrToPtr); + StorageLive(_7); + // DBG: _35 = &_2; + // DBG: _34 = &(_2.0: std::vec::Vec); + _7 = copy ((_2.0: std::vec::Vec).1: usize); + StorageLive(_8); + _8 = Le(copy _7, const ::MAX_SLICE_LEN); + assume(move _8); StorageDead(_8); - StorageDead(_10); + _9 = Offset(copy _6, copy _7); + _10 = copy _9 as *const impl Sized (PtrToPtr); + StorageDead(_7); + StorageDead(_9); goto -> bb4; } bb2: { + StorageLive(_11); + // DBG: _33 = &_2; + // DBG: _32 = &(_2.0: std::vec::Vec); + _11 = copy ((_2.0: std::vec::Vec).1: usize); StorageLive(_12); - // DBG: _34 = &_3; - // DBG: _33 = &((_3.0: std::mem::MaybeDangling>).0: std::vec::Vec); - _12 = copy (((_3.0: std::mem::MaybeDangling>).0: std::vec::Vec).1: usize); + _12 = Le(copy _11, const ::MAX_SLICE_LEN); + assume(move _12); + StorageDead(_12); + StorageLive(_17); StorageLive(_13); - _13 = Le(copy _12, const ::MAX_SLICE_LEN); - assume(move _13); - StorageDead(_13); - StorageLive(_18); + _13 = copy _4 as *mut u8 (Transmute); StorageLive(_14); - _14 = copy _5 as *mut u8 (Transmute); + _14 = copy _11 as isize (IntToInt); StorageLive(_15); - _15 = copy _12 as isize (IntToInt); - StorageLive(_16); - _16 = copy _5 as *const u8 (Transmute); - _17 = arith_offset::(move _16, move _15) -> [return: bb3, unwind unreachable]; + _15 = copy _4 as *const u8 (Transmute); + _16 = arith_offset::(move _15, move _14) -> [return: bb3, unwind unreachable]; } bb3: { - StorageDead(_16); - _18 = copy _17 as *mut u8 (PtrToPtr); StorageDead(_15); + _17 = copy _16 as *mut u8 (PtrToPtr); StorageDead(_14); - StorageLive(_19); - _19 = copy _5 as *const impl Sized (Transmute); - StorageDead(_19); + StorageDead(_13); + StorageLive(_18); + _18 = copy _4 as *const impl Sized (Transmute); StorageDead(_18); - StorageDead(_12); - _11 = copy _17 as *const impl Sized (PtrToPtr); + StorageDead(_17); + StorageDead(_11); + _10 = copy _16 as *const impl Sized (PtrToPtr); goto -> bb4; } bb4: { - // DBG: _38 = &_3; - // DBG: _37 = &(((_3.0: std::mem::MaybeDangling>).0: std::vec::Vec).0: alloc::raw_vec::RawVec); - // DBG: _39 = &((((_3.0: std::mem::MaybeDangling>).0: std::vec::Vec).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner); + // DBG: _37 = &_2; + // DBG: _36 = &((_2.0: std::vec::Vec).0: alloc::raw_vec::RawVec); + // DBG: _38 = &(((_2.0: std::vec::Vec).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner); switchInt(const ::SIZE) -> [0: bb5, otherwise: bb6]; } bb5: { - _20 = const usize::MAX; + _19 = const usize::MAX; goto -> bb7; } bb6: { - StorageLive(_21); - _21 = copy (((((_3.0: std::mem::MaybeDangling>).0: std::vec::Vec).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).1: core::num::niche_types::UsizeNoHighBit); - _20 = copy _21 as usize (Transmute); - StorageDead(_21); + StorageLive(_20); + _20 = copy ((((_2.0: std::vec::Vec).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).1: core::num::niche_types::UsizeNoHighBit); + _19 = copy _20 as usize (Transmute); + StorageDead(_20); goto -> bb7; } bb7: { - _22 = std::vec::IntoIter:: { buf: copy _6, phantom: const ZeroSized: PhantomData, cap: move _20, alloc: const ManuallyDrop:: {{ value: MaybeDangling::(std::alloc::Global) }}, ptr: copy _6, end: copy _11 }; - StorageDead(_7); + _21 = std::vec::IntoIter:: { buf: copy _5, phantom: const ZeroSized: PhantomData, cap: move _19, alloc: const ManuallyDrop:: {{ value: std::alloc::Global }}, ptr: copy _5, end: copy _10 }; StorageDead(_6); - StorageDead(_3); - StorageDead(_17); StorageDead(_5); - StorageDead(_20); - StorageDead(_11); - StorageLive(_23); - _23 = move _22; + StorageDead(_2); + StorageDead(_16); + StorageDead(_4); + StorageDead(_19); + StorageDead(_10); + StorageLive(_22); + _22 = move _21; goto -> bb8; } bb8: { - StorageLive(_25); StorageLive(_24); - _24 = &mut _23; - _25 = as Iterator>::next(move _24) -> [return: bb9, unwind: bb15]; + StorageLive(_23); + _23 = &mut _22; + _24 = as Iterator>::next(move _23) -> [return: bb9, unwind: bb15]; } bb9: { - _26 = discriminant(_25); - switchInt(move _26) -> [0: bb10, 1: bb12, otherwise: bb14]; + _25 = discriminant(_24); + switchInt(move _25) -> [0: bb10, 1: bb12, otherwise: bb14]; } bb10: { + StorageDead(_23); StorageDead(_24); - StorageDead(_25); - drop(_23) -> [return: bb11, unwind continue]; + drop(_22) -> [return: bb11, unwind continue]; } bb11: { - StorageDead(_23); StorageDead(_22); + StorageDead(_21); return; } bb12: { - StorageLive(_27); - _27 = move ((_25 as Some).0: impl Sized); - _28 = opaque::(move _27) -> [return: bb13, unwind: bb15]; + StorageLive(_26); + _26 = move ((_24 as Some).0: impl Sized); + _27 = opaque::(move _26) -> [return: bb13, unwind: bb15]; } bb13: { - StorageDead(_27); + StorageDead(_26); + StorageDead(_23); StorageDead(_24); - StorageDead(_25); goto -> bb8; } @@ -332,7 +314,7 @@ fn vec_move(_1: Vec) -> () { } bb15 (cleanup): { - drop(_23) -> [return: bb16, unwind terminate(cleanup)]; + drop(_22) -> [return: bb16, unwind terminate(cleanup)]; } bb16 (cleanup): { diff --git a/tests/rustdoc-gui/decl-macro-in-sidebar.goml b/tests/rustdoc-gui/decl-macro-in-sidebar.goml new file mode 100644 index 0000000000000..d32fee94065c1 --- /dev/null +++ b/tests/rustdoc-gui/decl-macro-in-sidebar.goml @@ -0,0 +1,9 @@ +// This test ensures that the `foo` decl macro is present in the module sidebar. +// Because these items are not generated into the HTML, we can't make them a `rustdoc-html` +// test, so here we go... + +go-to: "file://" + |DOC_PATH| + "/test_docs/details/index.html" +assert-text: ( + '//*[@id="rustdoc-modnav"]/ul[@class="block macro"]//a[@href="../macro.decl_macro.html"]', + "decl_macro", +) diff --git a/tests/rustdoc-gui/src/test_docs/lib.rs b/tests/rustdoc-gui/src/test_docs/lib.rs index c9932dcf158aa..54db340e7ba64 100644 --- a/tests/rustdoc-gui/src/test_docs/lib.rs +++ b/tests/rustdoc-gui/src/test_docs/lib.rs @@ -14,6 +14,7 @@ #![feature(macro_derive)] #![feature(negative_impls)] #![feature(doc_notable_trait)] +#![feature(decl_macro)] /*! Enable the feature some-feature to enjoy @@ -822,3 +823,7 @@ pub mod notable { pub struct Wrapper; impl Labeled for Wrapper {} } + +pub macro decl_macro { + () => { "bar" } +} diff --git a/tests/rustdoc-html/doc-cfg/all-targets.rs b/tests/rustdoc-html/doc-cfg/all-targets.rs index d5a8be83bc1d3..aec251878781e 100644 --- a/tests/rustdoc-html/doc-cfg/all-targets.rs +++ b/tests/rustdoc-html/doc-cfg/all-targets.rs @@ -79,11 +79,11 @@ pub fn bar() {} // Emscripten and ESP-IDF and FreeBSD and Fuchsia and GNU/Hurd and Haiku \ // and HelenOS and Hermit and Horizon and illumos and iOS and L4Re and Linux \ // and LynxOS-178 and macOS and Managarm and Motor OS and NetBSD and NuttX \ -// and OpenBSD and Play Station 1 and Play Station Portable and Play Station Vita \ -// and QNX SDP 7.x and QNX SDP 8.0+ and QuRT and Redox OS and RTEMS OS and Solaris and \ -// SOLID ASP3 and TEEOS and Trusty and tvOS and UEFI and VEXos and visionOS \ -// and VxWorks and WASI and watchOS and Windows and Xous and zero knowledge \ -// Virtual Machine only.' +// and OpenBSD and Play Station 1 and Play Station 3 and Play Station Portable \ +// and Play Station Vita and QNX SDP 7.x and QNX SDP 8.0+ and QuRT and Redox OS \ +// and RTEMS OS and Solaris and SOLID ASP3 and TEEOS and Trusty and tvOS and UEFI \ +// and VEXos and visionOS and VxWorks and WASI and watchOS and Windows and Xous \ +// and zero knowledge Virtual Machine only.' #[doc(cfg(all( target_os = "aix", target_os = "amdhsa", @@ -114,6 +114,7 @@ pub fn bar() {} target_os = "qnx", target_os = "nuttx", target_os = "openbsd", + target_os = "ps3", target_os = "psp", target_os = "psx", target_os = "qurt", diff --git a/tests/rustdoc-html/doc-cfg/extern-items.rs b/tests/rustdoc-html/doc-cfg/extern-items.rs index 369f8a7b22ee9..bf5121639a7e3 100644 --- a/tests/rustdoc-html/doc-cfg/extern-items.rs +++ b/tests/rustdoc-html/doc-cfg/extern-items.rs @@ -5,15 +5,15 @@ #![feature(doc_cfg)] #![crate_name = "foo"] -//@has 'foo/index.html' -//@count - '//*[@class="stab portability"]' 2 -//@has - '//*[@class="stab portability"]' 'Non-banana' +//@ has 'foo/index.html' +//@ count - '//*[@class="stab portability"]' 2 +//@ has - '//*[@class="stab portability"]' 'Non-banana' -//@has 'foo/fn.doc_cfg_doesnt_work.html' -//@has - '//*[@class="stab portability"]' 'Available on non-crate feature banana only.' +//@ has 'foo/fn.doc_cfg_doesnt_work.html' +//@ has - '//*[@class="stab portability"]' 'Available on non-crate feature banana only.' -//@has 'foo/fn.doc_cfg_works.html' -//@has - '//*[@class="stab portability"]' 'Available on non-crate feature banana only.' +//@ has 'foo/fn.doc_cfg_works.html' +//@ has - '//*[@class="stab portability"]' 'Available on non-crate feature banana only.' unsafe extern "C" { #[cfg(not(feature = "banana"))] diff --git a/tests/rustdoc-html/doc-cfg/impl-foreign-type.rs b/tests/rustdoc-html/doc-cfg/impl-foreign-type.rs index 81af598a55361..d28fa86c8ead5 100644 --- a/tests/rustdoc-html/doc-cfg/impl-foreign-type.rs +++ b/tests/rustdoc-html/doc-cfg/impl-foreign-type.rs @@ -6,8 +6,8 @@ #![feature(doc_cfg)] #![crate_name = "foo"] -//@has 'foo/trait.Blob.html' -//@has - '//*[@id="impl-Blob-for-Box%3CR%3E"]//*[@class="stab portability"]' 'Available on non-crate feature alloc only.' +//@ has 'foo/trait.Blob.html' +//@ has - '//*[@id="impl-Blob-for-Box%3CR%3E"]//*[@class="stab portability"]' 'Available on non-crate feature alloc only.' pub trait Blob {} diff --git a/tests/rustdoc-html/doc-cfg/reexports.rs b/tests/rustdoc-html/doc-cfg/reexports.rs index a5f54155ab2d4..25f40ae648050 100644 --- a/tests/rustdoc-html/doc-cfg/reexports.rs +++ b/tests/rustdoc-html/doc-cfg/reexports.rs @@ -6,17 +6,17 @@ #![feature(doc_cfg)] #![crate_name = "foo"] -//@has 'foo/struct.FlatBanana.html' -//@has - '//*[@class="item-info"]/*[@class="stab portability"]' 'Available on non-crate feature banana and non-crate feature yoyo only.' +//@ has 'foo/struct.FlatBanana.html' +//@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'Available on non-crate feature banana and non-crate feature yoyo only.' -//@has 'foo/struct.SubBanana.html' -//@has - '//*[@class="item-info"]/*[@class="stab portability"]' 'Available on non-crate feature ananas and non-crate feature banana and non-crate feature yoyo only.' +//@ has 'foo/struct.SubBanana.html' +//@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'Available on non-crate feature ananas and non-crate feature banana and non-crate feature yoyo only.' #[cfg(not(feature = "yoyo"))] pub use self::banana::*; -//@has 'foo/struct.Yolo.html' -//@has - '//*[@class="item-info"]/*[@class="stab portability"]' 'Available on non-crate feature ananas and non-crate feature banana only.' +//@ has 'foo/struct.Yolo.html' +//@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'Available on non-crate feature ananas and non-crate feature banana only.' pub use self::banana::SubBanana as Yolo; #[cfg(not(feature = "banana"))] diff --git a/tests/rustdoc-html/doc-cfg/trait-impls-manual.rs b/tests/rustdoc-html/doc-cfg/trait-impls-manual.rs index 4329d8e06dfc5..890c484c1e1de 100644 --- a/tests/rustdoc-html/doc-cfg/trait-impls-manual.rs +++ b/tests/rustdoc-html/doc-cfg/trait-impls-manual.rs @@ -22,36 +22,36 @@ pub trait Foo { pub struct X; -//@has 'foo/struct.X.html' -//@count - '//*[@id="impl-Bob-for-X"]' 1 -//@count - '//*[@id="impl-Bob-for-X"]/*[@class="item-info"]' 0 -//@count - '//*[@id="impl-Trait-for-X"]' 1 -//@count - '//*[@id="impl-Trait-for-X"]/*[@class="item-info"]' 0 +//@ has 'foo/struct.X.html' +//@ count - '//*[@id="impl-Bob-for-X"]' 1 +//@ count - '//*[@id="impl-Bob-for-X"]/*[@class="item-info"]' 1 +//@ count - '//*[@id="impl-Trait-for-X"]' 1 +//@ count - '//*[@id="impl-Trait-for-X"]/*[@class="item-info"]' 1 // If you need to update this XPath, in particular `item-info`, update all // the others in this file. -//@count - '//*[@id="impl-Foo-for-X"]/*[@class="item-info"]' 1 +//@ count - '//*[@id="impl-Foo-for-X"]/*[@class="item-info"]' 1 -//@has 'foo/trait.Trait.html' -//@count - '//*[@id="impl-Trait-for-X"]' 1 -//@count - '//*[@id="impl-Trait-for-X"]/*[@class="item-info"]' 0 +//@ has 'foo/trait.Trait.html' +//@ count - '//*[@id="impl-Trait-for-X"]' 1 +//@ count - '//*[@id="impl-Trait-for-X"]/*[@class="item-info"]' 1 #[doc(cfg(any(target_pointer_width = "64", target_arch = "wasm32")))] #[doc(auto_cfg(hide(target_arch, values("wasm32"))))] mod imp { impl super::Trait for super::X { fn f(&self) {} } } -//@has 'foo/trait.Bob.html' -//@count - '//*[@id="impl-Bob-for-X"]' 1 -//@count - '//*[@id="impl-Bob-for-X"]/*[@class="item-info"]' 0 +//@ has 'foo/trait.Bob.html' +//@ count - '//*[@id="impl-Bob-for-X"]' 1 +//@ count - '//*[@id="impl-Bob-for-X"]/*[@class="item-info"]' 1 #[doc(cfg(any(target_pointer_width = "64", target_arch = "wasm32")))] #[doc(auto_cfg = false)] mod imp2 { impl super::Bob for super::X { fn bob(&self) {} } } -//@has 'foo/trait.Foo.html' -//@count - '//*[@id="impl-Foo-for-X"]/*[@class="item-info"]' 1 +//@ has 'foo/trait.Foo.html' +//@ count - '//*[@id="impl-Foo-for-X"]/*[@class="item-info"]' 1 // We use this to force xpath tests to be updated if `item-info` class is changed. #[doc(cfg(any(target_pointer_width = "64", target_arch = "wasm32")))] mod imp3 { @@ -60,9 +60,9 @@ mod imp3 { pub struct Y; -//@has 'foo/struct.Y.html' -//@count - '//*[@id="implementations-list"]/*[@class="impl-items"]' 1 -//@count - '//*[@id="implementations-list"]/*[@class="impl-items"]/*[@class="item-info"]' 0 +//@ has 'foo/struct.Y.html' +//@ count - '//*[@id="implementations-list"]//*[@class="impl-items"]' 1 +//@ count - '//*[@id="implementations-list"]//*[@class="impl-items"]/*[@class="item-info"]' 0 #[doc(cfg(any(target_pointer_width = "64", target_arch = "wasm32")))] #[doc(auto_cfg(hide(target_arch, values("wasm32"))))] mod imp4 { @@ -71,9 +71,9 @@ mod imp4 { pub struct Z; -//@has 'foo/struct.Z.html' -//@count - '//*[@id="implementations-list"]/*[@class="impl-items"]' 1 -//@count - '//*[@id="implementations-list"]/*[@class="impl-items"]/*[@class="item-info"]' 0 +//@ has 'foo/struct.Z.html' +//@ count - '//*[@id="implementations-list"]//*[@class="impl-items"]' 1 +//@ count - '//*[@id="implementations-list"]//*[@class="impl-items"]/*[@class="item-info"]' 0 #[doc(cfg(any(target_pointer_width = "64", target_arch = "wasm32")))] #[doc(auto_cfg = false)] mod imp5 { @@ -83,9 +83,9 @@ mod imp5 { // The "witness" which has the item info. pub struct W; -//@has 'foo/struct.W.html' -//@count - '//*[@id="implementations-list"]/*[@class="impl-items"]' 1 -//@count - '//*[@id="implementations-list"]/*[@class="impl-items"]/*[@class="item-info"]' 1 +//@ has 'foo/struct.W.html' +//@ count - '//*[@id="implementations-list"]//*[@class="impl-items"]' 1 +//@ count - '//*[@id="implementations-list"]//*[@class="impl-items"]/*[@class="item-info"]' 1 #[doc(cfg(any(target_pointer_width = "64", target_arch = "wasm32")))] mod imp6 { impl super::W { pub fn plain_auto() {} } diff --git a/tests/rustdoc-html/doc-cfg/trait-impls.rs b/tests/rustdoc-html/doc-cfg/trait-impls.rs index 9ea6490ae8e21..6bb44b7fd6bce 100644 --- a/tests/rustdoc-html/doc-cfg/trait-impls.rs +++ b/tests/rustdoc-html/doc-cfg/trait-impls.rs @@ -22,36 +22,36 @@ pub trait Foo { pub struct X; -//@has 'foo/struct.X.html' -//@count - '//*[@id="impl-Bob-for-X"]' 1 -//@count - '//*[@id="impl-Bob-for-X"]/*[@class="item-info"]' 0 -//@count - '//*[@id="impl-Trait-for-X"]' 1 -//@count - '//*[@id="impl-Trait-for-X"]/*[@class="item-info"]' 0 +//@ has 'foo/struct.X.html' +//@ count - '//*[@id="impl-Bob-for-X"]' 1 +//@ count - '//*[@id="impl-Bob-for-X"]/*[@class="item-info"]' 0 +//@ count - '//*[@id="impl-Trait-for-X"]' 1 +//@ count - '//*[@id="impl-Trait-for-X"]/*[@class="item-info"]' 0 // If you need to update this XPath, in particular `item-info`, update all // the others in this file. -//@count - '//*[@id="impl-Foo-for-X"]/*[@class="item-info"]' 1 +//@ count - '//*[@id="impl-Foo-for-X"]/*[@class="item-info"]' 1 -//@has 'foo/trait.Trait.html' -//@count - '//*[@id="impl-Trait-for-X"]' 1 -//@count - '//*[@id="impl-Trait-for-X"]/*[@class="item-info"]' 0 +//@ has 'foo/trait.Trait.html' +//@ count - '//*[@id="impl-Trait-for-X"]' 1 +//@ count - '//*[@id="impl-Trait-for-X"]/*[@class="item-info"]' 0 #[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))] #[doc(auto_cfg(hide(target_arch, values("wasm32"))))] mod imp { impl super::Trait for super::X { fn f(&self) {} } } -//@has 'foo/trait.Bob.html' -//@count - '//*[@id="impl-Bob-for-X"]' 1 -//@count - '//*[@id="impl-Bob-for-X"]/*[@class="item-info"]' 0 +//@ has 'foo/trait.Bob.html' +//@ count - '//*[@id="impl-Bob-for-X"]' 1 +//@ count - '//*[@id="impl-Bob-for-X"]/*[@class="item-info"]' 0 #[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))] #[doc(auto_cfg = false)] mod imp2 { impl super::Bob for super::X { fn bob(&self) {} } } -//@has 'foo/trait.Foo.html' -//@count - '//*[@id="impl-Foo-for-X"]/*[@class="item-info"]' 1 +//@ has 'foo/trait.Foo.html' +//@ count - '//*[@id="impl-Foo-for-X"]/*[@class="item-info"]' 1 // We use this to force xpath tests to be updated if `item-info` class is changed. #[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))] mod imp3 { @@ -60,9 +60,9 @@ mod imp3 { pub struct Y; -//@has 'foo/struct.Y.html' -//@count - '//*[@id="implementations-list"]/*[@class="impl-items"]' 1 -//@count - '//*[@id="implementations-list"]/*[@class="impl-items"]/*[@class="item-info"]' 0 +//@ has 'foo/struct.Y.html' +//@ count - '//*[@id="implementations-list"]//*[@class="impl-items"]' 1 +//@ count - '//*[@id="implementations-list"]//*[@class="impl-items"]/*[@class="item-info"]' 0 #[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))] #[doc(auto_cfg(hide(target_arch, values("wasm32"))))] mod imp4 { @@ -71,9 +71,9 @@ mod imp4 { pub struct Z; -//@has 'foo/struct.Z.html' -//@count - '//*[@id="implementations-list"]/*[@class="impl-items"]' 1 -//@count - '//*[@id="implementations-list"]/*[@class="impl-items"]/*[@class="item-info"]' 0 +//@ has 'foo/struct.Z.html' +//@ count - '//*[@id="implementations-list"]//*[@class="impl-items"]' 1 +//@ count - '//*[@id="implementations-list"]//*[@class="impl-items"]/*[@class="item-info"]' 0 #[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))] #[doc(auto_cfg = false)] mod imp5 { @@ -83,9 +83,9 @@ mod imp5 { // The "witness" which has the item info. pub struct W; -//@has 'foo/struct.W.html' -//@count - '//*[@id="implementations-list"]/*[@class="impl-items"]' 1 -//@count - '//*[@id="implementations-list"]/*[@class="impl-items"]/*[@class="item-info"]' 1 +//@ has 'foo/struct.W.html' +//@ count - '//*[@id="implementations-list"]//*[@class="impl-items"]' 1 +//@ count - '//*[@id="implementations-list"]//*[@class="impl-items"]//*[@class="item-info"]' 1 #[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))] mod imp6 { impl super::W { pub fn plain_auto() {} } diff --git a/tests/rustdoc-html/duplicate_impls/impls.rs b/tests/rustdoc-html/duplicate_impls/auxiliary/impls.rs similarity index 100% rename from tests/rustdoc-html/duplicate_impls/impls.rs rename to tests/rustdoc-html/duplicate_impls/auxiliary/impls.rs diff --git a/tests/rustdoc-html/duplicate_impls/sidebar-links-duplicate-impls-33054.rs b/tests/rustdoc-html/duplicate_impls/sidebar-links-duplicate-impls-33054.rs index 511a40c38a0a2..84637a6aea3d6 100644 --- a/tests/rustdoc-html/duplicate_impls/sidebar-links-duplicate-impls-33054.rs +++ b/tests/rustdoc-html/duplicate_impls/sidebar-links-duplicate-impls-33054.rs @@ -10,6 +10,7 @@ //@ has foo/impls/bar/trait.Bar.html //@ has - '//h3[@class="code-header"]' 'impl Bar for Foo' //@ count - '//*[@class="struct"]' 1 +#[path = "auxiliary/impls.rs"] pub mod impls; #[doc(inline)] diff --git a/tests/rustdoc-html/inline_local/fully-stable-path-is-better.rs b/tests/rustdoc-html/inline_local/fully-stable-path-is-better.rs index 41bf42d2e7aad..343e66cfc9666 100644 --- a/tests/rustdoc-html/inline_local/fully-stable-path-is-better.rs +++ b/tests/rustdoc-html/inline_local/fully-stable-path-is-better.rs @@ -16,10 +16,10 @@ pub mod stb1 { #[unstable(feature = "uns", issue = "135003")] pub mod uns { #[stable(since = "1.0", feature = "stb1")] - #[rustc_allowed_through_unstable_modules = "use stable path instead"] + #[rustc_allowed_through_unstable_modules(message = "use stable path instead", module = "stb1")] pub struct Inside1; #[stable(since = "1.0", feature = "stb2")] - #[rustc_allowed_through_unstable_modules = "use stable path instead"] + #[rustc_allowed_through_unstable_modules(message = "use stable path instead", module = "stb2")] pub struct Inside2; } diff --git a/tests/rustdoc-html/macro/decl_macro-sidebar.rs b/tests/rustdoc-html/macro/decl_macro-sidebar.rs deleted file mode 100644 index 468b36c746db3..0000000000000 --- a/tests/rustdoc-html/macro/decl_macro-sidebar.rs +++ /dev/null @@ -1,15 +0,0 @@ -// This test ensures that the `foo` decl macro is present in the module sidebar. - -#![feature(decl_macro)] -#![crate_name = "foo"] - -//@has 'foo/bar/index.html' -//@has - '//*[@id="rustdoc-modnav"]/ul[@class="block macro"]//a[@href="../macro.foo.html"]' 'foo' - -pub macro foo { - () => { "bar" } -} - -/// docs -pub mod bar { -} diff --git a/tests/rustdoc-html/stability.rs b/tests/rustdoc-html/stability.rs index 4870c68dfe5e6..8df66a59d3c15 100644 --- a/tests/rustdoc-html/stability.rs +++ b/tests/rustdoc-html/stability.rs @@ -85,7 +85,10 @@ pub mod stable_later { } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_allowed_through_unstable_modules = "use stable path instead"] +#[rustc_allowed_through_unstable_modules( + message = "use stable path instead", + module = "stable_module", +)] pub mod stable_earlier1 { //@ has stability/stable_earlier1/struct.StableInUnstable.html \ // '//div[@class="main-heading"]//span[@class="since"]' '1.0.0' diff --git a/tests/rustdoc-html/auto/auto-impl-for-trait.rs b/tests/rustdoc-ui/auto/auto-impl-for-trait.rs similarity index 94% rename from tests/rustdoc-html/auto/auto-impl-for-trait.rs rename to tests/rustdoc-ui/auto/auto-impl-for-trait.rs index bc658fbfc8cce..8849a25458457 100644 --- a/tests/rustdoc-html/auto/auto-impl-for-trait.rs +++ b/tests/rustdoc-ui/auto/auto-impl-for-trait.rs @@ -1,5 +1,7 @@ // Test for https://github.com/rust-lang/rust/issues/48463 issue. +//@ check-pass + use std::any::Any; use std::ops::Deref; diff --git a/tests/rustdoc-html/constant/document-item-with-associated-const-in-where-clause.rs b/tests/rustdoc-ui/constant/document-item-with-associated-const-in-where-clause.rs similarity index 94% rename from tests/rustdoc-html/constant/document-item-with-associated-const-in-where-clause.rs rename to tests/rustdoc-ui/constant/document-item-with-associated-const-in-where-clause.rs index c9408ef3360b4..9c16fa0b9b4fa 100644 --- a/tests/rustdoc-html/constant/document-item-with-associated-const-in-where-clause.rs +++ b/tests/rustdoc-ui/constant/document-item-with-associated-const-in-where-clause.rs @@ -1,6 +1,8 @@ #![feature(generic_const_exprs)] #![allow(incomplete_features)] +//@ check-pass + pub trait Enumerable { const N: usize; } diff --git a/tests/rustdoc-html/deep-structures.rs b/tests/rustdoc-ui/deep-structures.rs similarity index 99% rename from tests/rustdoc-html/deep-structures.rs rename to tests/rustdoc-ui/deep-structures.rs index cd3b0d3ec9706..e763f6bbf652c 100644 --- a/tests/rustdoc-html/deep-structures.rs +++ b/tests/rustdoc-ui/deep-structures.rs @@ -1,6 +1,8 @@ // This test verifies that we do not hit recursion limit trying to prove auto-trait bounds for // reasonably deep structures. +//@ check-pass + #![crate_type="rlib"] pub struct A01(A02); diff --git a/tests/rustdoc-html/type-alias/deeply-nested-112515.rs b/tests/rustdoc-ui/deeply-nested-112515.rs similarity index 95% rename from tests/rustdoc-html/type-alias/deeply-nested-112515.rs rename to tests/rustdoc-ui/deeply-nested-112515.rs index 9530feb78de66..81b11cca1ac90 100644 --- a/tests/rustdoc-html/type-alias/deeply-nested-112515.rs +++ b/tests/rustdoc-ui/deeply-nested-112515.rs @@ -2,7 +2,9 @@ // It's to ensure that this code doesn't have infinite loop in rustdoc when // trying to retrieve type alias implementations. -// ignore-tidy-linelength +// ignore-tidy-file-linelength + +//@ check-pass pub type Boom = S, ()>, ()>, ()>, u8>, ()>, u8>, ()>, u8>, u8>, ()>, ()>, ()>, u8>, u8>, u8>, ()>, ()>, u8>, ()>, ()>, ()>, u8>, u8>, ()>, ()>, ()>, ()>, ()>, u8>, ()>, ()>, u8>, ()>, ()>, ()>, u8>, ()>, ()>, u8>, u8>, u8>, u8>, ()>, u8>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>; pub struct S(T, U); diff --git a/tests/rustdoc-html/empty-doc-comment.rs b/tests/rustdoc-ui/empty-doc-comment.rs similarity index 91% rename from tests/rustdoc-html/empty-doc-comment.rs rename to tests/rustdoc-ui/empty-doc-comment.rs index b1dae930e066b..7543553e60d56 100644 --- a/tests/rustdoc-html/empty-doc-comment.rs +++ b/tests/rustdoc-ui/empty-doc-comment.rs @@ -1,5 +1,7 @@ // Ensure that empty doc comments don't panic. +//@ check-pass + /*! */ diff --git a/tests/rustdoc-html/intra-doc/ice-deprecated-note-on-reexport.rs b/tests/rustdoc-ui/intra-doc/ice-deprecated-note-on-reexport.rs similarity index 96% rename from tests/rustdoc-html/intra-doc/ice-deprecated-note-on-reexport.rs rename to tests/rustdoc-ui/intra-doc/ice-deprecated-note-on-reexport.rs index 99415a9a2fd4a..43ec497d9de7a 100644 --- a/tests/rustdoc-html/intra-doc/ice-deprecated-note-on-reexport.rs +++ b/tests/rustdoc-ui/intra-doc/ice-deprecated-note-on-reexport.rs @@ -4,6 +4,8 @@ // // This is a regression test for . +//@ check-pass + #![crate_name = "foo"] #[deprecated(note = "use [`std::mem::forget`]")] diff --git a/tests/rustdoc-html/intra-doc/in-bodies.rs b/tests/rustdoc-ui/intra-doc/in-bodies.rs similarity index 97% rename from tests/rustdoc-html/intra-doc/in-bodies.rs rename to tests/rustdoc-ui/intra-doc/in-bodies.rs index 55169e5d3c459..69ebe459b681f 100644 --- a/tests/rustdoc-html/intra-doc/in-bodies.rs +++ b/tests/rustdoc-ui/intra-doc/in-bodies.rs @@ -1,5 +1,7 @@ // we need to make sure that intra-doc links on trait impls get resolved in the right scope +//@ check-pass + #![deny(rustdoc::broken_intra_doc_links)] pub mod inner { diff --git a/tests/rustdoc-html/intra-doc/libstd-re-export.rs b/tests/rustdoc-ui/intra-doc/libstd-re-export.rs similarity index 85% rename from tests/rustdoc-html/intra-doc/libstd-re-export.rs rename to tests/rustdoc-ui/intra-doc/libstd-re-export.rs index 6c41eb2b5b7c3..29cf3f8b295c7 100644 --- a/tests/rustdoc-html/intra-doc/libstd-re-export.rs +++ b/tests/rustdoc-ui/intra-doc/libstd-re-export.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![deny(rustdoc::broken_intra_doc_links)] #![feature(intra_doc_pointers)] diff --git a/tests/rustdoc-html/intra-doc/private-failures-ignored.rs b/tests/rustdoc-ui/intra-doc/private-failures-ignored.rs similarity index 95% rename from tests/rustdoc-html/intra-doc/private-failures-ignored.rs rename to tests/rustdoc-ui/intra-doc/private-failures-ignored.rs index b272bfb5a4df2..c36947286b57b 100644 --- a/tests/rustdoc-html/intra-doc/private-failures-ignored.rs +++ b/tests/rustdoc-ui/intra-doc/private-failures-ignored.rs @@ -2,6 +2,8 @@ // These failures were legitimate, but not truly relevant - the docs in question couldn't be // checked for accuracy anyway. +//@ check-pass + #![deny(rustdoc::broken_intra_doc_links)] /// ooh, i'm a [rebel] just for kicks diff --git a/tests/rustdoc-html/macro/doc-proc-macro.rs b/tests/rustdoc-ui/macro/doc-proc-macro.rs similarity index 94% rename from tests/rustdoc-html/macro/doc-proc-macro.rs rename to tests/rustdoc-ui/macro/doc-proc-macro.rs index 19172ffa41deb..c1e53b24eb2f2 100644 --- a/tests/rustdoc-html/macro/doc-proc-macro.rs +++ b/tests/rustdoc-ui/macro/doc-proc-macro.rs @@ -3,6 +3,8 @@ // As of this writing, we don't currently attempt to document proc-macros. However, we shouldn't // crash when we try. +//@ check-pass + extern crate proc_macro; pub use proc_macro::*; diff --git a/tests/rustdoc-html/macro/macro-ice-16019.rs b/tests/rustdoc-ui/macro/macro-ice-16019.rs similarity index 89% rename from tests/rustdoc-html/macro/macro-ice-16019.rs rename to tests/rustdoc-ui/macro/macro-ice-16019.rs index d0f82e0a314ce..fc217434d3811 100644 --- a/tests/rustdoc-html/macro/macro-ice-16019.rs +++ b/tests/rustdoc-ui/macro/macro-ice-16019.rs @@ -1,11 +1,13 @@ // https://github.com/rust-lang/rust/issues/16019 +//@ check-pass + macro_rules! define_struct { ($rounds:expr) => ( struct Struct { sk: [u32; $rounds + 1] } - ) + ) } define_struct!(2); diff --git a/tests/rustdoc-html/macro/macro-in-closure.rs b/tests/rustdoc-ui/macro/macro-in-closure.rs similarity index 94% rename from tests/rustdoc-html/macro/macro-in-closure.rs rename to tests/rustdoc-ui/macro/macro-in-closure.rs index b4411d927e271..adf87516c793f 100644 --- a/tests/rustdoc-html/macro/macro-in-closure.rs +++ b/tests/rustdoc-ui/macro/macro-in-closure.rs @@ -1,5 +1,7 @@ // Regression issue for rustdoc ICE encountered in PR #65252. +//@ check-pass + #![feature(decl_macro)] fn main() { diff --git a/tests/rustdoc-html/markdown-60482.rs b/tests/rustdoc-ui/markdown-60482.rs similarity index 93% rename from tests/rustdoc-html/markdown-60482.rs rename to tests/rustdoc-ui/markdown-60482.rs index e40af12e02258..4d817f3fe99e9 100644 --- a/tests/rustdoc-html/markdown-60482.rs +++ b/tests/rustdoc-ui/markdown-60482.rs @@ -1,8 +1,9 @@ // This code caused a panic in `pulldown-cmark` 0.4.1. // https://github.com/rust-lang/rust/issues/60482 -pub const BASIC_UNICODE: bool = true; +//@ check-pass +pub const BASIC_UNICODE: bool = true; /// # `BASIC_UNICODE`: `A` `|` /// ```text diff --git a/tests/rustdoc-html/private/private-use.rs b/tests/rustdoc-ui/private/private-use.rs similarity index 95% rename from tests/rustdoc-html/private/private-use.rs rename to tests/rustdoc-ui/private/private-use.rs index 689ed73140d98..c2185f10d4059 100644 --- a/tests/rustdoc-html/private/private-use.rs +++ b/tests/rustdoc-ui/private/private-use.rs @@ -1,6 +1,8 @@ // Regression test for to // ensure it doesn't panic. +//@ check-pass + mod generics { pub enum WherePredicate { EqPredicate, diff --git a/tests/rustdoc-html/recursion1.rs b/tests/rustdoc-ui/recursion/recursion1.rs similarity index 90% rename from tests/rustdoc-html/recursion1.rs rename to tests/rustdoc-ui/recursion/recursion1.rs index edf7e440fe7c4..c477510b89e11 100644 --- a/tests/rustdoc-html/recursion1.rs +++ b/tests/rustdoc-ui/recursion/recursion1.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![crate_type = "lib"] mod m { diff --git a/tests/rustdoc-html/recursion2.rs b/tests/rustdoc-ui/recursion/recursion2.rs similarity index 90% rename from tests/rustdoc-html/recursion2.rs rename to tests/rustdoc-ui/recursion/recursion2.rs index edf7e440fe7c4..c477510b89e11 100644 --- a/tests/rustdoc-html/recursion2.rs +++ b/tests/rustdoc-ui/recursion/recursion2.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![crate_type = "lib"] mod m { diff --git a/tests/rustdoc-html/recursion3.rs b/tests/rustdoc-ui/recursion/recursion3.rs similarity index 95% rename from tests/rustdoc-html/recursion3.rs rename to tests/rustdoc-ui/recursion/recursion3.rs index e69b4301646b7..e65632b830678 100644 --- a/tests/rustdoc-html/recursion3.rs +++ b/tests/rustdoc-ui/recursion/recursion3.rs @@ -1,3 +1,5 @@ +//@ check-pass + pub mod longhands { pub use super::*; diff --git a/tests/rustdoc-html/resolve-ice-124363.rs b/tests/rustdoc-ui/resolve-ice-124363.rs similarity index 80% rename from tests/rustdoc-html/resolve-ice-124363.rs rename to tests/rustdoc-ui/resolve-ice-124363.rs index 111916cc59050..a790972a53f2e 100644 --- a/tests/rustdoc-html/resolve-ice-124363.rs +++ b/tests/rustdoc-ui/resolve-ice-124363.rs @@ -1,3 +1,5 @@ +//@ check-pass + /** */ pub mod A { diff --git a/tests/rustdoc-html/synthetic_auto/issue-72213-projection-lifetime.rs b/tests/rustdoc-ui/synthetic-auto-trait-impls/issue-72213-projection-lifetime.rs similarity index 96% rename from tests/rustdoc-html/synthetic_auto/issue-72213-projection-lifetime.rs rename to tests/rustdoc-ui/synthetic-auto-trait-impls/issue-72213-projection-lifetime.rs index 6f66b8e556388..660672f01192c 100644 --- a/tests/rustdoc-html/synthetic_auto/issue-72213-projection-lifetime.rs +++ b/tests/rustdoc-ui/synthetic-auto-trait-impls/issue-72213-projection-lifetime.rs @@ -2,6 +2,8 @@ // Tests that we don't ICE when we have projection predicates // in our initial ParamEnv +//@ check-pass + pub struct Lines<'a, L> where L: Iterator, diff --git a/tests/rustdoc-ui/type-alias/deeply-nested-112515.rs b/tests/rustdoc-ui/type-alias/deeply-nested-112515.rs new file mode 100644 index 0000000000000..81b11cca1ac90 --- /dev/null +++ b/tests/rustdoc-ui/type-alias/deeply-nested-112515.rs @@ -0,0 +1,32 @@ +// Regression test for . +// It's to ensure that this code doesn't have infinite loop in rustdoc when +// trying to retrieve type alias implementations. + +// ignore-tidy-file-linelength + +//@ check-pass + +pub type Boom = S, ()>, ()>, ()>, u8>, ()>, u8>, ()>, u8>, u8>, ()>, ()>, ()>, u8>, u8>, u8>, ()>, ()>, u8>, ()>, ()>, ()>, u8>, u8>, ()>, ()>, ()>, ()>, ()>, u8>, ()>, ()>, u8>, ()>, ()>, ()>, u8>, ()>, ()>, u8>, u8>, u8>, u8>, ()>, u8>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>; +pub struct S(T, U); + +pub trait A {} + +pub trait B { + type P; +} + +impl A for u64 {} + +impl A for S {} + +impl B for S +where + T: B, + >::P: A, +{ + type P = (); +} + +impl B for S { + type P = (); +} diff --git a/tests/ui/abi/c-zst.aarch64-darwin.stderr b/tests/ui/abi/c-zst.aarch64-darwin.stderr index 6d2ac90c0c975..e7cb6199ab45c 100644 --- a/tests/ui/abi/c-zst.aarch64-darwin.stderr +++ b/tests/ui/abi/c-zst.aarch64-darwin.stderr @@ -59,6 +59,7 @@ error: fn_abi_of(pass_zst) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/c-zst.rs:65:1 | diff --git a/tests/ui/abi/c-zst.powerpc-linux.stderr b/tests/ui/abi/c-zst.powerpc-linux.stderr index edea2d5772280..437ebd63ceba5 100644 --- a/tests/ui/abi/c-zst.powerpc-linux.stderr +++ b/tests/ui/abi/c-zst.powerpc-linux.stderr @@ -70,6 +70,7 @@ error: fn_abi_of(pass_zst) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/c-zst.rs:65:1 | diff --git a/tests/ui/abi/c-zst.s390x-linux.stderr b/tests/ui/abi/c-zst.s390x-linux.stderr index edea2d5772280..437ebd63ceba5 100644 --- a/tests/ui/abi/c-zst.s390x-linux.stderr +++ b/tests/ui/abi/c-zst.s390x-linux.stderr @@ -70,6 +70,7 @@ error: fn_abi_of(pass_zst) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/c-zst.rs:65:1 | diff --git a/tests/ui/abi/c-zst.sparc64-linux.stderr b/tests/ui/abi/c-zst.sparc64-linux.stderr index edea2d5772280..437ebd63ceba5 100644 --- a/tests/ui/abi/c-zst.sparc64-linux.stderr +++ b/tests/ui/abi/c-zst.sparc64-linux.stderr @@ -70,6 +70,7 @@ error: fn_abi_of(pass_zst) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/c-zst.rs:65:1 | diff --git a/tests/ui/abi/c-zst.x86_64-linux.stderr b/tests/ui/abi/c-zst.x86_64-linux.stderr index 6d2ac90c0c975..e7cb6199ab45c 100644 --- a/tests/ui/abi/c-zst.x86_64-linux.stderr +++ b/tests/ui/abi/c-zst.x86_64-linux.stderr @@ -59,6 +59,7 @@ error: fn_abi_of(pass_zst) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/c-zst.rs:65:1 | diff --git a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr index edea2d5772280..437ebd63ceba5 100644 --- a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr +++ b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr @@ -70,6 +70,7 @@ error: fn_abi_of(pass_zst) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/c-zst.rs:65:1 | diff --git a/tests/ui/abi/debug.generic.stderr b/tests/ui/abi/debug.generic.stderr index 6242d93b09534..82c469e0f4f80 100644 --- a/tests/ui/abi/debug.generic.stderr +++ b/tests/ui/abi/debug.generic.stderr @@ -106,6 +106,7 @@ error: fn_abi_of(test) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:31:1 | @@ -187,6 +188,7 @@ error: fn_abi_of(TestFnPtr) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:37:1 | @@ -258,6 +260,7 @@ error: fn_abi_of(test_generic) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:40:1 | @@ -336,6 +339,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -402,6 +406,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:59:1 | @@ -481,6 +486,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -554,6 +560,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:62:1 | @@ -626,6 +633,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -692,6 +700,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:65:1 | @@ -764,6 +773,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -830,6 +840,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:69:1 | @@ -924,6 +935,7 @@ error: fn_abi_of(assoc_test) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:52:5 | diff --git a/tests/ui/abi/debug.loongarch64.stderr b/tests/ui/abi/debug.loongarch64.stderr index 176c68ecd4c7b..b5c73d00564c6 100644 --- a/tests/ui/abi/debug.loongarch64.stderr +++ b/tests/ui/abi/debug.loongarch64.stderr @@ -106,6 +106,7 @@ error: fn_abi_of(test) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:31:1 | @@ -187,6 +188,7 @@ error: fn_abi_of(TestFnPtr) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:37:1 | @@ -258,6 +260,7 @@ error: fn_abi_of(test_generic) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:40:1 | @@ -336,6 +339,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -402,6 +406,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:59:1 | @@ -481,6 +486,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -554,6 +560,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:62:1 | @@ -626,6 +633,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -692,6 +700,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:65:1 | @@ -764,6 +773,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -830,6 +840,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:69:1 | @@ -924,6 +935,7 @@ error: fn_abi_of(assoc_test) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:52:5 | diff --git a/tests/ui/abi/debug.riscv64.stderr b/tests/ui/abi/debug.riscv64.stderr index 176c68ecd4c7b..b5c73d00564c6 100644 --- a/tests/ui/abi/debug.riscv64.stderr +++ b/tests/ui/abi/debug.riscv64.stderr @@ -106,6 +106,7 @@ error: fn_abi_of(test) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:31:1 | @@ -187,6 +188,7 @@ error: fn_abi_of(TestFnPtr) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:37:1 | @@ -258,6 +260,7 @@ error: fn_abi_of(test_generic) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:40:1 | @@ -336,6 +339,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -402,6 +406,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:59:1 | @@ -481,6 +486,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -554,6 +560,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:62:1 | @@ -626,6 +633,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -692,6 +700,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:65:1 | @@ -764,6 +773,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -830,6 +840,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:69:1 | @@ -924,6 +935,7 @@ error: fn_abi_of(assoc_test) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:52:5 | diff --git a/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.apple.stderr b/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.apple.stderr index 65818feab4297..df49fbfe3d272 100644 --- a/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.apple.stderr +++ b/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.apple.stderr @@ -69,6 +69,7 @@ error: fn_abi_of(i8) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:13:1 | @@ -146,6 +147,7 @@ error: fn_abi_of(u8) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:19:1 | @@ -223,6 +225,7 @@ error: fn_abi_of(i16) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:25:1 | @@ -300,6 +303,7 @@ error: fn_abi_of(u16) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:31:1 | @@ -377,6 +381,7 @@ error: fn_abi_of(i32) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:37:1 | @@ -454,6 +459,7 @@ error: fn_abi_of(u32) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:43:1 | diff --git a/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.other.stderr b/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.other.stderr index cbe389c42d40a..7ceb6a2092af2 100644 --- a/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.other.stderr +++ b/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.other.stderr @@ -69,6 +69,7 @@ error: fn_abi_of(i8) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:13:1 | @@ -146,6 +147,7 @@ error: fn_abi_of(u8) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:19:1 | @@ -223,6 +225,7 @@ error: fn_abi_of(i16) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:25:1 | @@ -300,6 +303,7 @@ error: fn_abi_of(u16) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:31:1 | @@ -377,6 +381,7 @@ error: fn_abi_of(i32) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:37:1 | @@ -454,6 +459,7 @@ error: fn_abi_of(u32) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:43:1 | diff --git a/tests/ui/abi/pass-indirectly-attr.stderr b/tests/ui/abi/pass-indirectly-attr.stderr index efeec0d86982b..935ab97647321 100644 --- a/tests/ui/abi/pass-indirectly-attr.stderr +++ b/tests/ui/abi/pass-indirectly-attr.stderr @@ -83,6 +83,7 @@ error: fn_abi_of(extern_c) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/pass-indirectly-attr.rs:20:1 | @@ -174,6 +175,7 @@ error: fn_abi_of(extern_rust) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/pass-indirectly-attr.rs:27:1 | diff --git a/tests/ui/abi/sysv64-zst.stderr b/tests/ui/abi/sysv64-zst.stderr index 82d3793c35328..f19480faec4fa 100644 --- a/tests/ui/abi/sysv64-zst.stderr +++ b/tests/ui/abi/sysv64-zst.stderr @@ -61,6 +61,7 @@ error: fn_abi_of(pass_zst) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/sysv64-zst.rs:8:1 | diff --git a/tests/ui/assumptions_on_binders/test-infra-fails-properly.rs b/tests/ui/assumptions_on_binders/test-infra-fails-properly.rs index c02f3bace5071..240b64e770f51 100644 --- a/tests/ui/assumptions_on_binders/test-infra-fails-properly.rs +++ b/tests/ui/assumptions_on_binders/test-infra-fails-properly.rs @@ -67,4 +67,11 @@ core::test_binder_constraints! { } } +core::test_binder_constraints! { + impl<'a, T> { + for<> T: 'a + //~^ ERROR bound type test binder constraint must be alias (it's a AliasTyOutlivesViaEnv) + } +} + fn main() {} diff --git a/tests/ui/assumptions_on_binders/test-infra-fails-properly.stderr b/tests/ui/assumptions_on_binders/test-infra-fails-properly.stderr index 0572944204787..2931a37c0f340 100644 --- a/tests/ui/assumptions_on_binders/test-infra-fails-properly.stderr +++ b/tests/ui/assumptions_on_binders/test-infra-fails-properly.stderr @@ -61,9 +61,23 @@ note: constraint from here | LL | forall<'a> where 'b: 'a { | ^^^^^^ - = note: expected: RegionOutlives('c/#1, 'c/#1, $DIR/test-infra-fails-properly.rs:63:17: 63:23 (#0)) - = note: actual: RegionOutlives('c/#1, 'static, $DIR/test-infra-fails-properly.rs:58:9: 58:15 (#0)) + = note: expected: RegionOutlives( + 'c/#1, + 'c/#1, + $DIR/test-infra-fails-properly.rs:63:17: 63:23 (#0), + ) + = note: actual: RegionOutlives( + 'c/#1, + 'static, + $DIR/test-infra-fails-properly.rs:58:9: 58:15 (#0), + ) -error: aborting due to 8 previous errors +error: bound type test binder constraint must be alias (it's a AliasTyOutlivesViaEnv) + --> $DIR/test-infra-fails-properly.rs:72:15 + | +LL | for<> T: 'a + | ^ + +error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/assumptions_on_binders/test-infra-works.rs b/tests/ui/assumptions_on_binders/test-infra-works.rs index f172a112fdd43..d8d64d1aac255 100644 --- a/tests/ui/assumptions_on_binders/test-infra-works.rs +++ b/tests/ui/assumptions_on_binders/test-infra-works.rs @@ -41,4 +41,45 @@ core::test_binder_constraints! { } } +trait Trait { + type Assoc; +} + +// FIXME(-Zassumptions-on-binders): this probably shouldn't compile, the exit for the top-level +// `impl` should fail because the constraints asserted in `expect` should fail to prove true. Might +// be https://github.com/rust-lang/project-assumptions-on-binders/issues/26 +// +// for<> syntax does direct insert into constraint storage +core::test_binder_constraints! { + impl { + forall<'a> { + for<> T::Assoc: 'a + } expect { + or { + for<'b> T::Assoc: 'b, + for<> T::Assoc: 'static + } + } + } +} + +// FIXME(-Zassumptions-on-binders): this probably shouldn't compile, the exit for the top-level +// `impl` should fail because the constraints asserted in `expect` should fail to prove true. Might +// be https://github.com/rust-lang/project-assumptions-on-binders/issues/26 +// +// `where` syntax goes through the full clause destructuring and register_obligation pipeline +core::test_binder_constraints! { + impl { + forall<'a> { + where T::Assoc: 'a + } expect { + or { + for<'b> T::Assoc: 'b, + for<> T::Assoc: 'static, + T: 'static + } + } + } +} + fn main() {} diff --git a/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout b/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout index 90381a12bbd4b..775f683a8f926 100644 --- a/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout +++ b/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout @@ -7,8 +7,6 @@ print-type-size variant `Returned`: 0 bytes print-type-size variant `Panicked`: 0 bytes print-type-size type: `std::mem::ManuallyDrop<{async fn body of calls_fut<{async fn body of big_fut()}>()}>`: 3077 bytes, alignment: 1 bytes print-type-size field `.value`: 3077 bytes -print-type-size type: `std::mem::MaybeDangling<{async fn body of calls_fut<{async fn body of big_fut()}>()}>`: 3077 bytes, alignment: 1 bytes -print-type-size field `.0`: 3077 bytes print-type-size type: `std::mem::MaybeUninit<{async fn body of calls_fut<{async fn body of big_fut()}>()}>`: 3077 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 3077 bytes print-type-size field `.uninit`: 0 bytes @@ -38,8 +36,6 @@ print-type-size variant `Panicked`: 1025 bytes print-type-size upvar `.fut`: 1025 bytes print-type-size type: `std::mem::ManuallyDrop<{async fn body of big_fut()}>`: 1025 bytes, alignment: 1 bytes print-type-size field `.value`: 1025 bytes -print-type-size type: `std::mem::MaybeDangling<{async fn body of big_fut()}>`: 1025 bytes, alignment: 1 bytes -print-type-size field `.0`: 1025 bytes print-type-size type: `std::mem::MaybeUninit<{async fn body of big_fut()}>`: 1025 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 1025 bytes print-type-size field `.uninit`: 0 bytes @@ -93,10 +89,6 @@ print-type-size type: `std::mem::ManuallyDrop`: 1 bytes, alignment: 1 byte print-type-size field `.value`: 1 bytes print-type-size type: `std::mem::ManuallyDrop<{async fn body of wait()}>`: 1 bytes, alignment: 1 bytes print-type-size field `.value`: 1 bytes -print-type-size type: `std::mem::MaybeDangling`: 1 bytes, alignment: 1 bytes -print-type-size field `.0`: 1 bytes -print-type-size type: `std::mem::MaybeDangling<{async fn body of wait()}>`: 1 bytes, alignment: 1 bytes -print-type-size field `.0`: 1 bytes print-type-size type: `std::mem::MaybeUninit`: 1 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 1 bytes print-type-size field `.uninit`: 0 bytes diff --git a/tests/ui/async-await/future-sizes/large-arg.stdout b/tests/ui/async-await/future-sizes/large-arg.stdout index f65c5c1a7cb78..b6051da95ca42 100644 --- a/tests/ui/async-await/future-sizes/large-arg.stdout +++ b/tests/ui/async-await/future-sizes/large-arg.stdout @@ -7,8 +7,6 @@ print-type-size variant `Returned`: 0 bytes print-type-size variant `Panicked`: 0 bytes print-type-size type: `std::mem::ManuallyDrop<{async fn body of a<[u8; 1024]>()}>`: 3075 bytes, alignment: 1 bytes print-type-size field `.value`: 3075 bytes -print-type-size type: `std::mem::MaybeDangling<{async fn body of a<[u8; 1024]>()}>`: 3075 bytes, alignment: 1 bytes -print-type-size field `.0`: 3075 bytes print-type-size type: `std::mem::MaybeUninit<{async fn body of a<[u8; 1024]>()}>`: 3075 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 3075 bytes print-type-size field `.uninit`: 0 bytes @@ -26,8 +24,6 @@ print-type-size variant `Panicked`: 1024 bytes print-type-size upvar `.t`: 1024 bytes print-type-size type: `std::mem::ManuallyDrop<{async fn body of b<[u8; 1024]>()}>`: 2050 bytes, alignment: 1 bytes print-type-size field `.value`: 2050 bytes -print-type-size type: `std::mem::MaybeDangling<{async fn body of b<[u8; 1024]>()}>`: 2050 bytes, alignment: 1 bytes -print-type-size field `.0`: 2050 bytes print-type-size type: `std::mem::MaybeUninit<{async fn body of b<[u8; 1024]>()}>`: 2050 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 2050 bytes print-type-size field `.uninit`: 0 bytes @@ -45,8 +41,6 @@ print-type-size variant `Panicked`: 1024 bytes print-type-size upvar `.t`: 1024 bytes print-type-size type: `std::mem::ManuallyDrop<{async fn body of c<[u8; 1024]>()}>`: 1025 bytes, alignment: 1 bytes print-type-size field `.value`: 1025 bytes -print-type-size type: `std::mem::MaybeDangling<{async fn body of c<[u8; 1024]>()}>`: 1025 bytes, alignment: 1 bytes -print-type-size field `.0`: 1025 bytes print-type-size type: `std::mem::MaybeUninit<{async fn body of c<[u8; 1024]>()}>`: 1025 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 1025 bytes print-type-size field `.uninit`: 0 bytes diff --git a/tests/ui/c-variadic/pass-by-value-abi.aarch64.stderr b/tests/ui/c-variadic/pass-by-value-abi.aarch64.stderr index 45edd7bc0e0ee..c616e45a9ab8e 100644 --- a/tests/ui/c-variadic/pass-by-value-abi.aarch64.stderr +++ b/tests/ui/c-variadic/pass-by-value-abi.aarch64.stderr @@ -70,6 +70,7 @@ error: fn_abi_of(take_va_list) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/pass-by-value-abi.rs:27:1 | diff --git a/tests/ui/c-variadic/pass-by-value-abi.win.stderr b/tests/ui/c-variadic/pass-by-value-abi.win.stderr index d5da912a9b89a..638a0856b7b7f 100644 --- a/tests/ui/c-variadic/pass-by-value-abi.win.stderr +++ b/tests/ui/c-variadic/pass-by-value-abi.win.stderr @@ -66,6 +66,7 @@ error: fn_abi_of(take_va_list) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/pass-by-value-abi.rs:27:1 | diff --git a/tests/ui/c-variadic/pass-by-value-abi.x86_64.stderr b/tests/ui/c-variadic/pass-by-value-abi.x86_64.stderr index 1e203b93e66b3..776d0a72287f9 100644 --- a/tests/ui/c-variadic/pass-by-value-abi.x86_64.stderr +++ b/tests/ui/c-variadic/pass-by-value-abi.x86_64.stderr @@ -70,6 +70,7 @@ error: fn_abi_of(take_va_list) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/pass-by-value-abi.rs:27:1 | @@ -150,6 +151,7 @@ error: fn_abi_of(take_va_list_sysv64) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/pass-by-value-abi.rs:37:1 | @@ -230,6 +232,7 @@ error: fn_abi_of(take_va_list_win64) = FnAbi { Win64, ), can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/pass-by-value-abi.rs:44:1 | diff --git a/tests/ui/check-cfg/cfg-crate-features.stderr b/tests/ui/check-cfg/cfg-crate-features.stderr index 9bf3cef403159..d65562313cb42 100644 --- a/tests/ui/check-cfg/cfg-crate-features.stderr +++ b/tests/ui/check-cfg/cfg-crate-features.stderr @@ -24,7 +24,7 @@ warning: unexpected `cfg` condition value: `does_not_exist` LL | #![cfg(not(target(os = "does_not_exist")))] | ^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `qnx`, `qurt`, `redox`, `rtems`, and `solaris` and 15 more + = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `ps3`, `psp`, `psx`, `qnx`, `qurt`, `redox`, and `rtems` and 16 more = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 395a739b0be72..98404cd495dcf 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -232,7 +232,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_os = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `qnx`, `qurt`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` + = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `ps3`, `psp`, `psx`, `qnx`, `qurt`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -305,7 +305,7 @@ LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux` | | | help: there is a expected value with a similar name: `"linux"` | - = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `qnx`, `qurt`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` + = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `ps3`, `psp`, `psx`, `qnx`, `qurt`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` = note: see for more information about checking conditional configuration warning: 31 warnings emitted diff --git a/tests/ui/closures/closure-ref-fn-kind-mismatch-issue-161327.rs b/tests/ui/closures/closure-ref-fn-kind-mismatch-issue-161327.rs new file mode 100644 index 0000000000000..8233d6034a40a --- /dev/null +++ b/tests/ui/closures/closure-ref-fn-kind-mismatch-issue-161327.rs @@ -0,0 +1,73 @@ +fn req_fn(_: impl Fn(&'static str) -> String) {} +fn req_fn_mut(_: impl FnMut(&'static str) -> String) {} + +fn test_fn_mut_passed_as_mut_ref_to_fn() { + let mut v = Vec::new(); + let mut accumulate = |x| { + //~^ ERROR E0525 + v.push(x); + v.join("/") + }; + req_fn(&mut accumulate); +} + +fn test_fn_once_passed_as_mut_ref_to_fn() { + let s = String::new(); + let mut consume = move |_x| { + //~^ ERROR E0525 + drop(s); + String::new() + }; + req_fn(&mut consume); +} + +fn test_fn_once_passed_as_mut_ref_to_fn_mut() { + let s = String::new(); + let mut consume = move |_x| { + //~^ ERROR E0525 + drop(s); + String::new() + }; + req_fn_mut(&mut consume); +} + +fn test_double_ref_fn_mut_passed_to_fn() { + let mut v = Vec::new(); + let mut accumulate = |x| { + //~^ ERROR E0525 + v.push(x); + v.join("/") + }; + req_fn(&mut &mut accumulate); +} + +fn test_fn_passed_as_mut_ref_to_fn() { + let mut pure_closure = |x: &'static str| x.to_string(); + req_fn(&mut pure_closure); + //~^ ERROR E0277 +} + +fn test_nested_closure_conservative_fallback() { + let mut v = Vec::new(); + let s = String::new(); + let mut outer = |_x| { + v.push("a"); + let inner = || drop(s); + inner(); + v.join("/") + }; + req_fn(&mut outer); + //~^ ERROR E0277 +} + +fn test_unresolved_integer_fallback_copy() { + let x = 0; + let mut c = |_x| { + let _y = x; + String::new() + }; + req_fn(&mut c); + //~^ ERROR E0277 +} + +fn main() {} diff --git a/tests/ui/closures/closure-ref-fn-kind-mismatch-issue-161327.stderr b/tests/ui/closures/closure-ref-fn-kind-mismatch-issue-161327.stderr new file mode 100644 index 0000000000000..dfc657f6c3a00 --- /dev/null +++ b/tests/ui/closures/closure-ref-fn-kind-mismatch-issue-161327.stderr @@ -0,0 +1,145 @@ +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut` + --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:6:26 + | +LL | let mut accumulate = |x| { + | ^^^ this closure implements `FnMut`, not `Fn` +LL | +LL | v.push(x); + | - closure is `FnMut` because it mutates the variable `v` here +... +LL | req_fn(&mut accumulate); + | ------ --------------- the requirement to implement `Fn` derives from here + | | + | required by a bound introduced by this call + | +note: required by a bound in `req_fn` + --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:1:19 + | +LL | fn req_fn(_: impl Fn(&'static str) -> String) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `req_fn` + +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` + --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:16:23 + | +LL | let mut consume = move |_x| { + | ^^^^^^^^^ this closure implements `FnOnce`, not `Fn` +LL | +LL | drop(s); + | - closure is `FnOnce` because it moves the variable `s` out of its environment +... +LL | req_fn(&mut consume); + | ------ ------------ the requirement to implement `Fn` derives from here + | | + | required by a bound introduced by this call + | +note: required by a bound in `req_fn` + --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:1:19 + | +LL | fn req_fn(_: impl Fn(&'static str) -> String) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `req_fn` + +error[E0525]: expected a closure that implements the `FnMut` trait, but this closure only implements `FnOnce` + --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:26:23 + | +LL | let mut consume = move |_x| { + | ^^^^^^^^^ this closure implements `FnOnce`, not `FnMut` +LL | +LL | drop(s); + | - closure is `FnOnce` because it moves the variable `s` out of its environment +... +LL | req_fn_mut(&mut consume); + | ---------- ------- the requirement to implement `FnMut` derives from here + | | + | required by a bound introduced by this call + | + = note: required for `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:26:23: 26:32}` to implement `FnMut(&'static str)` +note: required by a bound in `req_fn_mut` + --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:2:23 + | +LL | fn req_fn_mut(_: impl FnMut(&'static str) -> String) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `req_fn_mut` + +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut` + --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:36:26 + | +LL | let mut accumulate = |x| { + | ^^^ this closure implements `FnMut`, not `Fn` +LL | +LL | v.push(x); + | - closure is `FnMut` because it mutates the variable `v` here +... +LL | req_fn(&mut &mut accumulate); + | ------ -------------------- the requirement to implement `Fn` derives from here + | | + | required by a bound introduced by this call + | +note: required by a bound in `req_fn` + --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:1:19 + | +LL | fn req_fn(_: impl Fn(&'static str) -> String) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `req_fn` + +error[E0277]: expected an `Fn(&'static str)` closure, found `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:45:28: 45:45}` + --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:46:12 + | +LL | req_fn(&mut pure_closure); + | ------ ^^^^^^^^^^^^^^^^^ expected an `Fn(&'static str)` closure, found `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:45:28: 45:45}` + | | + | required by a bound introduced by this call + | + = help: the trait `Fn(&'static str)` is not implemented for `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:45:28: 45:45}` +note: required by a bound in `req_fn` + --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:1:19 + | +LL | fn req_fn(_: impl Fn(&'static str) -> String) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `req_fn` +help: consider removing the leading `&`-reference + | +LL - req_fn(&mut pure_closure); +LL + req_fn(pure_closure); + | + +error[E0277]: expected an `Fn(&'static str)` closure, found `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:53:21: 53:25}` + --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:59:12 + | +LL | req_fn(&mut outer); + | ------ ^^^^^^^^^^ expected an `Fn(&'static str)` closure, found `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:53:21: 53:25}` + | | + | required by a bound introduced by this call + | + = help: the trait `Fn(&'static str)` is not implemented for `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:53:21: 53:25}` +note: required by a bound in `req_fn` + --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:1:19 + | +LL | fn req_fn(_: impl Fn(&'static str) -> String) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `req_fn` +help: consider removing the leading `&`-reference + | +LL - req_fn(&mut outer); +LL + req_fn(outer); + | + +error[E0277]: expected an `Fn(&'static str)` closure, found `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:65:17: 65:21}` + --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:69:12 + | +LL | req_fn(&mut c); + | ------ ^^^^^^ expected an `Fn(&'static str)` closure, found `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:65:17: 65:21}` + | | + | required by a bound introduced by this call + | + = help: the trait `Fn(&'static str)` is not implemented for `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:65:17: 65:21}` +note: required by a bound in `req_fn` + --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:1:19 + | +LL | fn req_fn(_: impl Fn(&'static str) -> String) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `req_fn` +help: consider removing the leading `&`-reference + | +LL - req_fn(&mut c); +LL + req_fn(c); + | + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0277, E0525. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/closures/fnmut-shared-reference-requires-fn.rs b/tests/ui/closures/fnmut-shared-reference-requires-fn.rs new file mode 100644 index 0000000000000..1207bc4cf1d52 --- /dev/null +++ b/tests/ui/closures/fnmut-shared-reference-requires-fn.rs @@ -0,0 +1,11 @@ +//! Do not suggest a mutable reference when the root obligation genuinely requires `Fn`. + +fn requires_fn(_: F) {} + +fn main() { + let mut value = 0; + let mut func = || value += 1; + //~^ ERROR expected a closure that implements the `Fn` trait + + requires_fn(&func); +} diff --git a/tests/ui/closures/fnmut-shared-reference-requires-fn.stderr b/tests/ui/closures/fnmut-shared-reference-requires-fn.stderr new file mode 100644 index 0000000000000..6a62f4d1a74c1 --- /dev/null +++ b/tests/ui/closures/fnmut-shared-reference-requires-fn.stderr @@ -0,0 +1,23 @@ +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut` + --> $DIR/fnmut-shared-reference-requires-fn.rs:7:20 + | +LL | let mut func = || value += 1; + | ^^ ----- closure is `FnMut` because it mutates the variable `value` here + | | + | this closure implements `FnMut`, not `Fn` +... +LL | requires_fn(&func); + | ----------- ---- the requirement to implement `Fn` derives from here + | | + | required by a bound introduced by this call + | + = note: required for `&{closure@$DIR/fnmut-shared-reference-requires-fn.rs:7:20: 7:22}` to implement `Fn()` +note: required by a bound in `requires_fn` + --> $DIR/fnmut-shared-reference-requires-fn.rs:3:19 + | +LL | fn requires_fn(_: F) {} + | ^^^^ required by this bound in `requires_fn` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/closures/fnmut-shared-reference-suggestion-issue-118843.fixed b/tests/ui/closures/fnmut-shared-reference-suggestion-issue-118843.fixed new file mode 100644 index 0000000000000..1918d26ac2d90 --- /dev/null +++ b/tests/ui/closures/fnmut-shared-reference-suggestion-issue-118843.fixed @@ -0,0 +1,13 @@ +//@ run-rustfix + +//! Regression test for https://github.com/rust-lang/rust/issues/118843. +//! A shared reference to an `FnMut` closure should suggest a mutable reference. + +fn main() { + let mut value = 0; + let mut func = |increment: usize| value += increment; + //~^ ERROR expected a closure that implements the `Fn` trait + + (0..100).for_each(&mut func); + //~^ HELP consider changing this borrow's mutability +} diff --git a/tests/ui/closures/fnmut-shared-reference-suggestion-issue-118843.rs b/tests/ui/closures/fnmut-shared-reference-suggestion-issue-118843.rs new file mode 100644 index 0000000000000..d7bd2fb60398a --- /dev/null +++ b/tests/ui/closures/fnmut-shared-reference-suggestion-issue-118843.rs @@ -0,0 +1,13 @@ +//@ run-rustfix + +//! Regression test for https://github.com/rust-lang/rust/issues/118843. +//! A shared reference to an `FnMut` closure should suggest a mutable reference. + +fn main() { + let mut value = 0; + let mut func = |increment: usize| value += increment; + //~^ ERROR expected a closure that implements the `Fn` trait + + (0..100).for_each(&func); + //~^ HELP consider changing this borrow's mutability +} diff --git a/tests/ui/closures/fnmut-shared-reference-suggestion-issue-118843.stderr b/tests/ui/closures/fnmut-shared-reference-suggestion-issue-118843.stderr new file mode 100644 index 0000000000000..817c073e92aa8 --- /dev/null +++ b/tests/ui/closures/fnmut-shared-reference-suggestion-issue-118843.stderr @@ -0,0 +1,24 @@ +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut` + --> $DIR/fnmut-shared-reference-suggestion-issue-118843.rs:8:20 + | +LL | let mut func = |increment: usize| value += increment; + | ^^^^^^^^^^^^^^^^^^ ----- closure is `FnMut` because it mutates the variable `value` here + | | + | this closure implements `FnMut`, not `Fn` +... +LL | (0..100).for_each(&func); + | -------- ---- the requirement to implement `Fn` derives from here + | | + | required by a bound introduced by this call + | + = note: required for `&{closure@$DIR/fnmut-shared-reference-suggestion-issue-118843.rs:8:20: 8:38}` to implement `FnMut(usize)` +note: required by a bound in `for_each` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +help: consider changing this borrow's mutability + | +LL | (0..100).for_each(&mut func); + | +++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr index 366711e6d43c7..3b53adb07a2b9 100644 --- a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr +++ b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr @@ -1,13 +1,13 @@ error[E0284]: type annotations needed for `([(); _], [(); 10])` - --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:32:9 + --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:31:9 | LL | let (mut arr, mut arr_with_weird_len) = free(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------ type must be known at this point | note: required by a const generic parameter in `free` - --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:27:9 + --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:26:9 | -LL | fn free() -> ([(); N], [(); FREE::]) { +LL | fn free() -> ([(); N], [(); core::direct_const_arg!(FREE::)]) { | ^^^^^^^^^^^^^^ required by this const generic parameter in `free` help: consider giving this pattern a type, where the value of const parameter `N` is specified | @@ -15,7 +15,7 @@ LL | let (mut arr, mut arr_with_weird_len): ([_; N], _) = free(); | +++++++++++++ error[E0271]: type mismatch resolving `FREE<10> == 2` - --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:38:45 + --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:37:45 | LL | let (mut arr, mut arr_with_weird_len) = free(); | ^^^^^^ expected `2`, found `10` @@ -24,16 +24,16 @@ LL | let (mut arr, mut arr_with_weird_len) = free(); found constant `10` error[E0284]: type annotations needed for `([(); _], [(); 10])` - --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:49:9 + --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:48:9 | LL | let (mut arr, mut arr_with_weird_len) = proj(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------ type must be known at this point | = note: cannot satisfy `::PROJ<_> == 10` note: required by a const generic parameter in `proj` - --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:44:9 + --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:43:9 | -LL | fn proj() -> ([(); N], [(); ::PROJ::]) { +LL | fn proj() -> ([(); N], [(); core::direct_const_arg!(::PROJ::)]) { | ^^^^^^^^^^^^^^ required by this const generic parameter in `proj` help: consider giving this pattern a type, where the value of const parameter `N` is specified | @@ -41,7 +41,7 @@ LL | let (mut arr, mut arr_with_weird_len): ([_; N], _) = proj(); | +++++++++++++ error[E0271]: type mismatch resolving `::PROJ<10> == 2` - --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:55:45 + --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:54:45 | LL | let (mut arr, mut arr_with_weird_len) = proj(); | ^^^^^^ expected `2`, found `10` diff --git a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.old.stderr b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.old.stderr index 11274b947b8f6..4306110c8433d 100644 --- a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.old.stderr +++ b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.old.stderr @@ -1,5 +1,5 @@ error: `generic_const_args` requires -Znext-solver=globally to be enabled - --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:10:5 + --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:9:5 | LL | generic_const_args, | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs index ef6d047309b13..8ee278af6ef56 100644 --- a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs +++ b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs @@ -6,7 +6,6 @@ #![feature( min_generic_const_args, - macroless_generic_const_args, generic_const_args, //[old]~^ ERROR next-solver generic_const_items @@ -24,7 +23,7 @@ impl Trait for S { const PROJ: usize = 10; } -fn free() -> ([(); N], [(); FREE::]) { +fn free() -> ([(); N], [(); core::direct_const_arg!(FREE::)]) { loop {} } @@ -41,7 +40,7 @@ fn test_free_mismatch() { arr = [(); 10]; } -fn proj() -> ([(); N], [(); ::PROJ::]) { +fn proj() -> ([(); N], [(); core::direct_const_arg!(::PROJ::)]) { loop {} } diff --git a/tests/ui/const-generics/gca/assoc-const.rs b/tests/ui/const-generics/gca/assoc-const.rs new file mode 100644 index 0000000000000..8a8d1b52e7e5a --- /dev/null +++ b/tests/ui/const-generics/gca/assoc-const.rs @@ -0,0 +1,22 @@ +//@ check-pass +//@ compile-flags: -Znext-solver +#![feature(min_generic_const_args, generic_const_args)] + +trait Trait { + const ASSOC: usize; +} + +impl Trait for T { + const ASSOC: usize = core::direct_const_arg!(T::RIGID); +} + +trait Other { + const RIGID: usize; +} + +fn foo() { + let a: [(); core::direct_const_arg!(::ASSOC)] = + [(); core::direct_const_arg!(T::RIGID)]; +} + +fn main() {} diff --git a/tests/ui/const-generics/gca/non-type-equality-fail.rs b/tests/ui/const-generics/gca/non-type-equality-fail.rs index 6e71125a4cffb..e058648e3da54 100644 --- a/tests/ui/const-generics/gca/non-type-equality-fail.rs +++ b/tests/ui/const-generics/gca/non-type-equality-fail.rs @@ -1,6 +1,6 @@ //@ compile-flags: -Znext-solver -#![feature(min_generic_const_args, macroless_generic_const_args, generic_const_args)] +#![feature(min_generic_const_args, generic_const_args)] #![expect(incomplete_features)] trait Trait { @@ -27,13 +27,14 @@ const FREE_B: usize = 1; struct Struct; fn f() { - let _: Struct<{ as Trait>::PROJECTED_A }> = - Struct::<{ as Trait>::PROJECTED_B }>; + let _: Struct<{ core::direct_const_arg!( as Trait>::PROJECTED_A) }> = + Struct::<{ core::direct_const_arg!( as Trait>::PROJECTED_B) }>; //~^ ERROR mismatched types } fn g() { - let _: Struct<{ T::PROJECTED_A }> = Struct::<{ T::PROJECTED_B }>; + let _: Struct<{ core::direct_const_arg!(T::PROJECTED_A) }> = + Struct::<{ core::direct_const_arg!(T::PROJECTED_B) }>; //~^ ERROR mismatched types } diff --git a/tests/ui/const-generics/gca/non-type-equality-fail.stderr b/tests/ui/const-generics/gca/non-type-equality-fail.stderr index 5a9c1bb6d4faa..28557d76d84e5 100644 --- a/tests/ui/const-generics/gca/non-type-equality-fail.stderr +++ b/tests/ui/const-generics/gca/non-type-equality-fail.stderr @@ -1,21 +1,21 @@ error[E0308]: mismatched types --> $DIR/non-type-equality-fail.rs:31:9 | -LL | let _: Struct<{ as Trait>::PROJECTED_A }> = - | -------------------------------------------------------- expected due to this -LL | Struct::<{ as Trait>::PROJECTED_B }>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected ` as Trait>::PROJECTED_A`, found ` as Trait>::PROJECTED_B` +LL | let _: Struct<{ core::direct_const_arg!( as Trait>::PROJECTED_A) }> = + | --------------------------------------------------------------------------------- expected due to this +LL | Struct::<{ core::direct_const_arg!( as Trait>::PROJECTED_B) }>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected ` as Trait>::PROJECTED_A`, found ` as Trait>::PROJECTED_B` | = note: expected struct `Struct< as Trait>::PROJECTED_A>` found struct `Struct< as Trait>::PROJECTED_B>` error[E0308]: mismatched types - --> $DIR/non-type-equality-fail.rs:36:41 + --> $DIR/non-type-equality-fail.rs:37:9 | -LL | let _: Struct<{ T::PROJECTED_A }> = Struct::<{ T::PROJECTED_B }>; - | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `::PROJECTED_A`, found `::PROJECTED_B` - | | - | expected due to this +LL | let _: Struct<{ core::direct_const_arg!(T::PROJECTED_A) }> = + | --------------------------------------------------- expected due to this +LL | Struct::<{ core::direct_const_arg!(T::PROJECTED_B) }>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `::PROJECTED_A`, found `::PROJECTED_B` | = note: expected struct `Struct<::PROJECTED_A>` found struct `Struct<::PROJECTED_B>` diff --git a/tests/ui/const-generics/gca/non-type-equality-ok.rs b/tests/ui/const-generics/gca/non-type-equality-ok.rs index e476b5d8124ca..45dcef1f2dc00 100644 --- a/tests/ui/const-generics/gca/non-type-equality-ok.rs +++ b/tests/ui/const-generics/gca/non-type-equality-ok.rs @@ -35,6 +35,8 @@ struct Struct; fn f() { let _: Struct<{ as Trait>::PROJECTED_A }> = Struct::<{ as Trait>::PROJECTED_A }>; + let _: Struct<{ as Trait>::PROJECTED_A }> = + Struct::<{ as Trait>::PROJECTED_B }>; } fn g() { diff --git a/tests/ui/const-generics/gca/wf-inherentimpl.old.stderr b/tests/ui/const-generics/gca/wf-inherentimpl.old.stderr index 0766847a93b18..5a9dd515868b9 100644 --- a/tests/ui/const-generics/gca/wf-inherentimpl.old.stderr +++ b/tests/ui/const-generics/gca/wf-inherentimpl.old.stderr @@ -1,5 +1,5 @@ error: `generic_const_args` requires -Znext-solver=globally to be enabled - --> $DIR/wf-inherentimpl.rs:7:12 + --> $DIR/wf-inherentimpl.rs:6:12 | LL | #![feature(generic_const_args, min_generic_const_args)] | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/gca/wf-inherentimpl.rs b/tests/ui/const-generics/gca/wf-inherentimpl.rs index cb3df20daa2dc..c0a7e7f930877 100644 --- a/tests/ui/const-generics/gca/wf-inherentimpl.rs +++ b/tests/ui/const-generics/gca/wf-inherentimpl.rs @@ -3,13 +3,12 @@ //@[next] compile-flags: -Znext-solver //@ ignore-compare-mode-next-solver (explicit revisions) #![feature(inherent_associated_types)] -#![feature(macroless_generic_const_args)] #![feature(generic_const_args, min_generic_const_args)] //[old]~^ ERROR `generic_const_args` requires -Znext-solver=globally to be enabled struct Foo; impl Foo { const SIZE: usize = { todo!() }; - fn to_bytes() -> [u8; Self::SIZE] { + fn to_bytes() -> [u8; core::direct_const_arg!(Self::SIZE)] { todo!() } } diff --git a/tests/ui/consts/array-type-usize-suggestion.rs b/tests/ui/consts/array-type-usize-suggestion.rs new file mode 100644 index 0000000000000..a86613ba8d4df --- /dev/null +++ b/tests/ui/consts/array-type-usize-suggestion.rs @@ -0,0 +1,9 @@ +//@ check-fail + +fn main() { + let length = 3; + let values: [i32; length] = [0; length]; + //~^ ERROR attempt to use a non-constant value in a constant [E0435] + //~| ERROR attempt to use a non-constant value in a constant [E0435] + println!("{}", values.len()); +} diff --git a/tests/ui/consts/array-type-usize-suggestion.stderr b/tests/ui/consts/array-type-usize-suggestion.stderr new file mode 100644 index 0000000000000..aef1cbee06011 --- /dev/null +++ b/tests/ui/consts/array-type-usize-suggestion.stderr @@ -0,0 +1,27 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/array-type-usize-suggestion.rs:5:23 + | +LL | let values: [i32; length] = [0; length]; + | ^^^^^^ non-constant value + | +help: consider using `const` instead of `let` + | +LL - let length = 3; +LL + const length: usize = 3; + | + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/array-type-usize-suggestion.rs:5:37 + | +LL | let values: [i32; length] = [0; length]; + | ^^^^^^ non-constant value + | +help: consider using `const` instead of `let` + | +LL - let length = 3; +LL + const length: usize = 3; + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/consts/non-const-value-in-const.stderr b/tests/ui/consts/non-const-value-in-const.stderr index 201c310843b38..67478a4f84727 100644 --- a/tests/ui/consts/non-const-value-in-const.stderr +++ b/tests/ui/consts/non-const-value-in-const.stderr @@ -19,7 +19,7 @@ LL | let _ = [0; x]; help: consider using `const` instead of `let` | LL - let x = 5; -LL + const x: /* Type */ = 5; +LL + const x: usize = 5; | error: aborting due to 2 previous errors diff --git a/tests/ui/error-codes/E0789.rs b/tests/ui/error-codes/E0789.rs index 4a55e1743158d..3b83d88aa9eaf 100644 --- a/tests/ui/error-codes/E0789.rs +++ b/tests/ui/error-codes/E0789.rs @@ -4,7 +4,7 @@ #![feature(staged_api)] #![unstable(feature = "foo_module", reason = "...", issue = "123")] -#[rustc_allowed_through_unstable_modules = "use stable path instead"] +#[rustc_allowed_through_unstable_modules(message = "use stable path instead", module = "stable")] // #[stable(feature = "foo", since = "1.0")] struct Foo; //~^ ERROR `rustc_allowed_through_unstable_modules` attribute must be paired with a `stable` attribute diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr index 96cef0a6a5c9e..2671765ef8e6b 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr @@ -8,14 +8,6 @@ LL | call(f, ()); | = note: expected a closure with signature `for<'a> fn(<_ as ATC<'a>>::Type)` found a closure with signature `fn(())` -note: this is a known limitation of the trait solver that will be lifted in the future - --> $DIR/issue-62529-3.rs:25:14 - | -LL | call(f, ()); - | -----^----- - | | | - | | the trait solver is unable to infer the generic types that should be inferred from this argument - | add turbofish arguments to this call to specify the types manually, even if it's redundant note: required by a bound in `call` --> $DIR/issue-62529-3.rs:9:36 | diff --git a/tests/ui/macros/correct-meta-item-span.rs b/tests/ui/macros/correct-meta-item-span.rs new file mode 100644 index 0000000000000..9c3e464024ded --- /dev/null +++ b/tests/ui/macros/correct-meta-item-span.rs @@ -0,0 +1,8 @@ +// The span of the suggestion should be correct and not ICE on this code (#161472) +macro_rules! m { ($m:meta) => { #[derive($m)] pub struct S; }; } + +m!(a(::b::c)); +//~^ ERROR traits in `#[derive(...)]` don't accept arguments +//~| ERROR cannot find derive macro `a` in this scope +//~| ERROR cannot find derive macro `a` in this scope +fn main(){} diff --git a/tests/ui/macros/correct-meta-item-span.stderr b/tests/ui/macros/correct-meta-item-span.stderr new file mode 100644 index 0000000000000..8091f3adf70eb --- /dev/null +++ b/tests/ui/macros/correct-meta-item-span.stderr @@ -0,0 +1,22 @@ +error: traits in `#[derive(...)]` don't accept arguments + --> $DIR/correct-meta-item-span.rs:4:5 + | +LL | m!(a(::b::c)); + | ^^^^^^^^ help: remove the arguments + +error: cannot find derive macro `a` in this scope + --> $DIR/correct-meta-item-span.rs:4:4 + | +LL | m!(a(::b::c)); + | ^ + +error: cannot find derive macro `a` in this scope + --> $DIR/correct-meta-item-span.rs:4:4 + | +LL | m!(a(::b::c)); + | ^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/mismatched_types/closure-mismatch.next.stderr b/tests/ui/mismatched_types/closure-mismatch.next.stderr index 6b4620aa8d1ba..a6380b7487dad 100644 --- a/tests/ui/mismatched_types/closure-mismatch.next.stderr +++ b/tests/ui/mismatched_types/closure-mismatch.next.stderr @@ -9,14 +9,6 @@ LL | baz(|_| ()); = help: the trait `for<'a> FnOnce(&'a ())` is not implemented for closure `{closure@$DIR/closure-mismatch.rs:12:9: 12:12}` = note: expected a closure with signature `for<'a> fn(&'a ())` found a closure with signature `fn(&())` -note: this is a known limitation of the trait solver that will be lifted in the future - --> $DIR/closure-mismatch.rs:12:9 - | -LL | baz(|_| ()); - | ----^^^---- - | | | - | | the trait solver is unable to infer the generic types that should be inferred from this argument - | add turbofish arguments to this call to specify the types manually, even if it's redundant note: required for `{closure@$DIR/closure-mismatch.rs:12:9: 12:12}` to implement `Foo` --> $DIR/closure-mismatch.rs:7:18 | @@ -41,14 +33,6 @@ LL | baz(|x| ()); = help: the trait `for<'a> FnOnce(&'a ())` is not implemented for closure `{closure@$DIR/closure-mismatch.rs:16:9: 16:12}` = note: expected a closure with signature `for<'a> fn(&'a ())` found a closure with signature `fn(&())` -note: this is a known limitation of the trait solver that will be lifted in the future - --> $DIR/closure-mismatch.rs:16:9 - | -LL | baz(|x| ()); - | ----^^^---- - | | | - | | the trait solver is unable to infer the generic types that should be inferred from this argument - | add turbofish arguments to this call to specify the types manually, even if it's redundant note: required for `{closure@$DIR/closure-mismatch.rs:16:9: 16:12}` to implement `Foo` --> $DIR/closure-mismatch.rs:7:18 | diff --git a/tests/ui/parser/recover/array-type-no-semi.stderr b/tests/ui/parser/recover/array-type-no-semi.stderr index 0af085140223e..01fcc3766f635 100644 --- a/tests/ui/parser/recover/array-type-no-semi.stderr +++ b/tests/ui/parser/recover/array-type-no-semi.stderr @@ -68,7 +68,7 @@ LL | let c: [i32, x]; help: consider using `const` instead of `let` | LL - let x = 5; -LL + const x: /* Type */ = 5; +LL + const x: usize = 5; | error[E0423]: cannot find value `i32` in this scope diff --git a/tests/ui/print_type_sizes/async.stdout b/tests/ui/print_type_sizes/async.stdout index c068818fdc9a5..0499531158844 100644 --- a/tests/ui/print_type_sizes/async.stdout +++ b/tests/ui/print_type_sizes/async.stdout @@ -12,8 +12,6 @@ print-type-size variant `Panicked`: 8192 bytes print-type-size upvar `.arg`: 8192 bytes print-type-size type: `std::mem::ManuallyDrop<[u8; 8192]>`: 8192 bytes, alignment: 1 bytes print-type-size field `.value`: 8192 bytes -print-type-size type: `std::mem::MaybeDangling<[u8; 8192]>`: 8192 bytes, alignment: 1 bytes -print-type-size field `.0`: 8192 bytes print-type-size type: `std::mem::MaybeUninit<[u8; 8192]>`: 8192 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 8192 bytes print-type-size field `.uninit`: 0 bytes @@ -53,8 +51,6 @@ print-type-size type: `std::ptr::NonNull>`: 8 bytes, alig print-type-size field `.pointer`: 8 bytes print-type-size type: `std::mem::ManuallyDrop<{async fn body of wait()}>`: 1 bytes, alignment: 1 bytes print-type-size field `.value`: 1 bytes -print-type-size type: `std::mem::MaybeDangling<{async fn body of wait()}>`: 1 bytes, alignment: 1 bytes -print-type-size field `.0`: 1 bytes print-type-size type: `std::mem::MaybeUninit<{async fn body of wait()}>`: 1 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 1 bytes print-type-size field `.uninit`: 0 bytes diff --git a/tests/ui/print_type_sizes/coroutine_discr_placement.stdout b/tests/ui/print_type_sizes/coroutine_discr_placement.stdout index b51beb514ba80..4ce1ce46f6e82 100644 --- a/tests/ui/print_type_sizes/coroutine_discr_placement.stdout +++ b/tests/ui/print_type_sizes/coroutine_discr_placement.stdout @@ -11,8 +11,6 @@ print-type-size variant `Returned`: 0 bytes print-type-size variant `Panicked`: 0 bytes print-type-size type: `std::mem::ManuallyDrop`: 4 bytes, alignment: 4 bytes print-type-size field `.value`: 4 bytes -print-type-size type: `std::mem::MaybeDangling`: 4 bytes, alignment: 4 bytes -print-type-size field `.0`: 4 bytes print-type-size type: `std::mem::MaybeUninit`: 4 bytes, alignment: 4 bytes print-type-size variant `MaybeUninit`: 4 bytes print-type-size field `.uninit`: 0 bytes diff --git a/tests/ui/repeat-expr/repeat_count.stderr b/tests/ui/repeat-expr/repeat_count.stderr index e2cecf9973b8b..91d6a5d79d0ac 100644 --- a/tests/ui/repeat-expr/repeat_count.stderr +++ b/tests/ui/repeat-expr/repeat_count.stderr @@ -7,7 +7,7 @@ LL | let a = [0; n]; help: consider using `const` instead of `let` | LL - let n = 1; -LL + const n: /* Type */ = 1; +LL + const n: usize = 1; | error[E0308]: mismatched types diff --git a/tests/ui/splat/splat-invalid.rs b/tests/ui/splat/splat-invalid.rs index a9586b056d8e7..9a0101636a8b0 100644 --- a/tests/ui/splat/splat-invalid.rs +++ b/tests/ui/splat/splat-invalid.rs @@ -61,4 +61,27 @@ impl FooTrait for Foo { fn no_splat(#[rustc_splat] _: (u32, f64)) {} //~ ERROR method `no_splat` has an incompatible type for trait } -fn main() {} +#[rustfmt::skip] +fn main() { + let multisplat_fn_bad_: + fn(#[rustc_splat] (u32, i8), #[rustc_splat] (u32, i8)) = multisplat_fn_bad; + //~^ ERROR multiple `#[rustc_splat]`s are not allowed in the same function argument list + let multisplat_arg_bad_: fn( + #[rustc_splat] + #[rustc_splat] + (u32, i8), + ) = multisplat_arg_bad; + let multisplat_arg_fn_bad_: fn( + #[rustc_splat] + //~^ ERROR multiple `#[rustc_splat]`s are not allowed in the same function argument list + #[rustc_splat] + (u32, i8), + #[rustc_splat] (u32, i8), + ) = multisplat_arg_fn_bad; + + let splat_variadic_: unsafe extern "C" fn(#[rustc_splat] (u32, i8), ...) = splat_variadic; + //~^ ERROR `...` and `#[rustc_splat]` are not allowed in the same function argument list + let splat_variadic2_: unsafe extern "C" fn(..., #[rustc_splat] (u32, i8)) = splat_variadic2; + //~^ ERROR `...` must be the last argument of a C-variadic function + //~| ERROR `...` and `#[rustc_splat]` are not allowed in the same function argument list +} diff --git a/tests/ui/splat/splat-invalid.stderr b/tests/ui/splat/splat-invalid.stderr index 771556d3e91a9..f1c492bd3e37e 100644 --- a/tests/ui/splat/splat-invalid.stderr +++ b/tests/ui/splat/splat-invalid.stderr @@ -87,6 +87,50 @@ LL | fn splat_variadic4(..., #[rustc_splat] (_a, _b): (u32, i8)) {} | = help: remove `#[rustc_splat]` or remove `...` +error: multiple `#[rustc_splat]`s are not allowed in the same function argument list + --> $DIR/splat-invalid.rs:67:12 + | +LL | fn(#[rustc_splat] (u32, i8), #[rustc_splat] (u32, i8)) = multisplat_fn_bad; + | ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ + | + = help: remove `#[rustc_splat]` from all but one argument + +error: multiple `#[rustc_splat]`s are not allowed in the same function argument list + --> $DIR/splat-invalid.rs:75:9 + | +LL | #[rustc_splat] + | ^^^^^^^^^^^^^^ +LL | +LL | #[rustc_splat] + | ^^^^^^^^^^^^^^ +LL | (u32, i8), +LL | #[rustc_splat] (u32, i8), + | ^^^^^^^^^^^^^^ + | + = help: remove `#[rustc_splat]` from all but one argument + +error: `...` and `#[rustc_splat]` are not allowed in the same function argument list + --> $DIR/splat-invalid.rs:82:47 + | +LL | let splat_variadic_: unsafe extern "C" fn(#[rustc_splat] (u32, i8), ...) = splat_variadic; + | ^^^^^^^^^^^^^^ ^^^ + | + = help: remove `#[rustc_splat]` or remove `...` + +error: `...` must be the last argument of a C-variadic function + --> $DIR/splat-invalid.rs:84:48 + | +LL | let splat_variadic2_: unsafe extern "C" fn(..., #[rustc_splat] (u32, i8)) = splat_variadic2; + | ^^^ + +error: `...` and `#[rustc_splat]` are not allowed in the same function argument list + --> $DIR/splat-invalid.rs:84:48 + | +LL | let splat_variadic2_: unsafe extern "C" fn(..., #[rustc_splat] (u32, i8)) = splat_variadic2; + | ^^^ ^^^^^^^^^^^^^^ + | + = help: remove `#[rustc_splat]` or remove `...` + error: multiple `rustc_splat` attributes --> $DIR/splat-invalid.rs:11:5 | @@ -139,6 +183,6 @@ LL | fn no_splat(_: (u32, f64)); = note: expected signature `fn((_, _))` found signature `fn(#[rustc_splat] (_, _))` -error: aborting due to 14 previous errors +error: aborting due to 19 previous errors For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/splat/splat-non-tuple.rs b/tests/ui/splat/splat-non-tuple.rs index e1b115432d788..a11d94a1fbb99 100644 --- a/tests/ui/splat/splat-non-tuple.rs +++ b/tests/ui/splat/splat-non-tuple.rs @@ -84,6 +84,11 @@ fn main() { primitive_arg(1u32); enum_arg(NotATuple::A(1u32)); + #[rustfmt::skip] + let primitive_arg_: fn(#[rustc_splat] u32) = primitive_arg; + primitive_arg_(1u32); + //~^ ERROR cannot use `rustc_splat` attribute; the splatted argument type must be a tuple or unit, not a u32 + let foo = Foo; struct_arg(foo); foo.tuple_2_self((1u32, 2i8)); diff --git a/tests/ui/splat/splat-non-tuple.stderr b/tests/ui/splat/splat-non-tuple.stderr index d51968eac80c0..b92c257b9b021 100644 --- a/tests/ui/splat/splat-non-tuple.stderr +++ b/tests/ui/splat/splat-non-tuple.stderr @@ -30,6 +30,12 @@ LL | fn enum_arg(#[rustc_splat] y: NotATuple) {} LL | enum_arg(NotATuple::A(1u32)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error[E0277]: cannot use `rustc_splat` attribute; the splatted argument type must be a tuple or unit, not a u32 (u32) + --> $DIR/splat-non-tuple.rs:89:5 + | +LL | primitive_arg_(1u32); + | ^^^^^^^^^^^^^^^^^^^^ + error[E0277]: cannot use `rustc_splat` attribute; the splatted argument type must be a tuple or unit, not a Foo (Foo) --> $DIR/splat-non-tuple.rs:25:33 | @@ -48,7 +54,7 @@ LL | fn tuple_struct_arg(#[rustc_splat] z: TupleStruct) {} LL | tuple_struct_arg(tuple_struct); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors Some errors have detailed explanations: E0053, E0277. For more information about an error, try `rustc --explain E0053`. diff --git a/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr b/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr index 16e3676aa6503..b0b1f78cb28b2 100644 --- a/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr +++ b/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr @@ -7,13 +7,18 @@ LL | use core::unicode::UNICODE_VERSION; = help: add `#![feature(unicode_internals)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -warning: use of deprecated module `std::intrinsics`: import this function via `std::mem` instead - --> $DIR/accidental-stable-in-unstable.rs:10:23 +warning: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidental-stable-in-unstable.rs:10:5 | LL | use core::intrinsics::transmute; // depended upon by rand_core - | ^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(deprecated)]` on by default +help: import this function via the `mem` module instead + | +LL - use core::intrinsics::transmute; // depended upon by rand_core +LL + use core::mem::transmute; // depended upon by rand_core + | error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/stability-attribute/accidentally-stable-intrinsics.fixed b/tests/ui/stability-attribute/accidentally-stable-intrinsics.fixed new file mode 100644 index 0000000000000..41917c65f5215 --- /dev/null +++ b/tests/ui/stability-attribute/accidentally-stable-intrinsics.fixed @@ -0,0 +1,39 @@ +//@ run-rustfix +#![crate_type = "lib"] +#![allow(unnecessary_transmutes, unused_imports)] +#![deny(deprecated)] + +extern crate core; + +use std::mem::transmute as _; +//~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +use core::ptr::copy as _; +//~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +use std::ptr::copy_nonoverlapping as _; +//~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +use core::ptr::write_bytes as _; +//~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + +use core::ptr::{ + copy as _, + //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + copy_nonoverlapping as _, + //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + write_bytes as _, + //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +}; + +pub fn what() { + unsafe { + let value = 42_u8; + let mut dst = 0; + let _ = std::mem::transmute::(value); + //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + core::ptr::copy(&value, &mut dst, 1); + //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + core::ptr::copy_nonoverlapping(&value, &mut dst, 1); + //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + std::ptr::write_bytes(&mut dst, value, 1) + //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + } +} diff --git a/tests/ui/stability-attribute/accidentally-stable-intrinsics.rs b/tests/ui/stability-attribute/accidentally-stable-intrinsics.rs new file mode 100644 index 0000000000000..189927e9e8989 --- /dev/null +++ b/tests/ui/stability-attribute/accidentally-stable-intrinsics.rs @@ -0,0 +1,39 @@ +//@ run-rustfix +#![crate_type = "lib"] +#![allow(unnecessary_transmutes, unused_imports)] +#![deny(deprecated)] + +extern crate core; + +use std::intrinsics::transmute as _; +//~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +use core::intrinsics::copy as _; +//~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +use std::intrinsics::copy_nonoverlapping as _; +//~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +use core::intrinsics::write_bytes as _; +//~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + +use core::intrinsics::{ + copy as _, + //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + copy_nonoverlapping as _, + //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + write_bytes as _, + //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +}; + +pub fn what() { + unsafe { + let value = 42_u8; + let mut dst = 0; + let _ = std::intrinsics::transmute::(value); + //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + core::intrinsics::copy(&value, &mut dst, 1); + //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + core::intrinsics::copy_nonoverlapping(&value, &mut dst, 1); + //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + std::intrinsics::write_bytes(&mut dst, value, 1) + //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + } +} diff --git a/tests/ui/stability-attribute/accidentally-stable-intrinsics.stderr b/tests/ui/stability-attribute/accidentally-stable-intrinsics.stderr new file mode 100644 index 0000000000000..645437a306f74 --- /dev/null +++ b/tests/ui/stability-attribute/accidentally-stable-intrinsics.stderr @@ -0,0 +1,139 @@ +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:8:5 + | +LL | use std::intrinsics::transmute as _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/accidentally-stable-intrinsics.rs:4:9 + | +LL | #![deny(deprecated)] + | ^^^^^^^^^^ +help: import this function via the `mem` module instead + | +LL - use std::intrinsics::transmute as _; +LL + use std::mem::transmute as _; + | + +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:10:5 + | +LL | use core::intrinsics::copy as _; + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: import this function via the `ptr` module instead + | +LL - use core::intrinsics::copy as _; +LL + use core::ptr::copy as _; + | + +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:12:5 + | +LL | use std::intrinsics::copy_nonoverlapping as _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: import this function via the `ptr` module instead + | +LL - use std::intrinsics::copy_nonoverlapping as _; +LL + use std::ptr::copy_nonoverlapping as _; + | + +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:14:5 + | +LL | use core::intrinsics::write_bytes as _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: import this function via the `ptr` module instead + | +LL - use core::intrinsics::write_bytes as _; +LL + use core::ptr::write_bytes as _; + | + +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:18:5 + | +LL | copy as _, + | ^^^^ + | +help: import this function via the `ptr` module instead + | +LL - use core::intrinsics::{ +LL + use core::ptr::{ + | + +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:20:5 + | +LL | copy_nonoverlapping as _, + | ^^^^^^^^^^^^^^^^^^^ + | +help: import this function via the `ptr` module instead + | +LL - use core::intrinsics::{ +LL + use core::ptr::{ + | + +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:22:5 + | +LL | write_bytes as _, + | ^^^^^^^^^^^ + | +help: import this function via the `ptr` module instead + | +LL - use core::intrinsics::{ +LL + use core::ptr::{ + | + +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:30:17 + | +LL | let _ = std::intrinsics::transmute::(value); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: import this function via the `mem` module instead + | +LL - let _ = std::intrinsics::transmute::(value); +LL + let _ = std::mem::transmute::(value); + | + +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:32:9 + | +LL | core::intrinsics::copy(&value, &mut dst, 1); + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: import this function via the `ptr` module instead + | +LL - core::intrinsics::copy(&value, &mut dst, 1); +LL + core::ptr::copy(&value, &mut dst, 1); + | + +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:34:9 + | +LL | core::intrinsics::copy_nonoverlapping(&value, &mut dst, 1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: import this function via the `ptr` module instead + | +LL - core::intrinsics::copy_nonoverlapping(&value, &mut dst, 1); +LL + core::ptr::copy_nonoverlapping(&value, &mut dst, 1); + | + +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:36:9 + | +LL | std::intrinsics::write_bytes(&mut dst, value, 1) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: import this function via the `ptr` module instead + | +LL - std::intrinsics::write_bytes(&mut dst, value, 1) +LL + std::ptr::write_bytes(&mut dst, value, 1) + | + +error: aborting due to 11 previous errors + diff --git a/tests/ui/stability-attribute/allowed-through-unstable.rs b/tests/ui/stability-attribute/allowed-through-unstable.rs index 5baa0fda94037..eaa3ad9b830b4 100644 --- a/tests/ui/stability-attribute/allowed-through-unstable.rs +++ b/tests/ui/stability-attribute/allowed-through-unstable.rs @@ -1,9 +1,9 @@ -// Test for new `#[rustc_allowed_through_unstable_modules]` attribute +// Test for `#[rustc_allowed_through_unstable_modules]` attribute // //@ aux-build:allowed-through-unstable-core.rs #![crate_type = "lib"] extern crate allowed_through_unstable_core; -use allowed_through_unstable_core::unstable_module::OldStableTraitAllowedThoughUnstable; //~WARN use of deprecated module `allowed_through_unstable_core::unstable_module`: use the new path instead +use allowed_through_unstable_core::unstable_module::OldStableTraitAllowedThoughUnstable; //~WARN use of deprecated import through accidentally stabilized module `unstable_module` use allowed_through_unstable_core::unstable_module::NewStableTraitNotAllowedThroughUnstable; //~ ERROR use of unstable library feature `unstable_test_feature` diff --git a/tests/ui/stability-attribute/allowed-through-unstable.stderr b/tests/ui/stability-attribute/allowed-through-unstable.stderr index 3098f1c961f95..160dd4d4babff 100644 --- a/tests/ui/stability-attribute/allowed-through-unstable.stderr +++ b/tests/ui/stability-attribute/allowed-through-unstable.stderr @@ -1,10 +1,15 @@ -warning: use of deprecated module `allowed_through_unstable_core::unstable_module`: use the new path instead - --> $DIR/allowed-through-unstable.rs:8:53 +warning: use of deprecated import through accidentally stabilized module `unstable_module` + --> $DIR/allowed-through-unstable.rs:8:5 | LL | use allowed_through_unstable_core::unstable_module::OldStableTraitAllowedThoughUnstable; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(deprecated)]` on by default +help: use the new path instead + | +LL - use allowed_through_unstable_core::unstable_module::OldStableTraitAllowedThoughUnstable; +LL + use allowed_through_unstable_core::stable::OldStableTraitAllowedThoughUnstable; + | error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/allowed-through-unstable.rs:9:36 diff --git a/tests/ui/stability-attribute/auxiliary/allowed-through-unstable-core.rs b/tests/ui/stability-attribute/auxiliary/allowed-through-unstable-core.rs index 23c722d6e8eba..5f7e344aece60 100644 --- a/tests/ui/stability-attribute/auxiliary/allowed-through-unstable-core.rs +++ b/tests/ui/stability-attribute/auxiliary/allowed-through-unstable-core.rs @@ -6,7 +6,10 @@ #[unstable(feature = "unstable_test_feature", issue = "1")] pub mod unstable_module { #[stable(feature = "stable_test_feature", since = "1.2.0")] - #[rustc_allowed_through_unstable_modules = "use the new path instead"] + #[rustc_allowed_through_unstable_modules( + message= "use the new path instead", + module = "stable", + )] pub trait OldStableTraitAllowedThoughUnstable {} #[stable(feature = "stable_test_feature", since = "1.2.0")] diff --git a/tests/ui/traits/non_lifetime_binders/universe-error-host-effect.rs b/tests/ui/traits/non_lifetime_binders/universe-error-host-effect.rs new file mode 100644 index 0000000000000..6d763a86ab271 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/universe-error-host-effect.rs @@ -0,0 +1,28 @@ +//@ compile-flags: -Znext-solver + +#![feature(const_trait_impl, non_lifetime_binders, sized_hierarchy)] +#![allow(incomplete_features)] + +use std::marker::PointeeSized; + +const trait Other: PointeeSized {} + +trait Guard {} + +const impl Other for X {} + +impl Other for X where u8: Guard {} +//~^ ERROR the trait bound `u8: Guard` is not satisfied + +fn foo() +where + for T: const Other, +{ +} + +fn bar() { + foo::<_, _>(); + //~^ ERROR the trait bound `u8: Guard` is not satisfied +} + +fn main() {} diff --git a/tests/ui/traits/non_lifetime_binders/universe-error-host-effect.stderr b/tests/ui/traits/non_lifetime_binders/universe-error-host-effect.stderr new file mode 100644 index 0000000000000..a634c86afa534 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/universe-error-host-effect.stderr @@ -0,0 +1,44 @@ +error[E0277]: the trait bound `u8: Guard` is not satisfied + --> $DIR/universe-error-host-effect.rs:14:50 + | +LL | impl Other for X where u8: Guard {} + | ^^^^^^^^^ the trait `Guard` is not implemented for `u8` + | +help: this trait has no implementations, consider adding one + --> $DIR/universe-error-host-effect.rs:10:1 + | +LL | trait Guard {} + | ^^^^^^^^^^^ +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | +LL + #![feature(trivial_bounds)] + | + +error[E0277]: the trait bound `u8: Guard` is not satisfied + --> $DIR/universe-error-host-effect.rs:24:11 + | +LL | foo::<_, _>(); + | ^ the trait `Guard` is not implemented for `u8` + | +help: this trait has no implementations, consider adding one + --> $DIR/universe-error-host-effect.rs:10:1 + | +LL | trait Guard {} + | ^^^^^^^^^^^ +note: required for `T` to implement `Other` + --> $DIR/universe-error-host-effect.rs:14:23 + | +LL | impl Other for X where u8: Guard {} + | ^^^^^^^^^^^^^^ ^ ----- unsatisfied trait bound introduced here +note: required by a bound in `foo` + --> $DIR/universe-error-host-effect.rs:19:15 + | +LL | fn foo() + | --- required by a bound in this function +LL | where +LL | for T: const Other, + | ^^^^^^^^^^^^^^^^^ required by this bound in `foo` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/non_lifetime_binders/universe-error1.stderr b/tests/ui/traits/non_lifetime_binders/universe-error1.current.stderr similarity index 87% rename from tests/ui/traits/non_lifetime_binders/universe-error1.stderr rename to tests/ui/traits/non_lifetime_binders/universe-error1.current.stderr index 899378b2bce4e..1ef4cc1034bc3 100644 --- a/tests/ui/traits/non_lifetime_binders/universe-error1.stderr +++ b/tests/ui/traits/non_lifetime_binders/universe-error1.current.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `T: Other<_>` is not satisfied - --> $DIR/universe-error1.rs:16:11 + --> $DIR/universe-error1.rs:20:11 | LL | foo::<_>(); | ^ the trait `Other<_>` is not implemented for `T` | note: required by a bound in `foo` - --> $DIR/universe-error1.rs:13:15 + --> $DIR/universe-error1.rs:17:15 | LL | fn foo() | --- required by a bound in this function diff --git a/tests/ui/traits/non_lifetime_binders/universe-error1.next.stderr b/tests/ui/traits/non_lifetime_binders/universe-error1.next.stderr new file mode 100644 index 0000000000000..1ef4cc1034bc3 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/universe-error1.next.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `T: Other<_>` is not satisfied + --> $DIR/universe-error1.rs:20:11 + | +LL | foo::<_>(); + | ^ the trait `Other<_>` is not implemented for `T` + | +note: required by a bound in `foo` + --> $DIR/universe-error1.rs:17:15 + | +LL | fn foo() + | --- required by a bound in this function +LL | where +LL | for T: Other {} + | ^^^^^^^^ required by this bound in `foo` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/non_lifetime_binders/universe-error1.rs b/tests/ui/traits/non_lifetime_binders/universe-error1.rs index 1c99794b6a641..b6c954cf56f47 100644 --- a/tests/ui/traits/non_lifetime_binders/universe-error1.rs +++ b/tests/ui/traits/non_lifetime_binders/universe-error1.rs @@ -1,3 +1,7 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + #![feature(sized_hierarchy)] #![feature(non_lifetime_binders)] diff --git a/tests/ui/traits/object/rerun-impossible-predicates-post-analysis.rs b/tests/ui/traits/object/rerun-impossible-predicates-post-analysis.rs new file mode 100644 index 0000000000000..232557c4a8a9d --- /dev/null +++ b/tests/ui/traits/object/rerun-impossible-predicates-post-analysis.rs @@ -0,0 +1,43 @@ +//@ run-pass + +// Regression test for #161441. This is a next-solver bug fixed by #158993 +// which affected stable due to `impossible_predicates` already using the next-solver +// by default. + +use std::marker::PhantomData; + +struct MyError; + +trait StreamingBody { + type BodyError; +} +struct Body; +impl StreamingBody for Body { + type BodyError = MyError; +} + +trait Service { + type Output; +} +struct HttpClientService; +impl Service for HttpClientService { + type Output = Body; +} + +trait Trait { + fn method(&self); +} +impl Trait for (F, PhantomData) +where + F: Fn() -> R, + HttpClientService: Service, + ResBody: StreamingBody, +{ + fn method(&self) {} +} + +fn inspect_websocket_message() -> impl Sized {} + +fn main() { + (&(inspect_websocket_message, PhantomData) as &dyn Trait).method(); +}