diff --git a/Cargo.lock b/Cargo.lock index 4648a12da487b..2f4d5f7f786ed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -174,9 +174,9 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "askama" -version = "0.15.4" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08e1676b346cadfec169374f949d7490fd80a24193d37d2afce0c047cf695e57" +checksum = "f1bf825125edd887a019d0a3a837dcc5499a68b0d034cc3eb594070c3e18addc" dependencies = [ "askama_macros", "itoa", @@ -187,12 +187,13 @@ dependencies = [ [[package]] name = "askama_derive" -version = "0.15.4" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7661ff56517787343f376f75db037426facd7c8d3049cef8911f1e75016f3a37" +checksum = "e1c7065972a130eafa84215f21352ae15b4a7393da48c1f5e103904490736738" dependencies = [ "askama_parser", "basic-toml", + "glob", "memchr", "proc-macro2", "quote", @@ -204,24 +205,24 @@ dependencies = [ [[package]] name = "askama_macros" -version = "0.15.4" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713ee4dbfd1eb719c2dab859465b01fa1d21cb566684614a713a6b7a99a4e47b" +checksum = "0e23b1d2c4bd39a41971f6124cef4cc6fd0540913ecb90919b69ab3bbe44ae1a" dependencies = [ "askama_derive", ] [[package]] name = "askama_parser" -version = "0.15.4" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d62d674238a526418b30c0def480d5beadb9d8964e7f38d635b03bf639c704c" +checksum = "7db09fde9143e7ac4513358fb32ee32847125b63b18ea715afd487956da715da" dependencies = [ "rustc-hash 2.1.1", "serde", "serde_derive", "unicode-ident", - "winnow 0.7.13", + "winnow 1.0.0", ] [[package]] @@ -756,7 +757,7 @@ checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681" dependencies = [ "serde", "termcolor", - "unicode-width 0.1.14", + "unicode-width 0.2.2", ] [[package]] @@ -6625,6 +6626,9 @@ name = "winnow" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a90e88e4667264a994d34e6d1ab2d26d398dcdca8b7f52bec8668957517fc7d8" +dependencies = [ + "memchr", +] [[package]] name = "winsplit" diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index bf574cf463cc0..7f1b58dd1de08 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -423,10 +423,6 @@ pub trait MacResult { None } - fn make_method_receiver_expr(self: Box) -> Option> { - self.make_expr() - } - /// Creates zero or more items. fn make_items(self: Box) -> Option; 1]>> { None diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index b6611e7e0ca0c..741c34e0304af 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -68,6 +68,7 @@ macro_rules! ast_fragments { /// Can also serve as an input and intermediate result for macro expansion operations. pub enum AstFragment { OptExpr(Option>), + MethodReceiverExpr(Box), $($Kind($AstTy),)* } @@ -75,6 +76,7 @@ macro_rules! ast_fragments { #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum AstFragmentKind { OptExpr, + MethodReceiverExpr, $($Kind,)* } @@ -82,6 +84,7 @@ macro_rules! ast_fragments { pub fn name(self) -> &'static str { match self { AstFragmentKind::OptExpr => "expression", + AstFragmentKind::MethodReceiverExpr => "expression", $(AstFragmentKind::$Kind => $kind_name,)* } } @@ -90,6 +93,8 @@ macro_rules! ast_fragments { match self { AstFragmentKind::OptExpr => result.make_expr().map(Some).map(AstFragment::OptExpr), + AstFragmentKind::MethodReceiverExpr => + result.make_expr().map(AstFragment::MethodReceiverExpr), $(AstFragmentKind::$Kind => result.$make_ast().map(AstFragment::$Kind),)* } } @@ -116,6 +121,13 @@ macro_rules! ast_fragments { } } + pub(crate) fn make_method_receiver_expr(self) -> Box { + match self { + AstFragment::MethodReceiverExpr(expr) => expr, + _ => panic!("AstFragment::make_method_receiver_expr called on the wrong kind of fragment"), + } + } + $(pub fn $make_ast(self) -> $AstTy { match self { AstFragment::$Kind(ast) => ast, @@ -134,6 +146,7 @@ macro_rules! ast_fragments { *opt_expr = vis.filter_map_expr(expr) } } + AstFragment::MethodReceiverExpr(expr) => vis.visit_method_receiver_expr(expr), $($(AstFragment::$Kind(ast) => vis.$visit_ast(ast),)?)* $($(AstFragment::$Kind(ast) => ast.flat_map_in_place(|ast| vis.$flat_map_ast_elt(ast, $($args)*)),)?)* @@ -144,6 +157,7 @@ macro_rules! ast_fragments { match self { AstFragment::OptExpr(Some(expr)) => try_visit!(visitor.visit_expr(expr)), AstFragment::OptExpr(None) => {} + AstFragment::MethodReceiverExpr(expr) => try_visit!(visitor.visit_method_receiver_expr(expr)), $($(AstFragment::$Kind(ast) => try_visit!(visitor.$visit_ast(ast)),)?)* $($(AstFragment::$Kind(ast) => walk_list!(visitor, $visit_ast_elt, &ast[..], $($args)*),)?)* } @@ -166,11 +180,6 @@ ast_fragments! { one fn visit_expr; fn make_expr; } - MethodReceiverExpr(Box) { - "expression"; - one fn visit_method_receiver_expr; - fn make_method_receiver_expr; - } Pat(Box) { "pattern"; one fn visit_pat; diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index 74da4d4c6db8b..0dc1f5e5eec58 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -22,6 +22,10 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { self.next_trait_solver } + fn disable_trait_solver_fast_paths(&self) -> bool { + self.disable_trait_solver_fast_paths() + } + fn typing_mode(&self) -> ty::TypingMode<'tcx> { self.typing_mode() } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 05043f8617a92..104a4e4d1ec4b 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -640,6 +640,11 @@ impl<'tcx> InferCtxt<'tcx> { self.next_trait_solver } + #[inline(always)] + pub fn disable_trait_solver_fast_paths(&self) -> bool { + self.tcx.disable_trait_solver_fast_paths() + } + #[inline(always)] pub fn typing_mode(&self) -> TypingMode<'tcx> { self.typing_mode diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index c25f5b402eb0d..2d7cefd137d91 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2657,6 +2657,10 @@ impl<'tcx> TyCtxt<'tcx> { self.sess.opts.unstable_opts.next_solver.coherence } + pub fn disable_trait_solver_fast_paths(self) -> bool { + self.sess.opts.unstable_opts.disable_fast_paths + } + #[allow(rustc::bad_opt_access)] pub fn use_typing_mode_borrowck(self) -> bool { self.next_trait_solver_globally() || self.sess.opts.unstable_opts.typing_mode_borrowck diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 615cc9e8f81d2..b9e1758be0fd4 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -447,6 +447,7 @@ where ref sub_roots, stalled_certainty, }) = stalled_on + && !self.delegate.disable_trait_solver_fast_paths() && !stalled_vars.iter().any(|value| self.delegate.is_changed_arg(*value)) && !sub_roots .iter() @@ -666,7 +667,10 @@ where // If this loop did not result in any progress, what's our final certainty. let mut unchanged_certainty = Some(Certainty::Yes); for (source, goal, stalled_on) in mem::take(&mut self.nested_goals) { - if let Some(certainty) = self.delegate.compute_goal_fast_path(goal, self.origin_span) { + if !self.delegate.disable_trait_solver_fast_paths() + && let Some(certainty) = + self.delegate.compute_goal_fast_path(goal, self.origin_span) + { match certainty { Certainty::Yes => {} Certainty::Maybe { .. } => { diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index e41df43e34bd3..420e74b130598 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -54,10 +54,11 @@ fn inherit_const_stability(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { match def_kind { DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst { .. } => { match tcx.def_kind(tcx.local_parent(def_id)) { - DefKind::Impl { .. } => true, + DefKind::Trait | DefKind::Impl { .. } => true, _ => false, } } + DefKind::Closure => true, _ => false, } } diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 360c14afa8ba6..e63ab9f21a6ad 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -9,7 +9,9 @@ use rustc_attr_parsing::AttributeParser; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_data_structures::intern::Interned; use rustc_errors::codes::*; -use rustc_errors::{Applicability, Diagnostic, MultiSpan, pluralize, struct_span_code_err}; +use rustc_errors::{ + Applicability, BufferedEarlyLint, Diagnostic, MultiSpan, pluralize, struct_span_code_err, +}; use rustc_hir::Attribute; use rustc_hir::attrs::AttributeKind; use rustc_hir::attrs::diagnostic::{CustomDiagnostic, Directive, FormatArgs}; @@ -19,6 +21,7 @@ use rustc_middle::metadata::{AmbigModChild, ModChild, Reexport}; use rustc_middle::span_bug; use rustc_middle::ty::{TyCtxt, Visibility}; use rustc_session::errors::feature_err; +use rustc_session::lint::LintId; use rustc_session::lint::builtin::{ AMBIGUOUS_GLOB_REEXPORTS, EXPORTED_PRIVATE_DEPENDENCIES, HIDDEN_GLOB_REEXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE, REDUNDANT_IMPORTS, UNUSED_IMPORTS, @@ -273,6 +276,8 @@ impl<'ra> ImportData<'ra> { vis: self.vis, nearest_parent_mod: self.parent_scope.module.nearest_parent_mod().expect_local(), is_single: matches!(self.kind, ImportKind::Single { .. }), + priv_macro_use: matches!(self.kind, ImportKind::MacroUse { warn_private: true }), + span: self.span, } } } @@ -381,9 +386,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ) -> Visibility { assert!(import.vis.is_accessible_from(import.nearest_parent_mod, self.tcx)); let decl_vis = if min { decl.min_vis() } else { decl.vis() }; - if decl_vis.partial_cmp(import.vis, self.tcx) == Some(Ordering::Less) + let ord = decl_vis.partial_cmp(import.vis, self.tcx); + let extern_crate_hack = pub_use_of_private_extern_crate_hack(import, decl).is_some(); + if ord == Some(Ordering::Less) && decl_vis.is_accessible_from(import.nearest_parent_mod, self.tcx) - && pub_use_of_private_extern_crate_hack(import, decl).is_none() + && !extern_crate_hack { // Imported declaration is less visible than the import, but is still visible // from the current module, use the declaration's visibility. @@ -391,12 +398,19 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } else { // Good case - imported declaration is more visible than the import, or the same, // use the import's visibility. + // // Bad case - imported declaration is too private for the current module. // It doesn't matter what visibility we choose here (except in the `PRIVATE_MACRO_USE` - // and `PUB_USE_OF_PRIVATE_EXTERN_CRATE` cases), because either some error will be - // reported, or the import declaration will be thrown away (unfortunately cannot use - // delayed bug here for this reason). + // and `PUB_USE_OF_PRIVATE_EXTERN_CRATE` cases), because an error will be reported. // Use import visibility to keep the all declaration visibilities in a module ordered. + if !min + && matches!(ord, None | Some(Ordering::Less)) + && !extern_crate_hack + && !import.priv_macro_use + { + let msg = format!("cannot extend visibility from {decl_vis:?} to {:?}", import.vis); + self.dcx().span_delayed_bug(import.span, msg); + } import.vis } } @@ -784,6 +798,29 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let resolution = resolution.borrow(); let Some(binding) = resolution.best_decl() else { continue }; + // Report "cannot reexport" errors for exotic cases involving macros 2.0 + // privacy bending or invariant-breaking code under deprecation lints. + for decl in [resolution.non_glob_decl, resolution.glob_decl] { + if let Some(decl) = decl + && let DeclKind::Import { source_decl, import } = decl.kind + { + // The source entity is too private to be reexported + // with the given import declaration's visibility. + let ord = source_decl.vis().partial_cmp(decl.vis(), self.tcx); + if matches!(ord, None | Some(Ordering::Less)) { + let ident = match import.kind { + ImportKind::Single { source, .. } => source, + _ => key.ident.orig(resolution.orig_ident_span), + }; + if let Some(lint) = + self.report_cannot_reexport(import, source_decl, ident, key.ns) + { + self.lint_buffer.add_early_lint(lint); + } + } + } + } + if let DeclKind::Import { import, .. } = binding.kind && let Some(amb_binding) = binding.ambiguity.get() && binding.res() != Res::Err @@ -1515,76 +1552,25 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let mut reexport_error = None; let mut any_successful_reexport = false; - let mut crate_private_reexport = false; self.per_ns(|this, ns| { - let Some(binding) = bindings[ns].get().decl().map(|b| b.import_source()) else { + let Some(binding) = bindings[ns].get().decl() else { return; }; if import.vis.greater_than(binding.vis(), this.tcx) { - reexport_error = Some((ns, binding)); - if let Visibility::Restricted(binding_def_id) = binding.vis() - && binding_def_id.is_top_level_module() - { - crate_private_reexport = true; - } + // In isolation, a declaration like this is not an error, but if *all* 1-3 + // declarations introduced by the import are more private than the import item's + // nominal visibility, then it's an error. + reexport_error = Some((ns, binding.import_source())); } else { any_successful_reexport = true; } }); - // All namespaces must be re-exported with extra visibility for an error to occur. if !any_successful_reexport { let (ns, binding) = reexport_error.unwrap(); - if let Some(extern_crate_id) = - pub_use_of_private_extern_crate_hack(import.summary(), binding) - { - let extern_crate_sp = self.tcx.source_span(self.local_def_id(extern_crate_id)); - self.lint_buffer.buffer_lint( - PUB_USE_OF_PRIVATE_EXTERN_CRATE, - import_id, - import.span, - crate::errors::PrivateExternCrateReexport { - ident, - sugg: extern_crate_sp.shrink_to_lo(), - }, - ); - } else if ns == TypeNS { - let err = if crate_private_reexport { - self.dcx() - .create_err(CannotBeReexportedCratePublicNS { span: import.span, ident }) - } else { - self.dcx().create_err(CannotBeReexportedPrivateNS { span: import.span, ident }) - }; - err.emit(); - } else { - let mut err = if crate_private_reexport { - self.dcx() - .create_err(CannotBeReexportedCratePublic { span: import.span, ident }) - } else { - self.dcx().create_err(CannotBeReexportedPrivate { span: import.span, ident }) - }; - - match binding.kind { - DeclKind::Def(Res::Def(DefKind::Macro(_), def_id)) - // exclude decl_macro - if self.get_macro_by_def_id(def_id).macro_rules => - { - err.subdiagnostic( ConsiderAddingMacroExport { - span: binding.span, - }); - err.subdiagnostic( ConsiderMarkingAsPubCrate { - vis_span: import.vis_span, - }); - } - _ => { - err.subdiagnostic( ConsiderMarkingAsPub { - span: import.span, - ident, - }); - } - } - err.emit(); + if let Some(lint) = self.report_cannot_reexport(import, binding, ident, ns) { + self.lint_buffer.add_early_lint(lint); } } @@ -1613,6 +1599,61 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { None } + fn report_cannot_reexport( + &self, + import: Import<'ra>, + decl: Decl<'ra>, + ident: Ident, + ns: Namespace, + ) -> Option { + let crate_private_reexport = match decl.vis() { + Visibility::Restricted(def_id) if def_id.is_top_level_module() => true, + _ => false, + }; + + if let Some(extern_crate_id) = pub_use_of_private_extern_crate_hack(import.summary(), decl) + { + let ImportKind::Single { id, .. } = import.kind else { unreachable!() }; + let sugg = self.tcx.source_span(self.local_def_id(extern_crate_id)).shrink_to_lo(); + let diagnostic = crate::errors::PrivateExternCrateReexport { ident, sugg }; + return Some(BufferedEarlyLint { + lint_id: LintId::of(PUB_USE_OF_PRIVATE_EXTERN_CRATE), + node_id: id, + span: Some(import.span.into()), + diagnostic: diagnostic.into(), + }); + } else if ns == TypeNS { + let err = if crate_private_reexport { + self.dcx().create_err(CannotBeReexportedCratePublicNS { span: import.span, ident }) + } else { + self.dcx().create_err(CannotBeReexportedPrivateNS { span: import.span, ident }) + }; + err.emit(); + } else { + let mut err = if crate_private_reexport { + self.dcx().create_err(CannotBeReexportedCratePublic { span: import.span, ident }) + } else { + self.dcx().create_err(CannotBeReexportedPrivate { span: import.span, ident }) + }; + + match decl.kind { + // exclude decl_macro + DeclKind::Def(Res::Def(DefKind::Macro(_), def_id)) + if self.get_macro_by_def_id(def_id).macro_rules => + { + err.subdiagnostic(ConsiderAddingMacroExport { span: decl.span }); + err.subdiagnostic(ConsiderMarkingAsPubCrate { vis_span: import.vis_span }); + } + _ => { + err.subdiagnostic(ConsiderMarkingAsPub { span: import.span, ident }); + } + } + err.emit(); + } + + None + } + pub(crate) fn check_for_redundant_imports(&mut self, import: Import<'ra>) -> bool { // This function is only called for single imports. let ImportKind::Single { source, target, ref decls, id, .. } = import.kind else { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index f5f063ecaf458..1141ac75ce4c0 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -2750,6 +2750,8 @@ struct ImportSummary { vis: Visibility, nearest_parent_mod: LocalDefId, is_single: bool, + priv_macro_use: bool, + span: Span, } /// Invariant: if `Finalize` is used, expansion and import resolution must be complete. diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index f7a3387e5238a..4767b0cfbe868 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2269,6 +2269,8 @@ options! { themselves (default: no)"), direct_access_external_data: Option = (None, parse_opt_bool, [TRACKED], "Direct or use GOT indirect to reference external data symbols"), + disable_fast_paths: bool = (false, parse_bool, [TRACKED], + "disable various performance optimizations in trait solving"), dual_proc_macros: bool = (false, parse_bool, [TRACKED], "load proc macros for both target and host, but only link to the target (default: no)"), dump_dep_graph: bool = (false, parse_bool, [UNTRACKED], diff --git a/compiler/rustc_thread_pool/src/sleep/mod.rs b/compiler/rustc_thread_pool/src/sleep/mod.rs index aa6666092147a..cbaead52902dc 100644 --- a/compiler/rustc_thread_pool/src/sleep/mod.rs +++ b/compiler/rustc_thread_pool/src/sleep/mod.rs @@ -106,7 +106,6 @@ impl Sleep { let mut data = self.data.lock().unwrap(); debug_assert!(data.active_threads > 0); debug_assert!(data.blocked_threads < data.worker_count); - debug_assert!(data.active_threads > 0); data.active_threads -= 1; data.blocked_threads += 1; diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index 21951cee6d5ab..887b0804c2296 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -779,29 +779,40 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let (lt1, sig1) = get_lifetimes(sig1); let (lt2, sig2) = get_lifetimes(sig2); - // unsafe extern "C" for<'a> fn(&'a T) -> &'a T + // #[target_features] for<'a> unsafe extern "C" fn(&'a T) -> &'a T let mut values = (DiagStyledString::normal("".to_string()), DiagStyledString::normal("".to_string())); - // unsafe extern "C" for<'a> fn(&'a T) -> &'a T - // ^^^^^^ - let safety = |fn_def, sig: ty::FnSig<'_>| match fn_def { - None => sig.safety().prefix_str(), + // #[target_features] for<'a> unsafe extern "C" fn(&'a T) -> &'a T + // ^^^^^^^^^^^^^^^^^^ + let fn_item_prefix_and_safety = |fn_def, sig: ty::FnSig<'_>| match fn_def { + None => ("", sig.safety().prefix_str()), Some((did, _)) => { if self.tcx.codegen_fn_attrs(did).safe_target_features { - "#[target_features] " + ("#[target_features] ", "") } else { - sig.safety().prefix_str() + ("", sig.safety().prefix_str()) } } }; - let safety1 = safety(fn_def1, sig1); - let safety2 = safety(fn_def2, sig2); + let (prefix1, safety1) = fn_item_prefix_and_safety(fn_def1, sig1); + let (prefix2, safety2) = fn_item_prefix_and_safety(fn_def2, sig2); + values.0.push(prefix1, prefix1 != prefix2); + values.1.push(prefix2, prefix1 != prefix2); + + // #[target_features] for<'a> unsafe extern "C" fn(&'a T) -> &'a T + // ^^^^^^^^ + let lifetime_diff = lt1 != lt2; + values.0.push(lt1, lifetime_diff); + values.1.push(lt2, lifetime_diff); + + // #[target_features] for<'a> unsafe extern "C" fn(&'a T) -> &'a T + // ^^^^^^ values.0.push(safety1, safety1 != safety2); values.1.push(safety2, safety1 != safety2); - // unsafe extern "C" for<'a> fn(&'a T) -> &'a T - // ^^^^^^^^^^ + // #[target_features] for<'a> unsafe extern "C" fn(&'a T) -> &'a T + // ^^^^^^^^^^ if sig1.abi() != ExternAbi::Rust { values.0.push(format!("extern {} ", sig1.abi()), sig1.abi() != sig2.abi()); } @@ -809,19 +820,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { values.1.push(format!("extern {} ", sig2.abi()), sig1.abi() != sig2.abi()); } - // unsafe extern "C" for<'a> fn(&'a T) -> &'a T - // ^^^^^^^^ - let lifetime_diff = lt1 != lt2; - values.0.push(lt1, lifetime_diff); - values.1.push(lt2, lifetime_diff); - - // unsafe extern "C" for<'a> fn(&'a T) -> &'a T - // ^^^ + // #[target_features] for<'a> unsafe extern "C" fn(&'a T) -> &'a T + // ^^^ values.0.push_normal("fn("); values.1.push_normal("fn("); - // unsafe extern "C" for<'a> fn(&'a T) -> &'a T - // ^^^^^ + // #[target_features] for<'a> unsafe extern "C" fn(&'a T) -> &'a T + // ^^^^^ let len1 = sig1.inputs().len(); let len2 = sig2.inputs().len(); if len1 == len2 { @@ -859,13 +864,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { values.1.push("...", !sig1.c_variadic()); } - // unsafe extern "C" for<'a> fn(&'a T) -> &'a T - // ^ + // #[target_features] for<'a> unsafe extern "C" fn(&'a T) -> &'a T + // ^ values.0.push_normal(")"); values.1.push_normal(")"); - // unsafe extern "C" for<'a> fn(&'a T) -> &'a T - // ^^^^^^^^ + // #[target_features] for<'a> unsafe extern "C" fn(&'a T) -> &'a T + // ^^^^^^^^ let output1 = sig1.output(); let output2 = sig2.output(); let (x1, x2) = self.cmp(output1, output2); diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 8848b4c40f510..d8b9c400b4d7d 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -186,8 +186,9 @@ where let goal = obligation.as_goal(); let delegate = <&SolverDelegate<'tcx>>::from(infcx); - if let Some(certainty) = - delegate.compute_goal_fast_path(goal, obligation.cause.span) + if !delegate.disable_trait_solver_fast_paths() + && let Some(certainty) = + delegate.compute_goal_fast_path(goal, obligation.cause.span) { match certainty { // This fast path doesn't depend on region identity so it doesn't diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 0b1d4a8453d05..b4b54cd16bd5f 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -325,6 +325,10 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { /// compile-time benchmarks are very sensitive to even small changes. #[inline(always)] fn needs_process_obligation(&self, pending_obligation: &Self::Obligation) -> bool { + if self.selcx.infcx.disable_trait_solver_fast_paths() { + return true; + } + // If we were stalled on some unresolved variables, first check whether // any of them have been resolved; if not, don't bother doing more work // yet. @@ -388,7 +392,9 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { let infcx = self.selcx.infcx; - if sizedness_fast_path(infcx.tcx, obligation.predicate, obligation.param_env) { + if !infcx.disable_trait_solver_fast_paths() + && sizedness_fast_path(infcx.tcx, obligation.predicate, obligation.param_env) + { return ProcessResult::Changed(thin_vec![]); } diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs index b2c1f9a5eed14..3a8a3fc66e663 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs @@ -110,7 +110,9 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable> + 't ), NoSolution, > { - if let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &query_key) { + if !infcx.disable_trait_solver_fast_paths() + && let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &query_key) + { return Ok((result, None, PredicateObligations::new(), Certainty::Proven)); } @@ -159,7 +161,9 @@ where "query type op", span, |ocx| { - if let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &self) { + if !infcx.disable_trait_solver_fast_paths() + && let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &self) + { return Ok(result); } QueryTypeOp::perform_locally_with_next_solver(ocx, self, span) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 9eca0f31a4402..3a8e2429069f5 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -604,7 +604,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { None => self.check_recursion_limit(&obligation, &obligation)?, } - if sizedness_fast_path(self.tcx(), obligation.predicate, obligation.param_env) { + if !self.infcx.disable_trait_solver_fast_paths() + && sizedness_fast_path(self.tcx(), obligation.predicate, obligation.param_env) + { return Ok(EvaluatedToOk); } diff --git a/compiler/rustc_traits/src/evaluate_obligation.rs b/compiler/rustc_traits/src/evaluate_obligation.rs index 8f72bdf097261..6bc6543a0a01b 100644 --- a/compiler/rustc_traits/src/evaluate_obligation.rs +++ b/compiler/rustc_traits/src/evaluate_obligation.rs @@ -24,7 +24,7 @@ fn evaluate_obligation<'tcx>( debug!("evaluate_obligation: goal={:#?}", goal); let ParamEnvAnd { param_env, value: predicate } = goal; - if sizedness_fast_path(tcx, predicate, param_env) { + if !tcx.disable_trait_solver_fast_paths() && sizedness_fast_path(tcx, predicate, param_env) { return Ok(EvaluationResult::EvaluatedToOk); } diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index 1b6bdf8c34dd8..99588cb20aed0 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -230,6 +230,8 @@ pub trait InferCtxtLike: Sized { true } + fn disable_trait_solver_fast_paths(&self) -> bool; + fn typing_mode(&self) -> TypingMode; fn universe(&self) -> ty::UniverseIndex; diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index d85a63999fe03..7b41023ff31bf 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -108,6 +108,7 @@ #![feature(const_heap)] #![feature(const_index)] #![feature(const_option_ops)] +#![feature(const_result_trait_fn)] #![feature(const_try)] #![feature(copied_into_inner)] #![feature(core_intrinsics)] @@ -173,6 +174,7 @@ #![feature(allocator_internals)] #![feature(allow_internal_unstable)] #![feature(cfg_sanitize)] +#![feature(const_closures)] #![feature(const_precise_live_drops)] #![feature(const_trait_impl)] #![feature(coroutine_trait)] diff --git a/library/alloc/src/raw_vec/mod.rs b/library/alloc/src/raw_vec/mod.rs index cabf6accf3b53..0309d63cce06d 100644 --- a/library/alloc/src/raw_vec/mod.rs +++ b/library/alloc/src/raw_vec/mod.rs @@ -898,9 +898,5 @@ const fn layout_array(cap: usize, elem_layout: Layout) -> Result Ok(layout), - Err(_) => Err(CapacityOverflow.into()), - } + elem_layout.repeat_packed(cap).map_err(const |_| CapacityOverflow.into()) } diff --git a/library/alloctests/lib.rs b/library/alloctests/lib.rs index e09d8495fdeac..936d60fdad73b 100644 --- a/library/alloctests/lib.rs +++ b/library/alloctests/lib.rs @@ -23,6 +23,7 @@ #![feature(const_destruct)] #![feature(const_heap)] #![feature(const_option_ops)] +#![feature(const_result_trait_fn)] #![feature(const_try)] #![feature(copied_into_inner)] #![feature(core_intrinsics)] @@ -54,6 +55,7 @@ // // Language features: // tidy-alphabetical-start +#![feature(const_closures)] #![feature(const_trait_impl)] #![feature(dropck_eyepatch)] #![feature(min_specialization)] diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index c6a06c133a156..6dc748c568fcd 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -226,13 +226,11 @@ pub const trait Iterator { Self: Sized + [const] Destruct, Self::Item: [const] Destruct, { - // FIXME(const-hack): revert this to a const closure - #[rustc_const_unstable(feature = "const_iter", issue = "92476")] - #[rustc_inherit_overflow_checks] - const fn plus_one(accum: usize, _elem: T) -> usize { - accum + 1 - } - self.fold(0, plus_one) + self.fold( + 0, + #[rustc_inherit_overflow_checks] + const |accum, _elem| accum + 1, + ) } /// Consumes the iterator, returning the last element. diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 3451b2976bb73..57ce51bb8c0ed 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -125,6 +125,7 @@ #![feature(cfg_target_has_atomic)] #![feature(cfg_target_has_atomic_equal_alignment)] #![feature(cfg_ub_checks)] +#![feature(const_closures)] #![feature(const_precise_live_drops)] #![feature(const_trait_impl)] #![feature(decl_macro)] diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs index 9521213e1bc7e..aaa71786854da 100644 --- a/library/core/src/ops/try_trait.rs +++ b/library/core/src/ops/try_trait.rs @@ -1,4 +1,4 @@ -use crate::marker::{Destruct, PhantomData}; +use crate::marker::Destruct; use crate::ops::ControlFlow; /// The `?` operator and `try {}` blocks. @@ -398,25 +398,6 @@ pub(crate) type ChangeOutputType>, V> = /// Not currently planned to be exposed publicly, so just `pub(crate)`. #[repr(transparent)] pub(crate) struct NeverShortCircuit(pub T); -// FIXME(const-hack): replace with `|a| NeverShortCircuit(f(a))` when const closures added. -pub(crate) struct Wrapped T> { - f: F, - p: PhantomData<(T, A)>, -} -#[rustc_const_unstable(feature = "const_never_short_circuit", issue = "none")] -impl T + [const] Destruct> const FnOnce<(A,)> for Wrapped { - type Output = NeverShortCircuit; - - extern "rust-call" fn call_once(mut self, args: (A,)) -> Self::Output { - self.call_mut(args) - } -} -#[rustc_const_unstable(feature = "const_never_short_circuit", issue = "none")] -impl T> const FnMut<(A,)> for Wrapped { - extern "rust-call" fn call_mut(&mut self, (args,): (A,)) -> Self::Output { - NeverShortCircuit((self.f)(args)) - } -} impl NeverShortCircuit { /// Wraps a unary function to produce one that wraps the output into a `NeverShortCircuit`. @@ -424,11 +405,14 @@ impl NeverShortCircuit { /// This is useful for implementing infallible functions in terms of the `try_` ones, /// without accidentally capturing extra generic parameters in a closure. #[inline] - pub(crate) const fn wrap_mut_1(f: F) -> Wrapped + #[rustc_const_unstable(feature = "const_array", issue = "147606")] + pub(crate) const fn wrap_mut_1( + mut f: F, + ) -> impl [const] FnMut(A) -> Self + [const] Destruct where - F: [const] FnMut(A) -> T, + F: [const] FnMut(A) -> T + [const] Destruct, { - Wrapped { f, p: PhantomData } + const move |a| NeverShortCircuit(f(a)) } #[inline] diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs index 69a01eef88f97..6a10fc22c2e2c 100644 --- a/library/core/src/slice/cmp.rs +++ b/library/core/src/slice/cmp.rs @@ -3,7 +3,6 @@ use super::{from_raw_parts, memchr}; use crate::ascii; use crate::cmp::{self, BytewiseEq, Ordering}; -use crate::convert::Infallible; use crate::intrinsics::compare_bytes; use crate::marker::Destruct; use crate::mem::SizedTypeProperties; @@ -182,20 +181,12 @@ type AlwaysBreak = ControlFlow; #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] impl const SlicePartialOrd for A { default fn partial_compare(left: &[A], right: &[A]) -> Option { - // FIXME(const-hack): revert this to a const closure once possible - #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] - const fn elem_chain(a: &A, b: &A) -> ControlFlow> { - match PartialOrd::partial_cmp(a, b) { - Some(Ordering::Equal) => ControlFlow::Continue(()), - non_eq => ControlFlow::Break(non_eq), - } - } + let elem_chain = const |a, b| match PartialOrd::partial_cmp(a, b) { + Some(Ordering::Equal) => ControlFlow::Continue(()), + non_eq => ControlFlow::Break(non_eq), + }; - // FIXME(const-hack): revert this to a const closure once possible - #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] - const fn len_chain(a: &usize, b: &usize) -> ControlFlow, Infallible> { - ControlFlow::Break(usize::partial_cmp(a, b)) - } + let len_chain = const |a: &_, b: &_| ControlFlow::Break(usize::partial_cmp(a, b)); let AlwaysBreak::Break(b) = chaining_impl(left, right, elem_chain, len_chain); b @@ -293,20 +284,12 @@ const trait SliceOrd: Sized { #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] impl const SliceOrd for A { default fn compare(left: &[Self], right: &[Self]) -> Ordering { - // FIXME(const-hack): revert this to a const closure once possible - #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] - const fn elem_chain(a: &A, b: &A) -> ControlFlow { - match Ord::cmp(a, b) { - Ordering::Equal => ControlFlow::Continue(()), - non_eq => ControlFlow::Break(non_eq), - } - } + let elem_chain = const |a, b| match Ord::cmp(a, b) { + Ordering::Equal => ControlFlow::Continue(()), + non_eq => ControlFlow::Break(non_eq), + }; - // FIXME(const-hack): revert this to a const closure once possible - #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] - const fn len_chain(a: &usize, b: &usize) -> ControlFlow { - ControlFlow::Break(usize::cmp(a, b)) - } + let len_chain = const |a: &_, b: &_| ControlFlow::Break(usize::cmp(a, b)); let AlwaysBreak::Break(b) = chaining_impl(left, right, elem_chain, len_chain); b diff --git a/src/bootstrap/src/utils/proc_macro_deps.rs b/src/bootstrap/src/utils/proc_macro_deps.rs index fee9b12aca069..94f8243ae1f68 100644 --- a/src/bootstrap/src/utils/proc_macro_deps.rs +++ b/src/bootstrap/src/utils/proc_macro_deps.rs @@ -22,6 +22,7 @@ pub static CRATES: &[&str] = &[ "fnv", "foldhash", "generic-array", + "glob", "hashbrown", "heck", "ident_case", diff --git a/src/ci/citool/Cargo.toml b/src/ci/citool/Cargo.toml index f97d5e807fcc8..4e954f77c081e 100644 --- a/src/ci/citool/Cargo.toml +++ b/src/ci/citool/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] anyhow = "1" -askama = "0.15.4" +askama = "0.16.0" clap = { version = "4.5", features = ["derive"] } csv = "1" diff = "0.1" diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 440d54b007a19..c06b4857e4903 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.15.4", default-features = false, features = ["alloc", "config", "derive"] } +askama = { version = "0.16.0", default-features = false, features = ["alloc", "config", "derive"] } base64 = "0.21.7" indexmap = { version = "2", features = ["serde"] } itertools = "0.12" diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml index 234478eadbf96..a87fdeaf99c5c 100644 --- a/src/tools/clippy/Cargo.toml +++ b/src/tools/clippy/Cargo.toml @@ -42,7 +42,7 @@ walkdir = "2.3" filetime = "0.2.9" itertools = "0.12" pulldown-cmark = { version = "0.11", default-features = false, features = ["html"] } -askama = { version = "0.15.4", default-features = false, features = ["alloc", "config", "derive"] } +askama = { version = "0.16.0", default-features = false, features = ["alloc", "config", "derive"] } [dev-dependencies.toml] version = "0.9.7" diff --git a/src/tools/generate-copyright/Cargo.toml b/src/tools/generate-copyright/Cargo.toml index 17b5c727964fe..91236ff6c6040 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.15.4" +askama = "0.16.0" cargo_metadata = "0.21" serde = { version = "1.0.147", features = ["derive"] } serde_json = "1.0.85" diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs index 9a7fbc812f875..22c9073a581fc 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs @@ -16,6 +16,7 @@ extern crate rustc_parse_format; extern crate ra_ap_rustc_parse_format as rustc_parse_format; extern crate ra_ap_rustc_abi as rustc_abi; +pub extern crate ra_ap_rustc_abi as layout; pub mod db; @@ -47,7 +48,6 @@ pub mod import_map; pub mod visibility; use intern::{Interned, Symbol}; -pub use rustc_abi as layout; use thin_vec::ThinVec; pub use crate::signatures::LocalFieldId; diff --git a/tests/ui/hygiene/privacy-early.rs b/tests/ui/hygiene/privacy-early.rs index 07680a7b9b22d..a279e5cd42651 100644 --- a/tests/ui/hygiene/privacy-early.rs +++ b/tests/ui/hygiene/privacy-early.rs @@ -8,6 +8,7 @@ mod foo { pub macro m() { use f as g; //~ ERROR `f` is private, and cannot be re-exported + //~| ERROR `f` is private, and cannot be re-exported f!(); } } diff --git a/tests/ui/hygiene/privacy-early.stderr b/tests/ui/hygiene/privacy-early.stderr index 1c2f9ff5405f4..556c6e3fe02ca 100644 --- a/tests/ui/hygiene/privacy-early.stderr +++ b/tests/ui/hygiene/privacy-early.stderr @@ -17,6 +17,26 @@ LL | foo::m!(); | --------- in this macro invocation = note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 1 previous error +error[E0364]: `f` is private, and cannot be re-exported + --> $DIR/privacy-early.rs:10:13 + | +LL | use f as g; + | ^^^^^^ +... +LL | foo::m!(); + | --------- in this macro invocation + | +note: consider marking `f` as `pub` in the imported module + --> $DIR/privacy-early.rs:10:13 + | +LL | use f as g; + | ^^^^^^ +... +LL | foo::m!(); + | --------- in this macro invocation + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + = note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0364`. diff --git a/tests/ui/imports/private-from-decl-macro.fail.stderr b/tests/ui/imports/private-from-decl-macro.fail.stderr index e09c193f5e6ba..a4090ef5dcfd1 100644 --- a/tests/ui/imports/private-from-decl-macro.fail.stderr +++ b/tests/ui/imports/private-from-decl-macro.fail.stderr @@ -1,5 +1,24 @@ +error[E0364]: `S` is private, and cannot be re-exported + --> $DIR/private-from-decl-macro.rs:18:13 + | +LL | use crate::m::*; + | ^^^^^^^^^^^ +... +LL | crate::m::mac_glob!(); + | --------------------- in this macro invocation + | +note: consider marking `S` as `pub` in the imported module + --> $DIR/private-from-decl-macro.rs:18:13 + | +LL | use crate::m::*; + | ^^^^^^^^^^^ +... +LL | crate::m::mac_glob!(); + | --------------------- in this macro invocation + = note: this error originates in the macro `crate::m::mac_glob` (in Nightly builds, run with -Z macro-backtrace for more info) + error[E0423]: expected value, found struct `S` - --> $DIR/private-from-decl-macro.rs:27:17 + --> $DIR/private-from-decl-macro.rs:28:17 | LL | pub struct S {} | --------------- `S` defined here @@ -22,6 +41,7 @@ LL - let s = S; LL + let s = s; | -error: aborting due to 1 previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0423`. +Some errors have detailed explanations: E0364, E0423. +For more information about an error, try `rustc --explain E0364`. diff --git a/tests/ui/imports/private-from-decl-macro.rs b/tests/ui/imports/private-from-decl-macro.rs index cdb3bb40ef7b5..ff37665b96862 100644 --- a/tests/ui/imports/private-from-decl-macro.rs +++ b/tests/ui/imports/private-from-decl-macro.rs @@ -14,7 +14,8 @@ mod m { } pub macro mac_glob() { - use crate::m::*; + #[cfg(fail)] + use crate::m::*; //[fail]~ ERROR `S` is private, and cannot be re-exported } } diff --git a/tests/ui/macros/auxiliary/semicolon-in-exprs.rs b/tests/ui/macros/auxiliary/semicolon-in-exprs.rs new file mode 100644 index 0000000000000..87a1c1786c1e4 --- /dev/null +++ b/tests/ui/macros/auxiliary/semicolon-in-exprs.rs @@ -0,0 +1,4 @@ +#[macro_export] +macro_rules! outer { + ($inner:ident) => { $inner![1, 2, 3]; }; +} diff --git a/tests/ui/macros/semicolon-in-exprs.rs b/tests/ui/macros/semicolon-in-exprs.rs new file mode 100644 index 0000000000000..1d6c9d895f067 --- /dev/null +++ b/tests/ui/macros/semicolon-in-exprs.rs @@ -0,0 +1,15 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/156084. +//! This test can probably be removed again once +//! `semicolon_in_expressions_from_macros` is a hard error. +//@ check-pass +//@ aux-build:semicolon-in-exprs.rs +//@ edition: 2021 + +extern crate semicolon_in_exprs; + +macro_rules! inner { + [$($x:expr),*] => { [$($x),*] }; +} +fn main() { + let _v: Vec = semicolon_in_exprs::outer!(inner).into_iter().collect(); +} diff --git a/tests/ui/mismatched_types/fn-pointer-mismatch-diagnostics.rs b/tests/ui/mismatched_types/fn-pointer-mismatch-diagnostics.rs index e28ca3e55b5ed..e32a4792367d5 100644 --- a/tests/ui/mismatched_types/fn-pointer-mismatch-diagnostics.rs +++ b/tests/ui/mismatched_types/fn-pointer-mismatch-diagnostics.rs @@ -10,7 +10,19 @@ fn foo(x: i32) -> u32 { 0 } +extern "C" fn extern_foo(_: &i32) {} + +unsafe extern "C" fn unsafe_extern_foo(_: &i32) {} + +fn rust_foo(_: &i32) {} + fn main() { let b: fn() -> u32 = bar; //~ ERROR mismatched types [E0308] let f: fn(i32) = foo; //~ ERROR mismatched types [E0308] + + // See https://github.com/rust-lang/rust/issues/151393 + let _: for<'a> fn(&'a i32) = extern_foo; //~ ERROR mismatched types [E0308] + let _: for<'a> fn(&'a i32) = unsafe_extern_foo; //~ ERROR mismatched types [E0308] + let _: for<'a> extern "C" fn(&'a i32) = rust_foo; //~ ERROR mismatched types [E0308] + let _: for<'a> unsafe extern "C" fn(&'a i32) = rust_foo; //~ ERROR mismatched types [E0308] } diff --git a/tests/ui/mismatched_types/fn-pointer-mismatch-diagnostics.stderr b/tests/ui/mismatched_types/fn-pointer-mismatch-diagnostics.stderr index 8d63f2ea2d3c0..7158143679465 100644 --- a/tests/ui/mismatched_types/fn-pointer-mismatch-diagnostics.stderr +++ b/tests/ui/mismatched_types/fn-pointer-mismatch-diagnostics.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/fn-pointer-mismatch-diagnostics.rs:14:26 + --> $DIR/fn-pointer-mismatch-diagnostics.rs:20:26 | LL | let b: fn() -> u32 = bar; | ----------- ^^^ expected fn pointer, found fn item @@ -10,7 +10,7 @@ LL | let b: fn() -> u32 = bar; found fn item `fn() -> () {bar}` error[E0308]: mismatched types - --> $DIR/fn-pointer-mismatch-diagnostics.rs:15:22 + --> $DIR/fn-pointer-mismatch-diagnostics.rs:21:22 | LL | let f: fn(i32) = foo; | ------- ^^^ expected fn pointer, found fn item @@ -20,6 +20,51 @@ LL | let f: fn(i32) = foo; = note: expected fn pointer `fn(_) -> ()` found fn item `fn(_) -> u32 {foo}` -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/fn-pointer-mismatch-diagnostics.rs:24:34 + | +LL | let _: for<'a> fn(&'a i32) = extern_foo; + | ------------------- ^^^^^^^^^^ expected "Rust" fn, found "C" fn + | | + | expected due to this + | + = note: expected fn pointer `for<'a> fn(&'a _)` + found fn item `for<'a> extern "C" fn(&'a _) {extern_foo}` + +error[E0308]: mismatched types + --> $DIR/fn-pointer-mismatch-diagnostics.rs:25:34 + | +LL | let _: for<'a> fn(&'a i32) = unsafe_extern_foo; + | ------------------- ^^^^^^^^^^^^^^^^^ expected safe fn, found unsafe fn + | | + | expected due to this + | + = note: expected fn pointer `for<'a> fn(&'a _)` + found fn item `for<'a> unsafe extern "C" fn(&'a _) {unsafe_extern_foo}` + = note: unsafe functions cannot be coerced into safe function pointers + +error[E0308]: mismatched types + --> $DIR/fn-pointer-mismatch-diagnostics.rs:26:45 + | +LL | let _: for<'a> extern "C" fn(&'a i32) = rust_foo; + | ------------------------------ ^^^^^^^^ expected "C" fn, found "Rust" fn + | | + | expected due to this + | + = note: expected fn pointer `for<'a> extern "C" fn(&'a _)` + found fn item `for<'a> fn(&'a _) {rust_foo}` + +error[E0308]: mismatched types + --> $DIR/fn-pointer-mismatch-diagnostics.rs:27:52 + | +LL | let _: for<'a> unsafe extern "C" fn(&'a i32) = rust_foo; + | ------------------------------------- ^^^^^^^^ expected "C" fn, found "Rust" fn + | | + | expected due to this + | + = note: expected fn pointer `for<'a> unsafe extern "C" fn(&'a _)` + found fn item `for<'a> fn(&'a _) {rust_foo}` + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0308`.