diff --git a/.ignore b/.ignore new file mode 100644 index 0000000000000..40d1513978fc6 --- /dev/null +++ b/.ignore @@ -0,0 +1,2 @@ +# Make vscode *not* count `config.toml` as ignored, so it is included in search +!/config.toml diff --git a/.reuse/dep5 b/.reuse/dep5 index 0e2650ff2c048..5706ea0b2046b 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -36,6 +36,7 @@ Files: compiler/* .gitignore .gitmodules .mailmap + .ignore Copyright: The Rust Project Developers (see https://thanks.rust-lang.org) License: MIT or Apache-2.0 diff --git a/Cargo.lock b/Cargo.lock index 0182eca05058d..94d70a020a4dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3401,6 +3401,7 @@ name = "run_make_support" version = "0.2.0" dependencies = [ "ar", + "bstr", "gimli 0.28.1", "object 0.34.0", "regex", @@ -3460,6 +3461,13 @@ dependencies = [ "stable_mir", ] +[[package]] +name = "rustc-perf-wrapper" +version = "0.1.0" +dependencies = [ + "clap", +] + [[package]] name = "rustc-rayon" version = "0.5.0" @@ -4752,8 +4760,6 @@ checksum = "8ba09476327c4b70ccefb6180f046ef588c26a24cf5d269a9feba316eb4f029f" name = "rustc_trait_selection" version = "0.0.0" dependencies = [ - "bitflags 2.5.0", - "derivative", "itertools", "rustc_ast", "rustc_ast_ir", @@ -4762,7 +4768,6 @@ dependencies = [ "rustc_errors", "rustc_fluent_macro", "rustc_hir", - "rustc_index", "rustc_infer", "rustc_macros", "rustc_middle", @@ -4775,7 +4780,6 @@ dependencies = [ "rustc_target", "rustc_transmute", "rustc_type_ir", - "rustc_type_ir_macros", "smallvec", "tracing", ] diff --git a/Cargo.toml b/Cargo.toml index c17ea99d03767..93c520b0d689d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,6 +44,7 @@ members = [ "src/tools/rustdoc-gui-test", "src/tools/opt-dist", "src/tools/coverage-dump", + "src/tools/rustc-perf-wrapper", ] exclude = [ diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 624bca525b9f3..218fa9740229d 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -103,7 +103,6 @@ impl<'hir> LoweringContext<'_, 'hir> { ParamMode::Optional, ParenthesizedGenericArgs::Err, ImplTraitContext::Disallowed(ImplTraitPosition::Path), - None, // Method calls can't have bound modifiers None, )); diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 74e04eff4f3e0..d59ac5766298d 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -56,7 +56,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { owner: NodeId, f: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::OwnerNode<'hir>, ) { - let mut lctx = LoweringContext::new(self.tcx, self.resolver); + let mut lctx = LoweringContext::new(self.tcx, self.resolver, self.ast_index); lctx.with_hir_id_owner(owner, |lctx| f(lctx)); for (def_id, info) in lctx.children { @@ -190,6 +190,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, (ty, body_id)) = self.lower_generics( generics, Const::No, + false, id, ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { @@ -221,7 +222,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let itctx = ImplTraitContext::Universal; let (generics, decl) = - this.lower_generics(generics, header.constness, id, itctx, |this| { + this.lower_generics(generics, header.constness, false, id, itctx, |this| { this.lower_fn_decl( decl, id, @@ -265,6 +266,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, ty) = self.lower_generics( &generics, Const::No, + false, id, ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| match ty { @@ -293,6 +295,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, variants) = self.lower_generics( generics, Const::No, + false, id, ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { @@ -307,6 +310,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, struct_def) = self.lower_generics( generics, Const::No, + false, id, ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| this.lower_variant_data(hir_id, struct_def), @@ -317,6 +321,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, vdata) = self.lower_generics( generics, Const::No, + false, id, ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| this.lower_variant_data(hir_id, vdata), @@ -348,12 +353,9 @@ impl<'hir> LoweringContext<'_, 'hir> { // parent lifetime. let itctx = ImplTraitContext::Universal; let (generics, (trait_ref, lowered_ty)) = - self.lower_generics(ast_generics, *constness, id, itctx, |this| { + self.lower_generics(ast_generics, Const::No, false, id, itctx, |this| { let modifiers = TraitBoundModifiers { - constness: match *constness { - Const::Yes(span) => BoundConstness::Maybe(span), - Const::No => BoundConstness::Never, - }, + constness: BoundConstness::Never, asyncness: BoundAsyncness::Normal, // we don't use this in bound lowering polarity: BoundPolarity::Positive, @@ -389,6 +391,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ImplPolarity::Negative(s) => ImplPolarity::Negative(self.lower_span(*s)), }; hir::ItemKind::Impl(self.arena.alloc(hir::Impl { + constness: self.lower_constness(*constness), safety: self.lower_safety(*safety, hir::Safety::Safe), polarity, defaultness, @@ -400,15 +403,10 @@ impl<'hir> LoweringContext<'_, 'hir> { })) } ItemKind::Trait(box Trait { is_auto, safety, generics, bounds, items }) => { - // FIXME(const_trait_impl, effects, fee1-dead) this should be simplified if possible - let constness = attrs - .unwrap_or(&[]) - .iter() - .find(|x| x.has_name(sym::const_trait)) - .map_or(Const::No, |x| Const::Yes(x.span)); let (generics, (safety, items, bounds)) = self.lower_generics( generics, - constness, + Const::No, + false, id, ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { @@ -429,6 +427,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, bounds) = self.lower_generics( generics, Const::No, + false, id, ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { @@ -609,30 +608,45 @@ impl<'hir> LoweringContext<'_, 'hir> { // This is used to track which lifetimes have already been defined, // and which need to be replicated when lowering an async fn. - let generics = match parent_hir.node().expect_item().kind { + let parent_item = parent_hir.node().expect_item(); + let constness = match parent_item.kind { hir::ItemKind::Impl(impl_) => { self.is_in_trait_impl = impl_.of_trait.is_some(); - &impl_.generics + // N.B. the impl should always lower to methods that have `const host: bool` params if the trait + // is const. It doesn't matter whether the `impl` itself is const. Disallowing const fn from + // calling non-const impls are done through associated types. + if let Some(def_id) = impl_.of_trait.and_then(|tr| tr.trait_def_id()) { + if let Some(local_def) = def_id.as_local() { + match &self.ast_index[local_def] { + AstOwner::Item(ast::Item { attrs, .. }) => attrs + .iter() + .find(|attr| attr.has_name(sym::const_trait)) + .map_or(Const::No, |attr| Const::Yes(attr.span)), + _ => Const::No, + } + } else { + self.tcx + .get_attr(def_id, sym::const_trait) + .map_or(Const::No, |attr| Const::Yes(attr.span)) + } + } else { + Const::No + } } - hir::ItemKind::Trait(_, _, generics, _, _) => generics, + hir::ItemKind::Trait(_, _, _, _, _) => parent_hir + .attrs + .get(parent_item.hir_id().local_id) + .iter() + .find(|attr| attr.has_name(sym::const_trait)) + .map_or(Const::No, |attr| Const::Yes(attr.span)), kind => { span_bug!(item.span, "assoc item has unexpected kind of parent: {}", kind.descr()) } }; - if self.tcx.features().effects { - self.host_param_id = generics - .params - .iter() - .find(|param| { - matches!(param.kind, hir::GenericParamKind::Const { is_host_effect: true, .. }) - }) - .map(|param| param.def_id); - } - match ctxt { - AssocCtxt::Trait => hir::OwnerNode::TraitItem(self.lower_trait_item(item)), - AssocCtxt::Impl => hir::OwnerNode::ImplItem(self.lower_impl_item(item)), + AssocCtxt::Trait => hir::OwnerNode::TraitItem(self.lower_trait_item(item, constness)), + AssocCtxt::Impl => hir::OwnerNode::ImplItem(self.lower_impl_item(item, constness)), } } @@ -648,7 +662,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let fdec = &sig.decl; let itctx = ImplTraitContext::Universal; let (generics, (fn_dec, fn_args)) = - self.lower_generics(generics, Const::No, i.id, itctx, |this| { + self.lower_generics(generics, Const::No, false, i.id, itctx, |this| { ( // Disallow `impl Trait` in foreign items. this.lower_fn_decl( @@ -765,7 +779,11 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> { + fn lower_trait_item( + &mut self, + i: &AssocItem, + trait_constness: Const, + ) -> &'hir hir::TraitItem<'hir> { let hir_id = self.lower_node_id(i.id); self.lower_attrs(hir_id, &i.attrs); let trait_item_def_id = hir_id.expect_owner(); @@ -775,6 +793,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, kind) = self.lower_generics( generics, Const::No, + false, i.id, ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { @@ -795,6 +814,7 @@ impl<'hir> LoweringContext<'_, 'hir> { i.id, FnDeclKind::Trait, sig.header.coroutine_kind, + trait_constness, ); (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false) } @@ -813,6 +833,7 @@ impl<'hir> LoweringContext<'_, 'hir> { i.id, FnDeclKind::Trait, sig.header.coroutine_kind, + trait_constness, ); (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true) } @@ -822,6 +843,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, kind) = self.lower_generics( &generics, Const::No, + false, i.id, ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { @@ -894,7 +916,11 @@ impl<'hir> LoweringContext<'_, 'hir> { self.expr(span, hir::ExprKind::Err(guar)) } - fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> { + fn lower_impl_item( + &mut self, + i: &AssocItem, + constness_of_trait: Const, + ) -> &'hir hir::ImplItem<'hir> { // Since `default impl` is not yet implemented, this is always true in impls. let has_value = true; let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value); @@ -905,6 +931,7 @@ impl<'hir> LoweringContext<'_, 'hir> { AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => self.lower_generics( generics, Const::No, + false, i.id, ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { @@ -930,6 +957,7 @@ impl<'hir> LoweringContext<'_, 'hir> { i.id, if self.is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent }, sig.header.coroutine_kind, + constness_of_trait, ); (generics, hir::ImplItemKind::Fn(sig, body_id)) @@ -940,6 +968,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_generics( &generics, Const::No, + false, i.id, ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| match ty { @@ -1352,15 +1381,18 @@ impl<'hir> LoweringContext<'_, 'hir> { id: NodeId, kind: FnDeclKind, coroutine_kind: Option, + parent_constness: Const, ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) { let header = self.lower_fn_header(sig.header); // Don't pass along the user-provided constness of trait associated functions; we don't want to // synthesize a host effect param for them. We reject `const` on them during AST validation. - let constness = if kind == FnDeclKind::Inherent { sig.header.constness } else { Const::No }; + let constness = + if kind == FnDeclKind::Inherent { sig.header.constness } else { parent_constness }; let itctx = ImplTraitContext::Universal; - let (generics, decl) = self.lower_generics(generics, constness, id, itctx, |this| { - this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind) - }); + let (generics, decl) = + self.lower_generics(generics, constness, kind == FnDeclKind::Impl, id, itctx, |this| { + this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind) + }); (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) }) } @@ -1436,6 +1468,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, generics: &Generics, constness: Const, + force_append_constness: bool, parent_node_id: NodeId, itctx: ImplTraitContext, f: impl FnOnce(&mut Self) -> T, @@ -1496,7 +1529,9 @@ impl<'hir> LoweringContext<'_, 'hir> { // if the effects feature is enabled. This needs to be done before we lower where // clauses since where clauses need to bind to the DefId of the host param let host_param_parts = if let Const::Yes(span) = constness - && self.tcx.features().effects + // if this comes from implementing a `const` trait, we must force constness to be appended + // to the impl item, no matter whether effects is enabled. + && (self.tcx.features().effects || force_append_constness) { let span = self.lower_span(span); let param_node_id = self.next_node_id(); @@ -1609,6 +1644,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }), )), )), + // FIXME(effects) we might not need a default. default: Some(self.arena.alloc(hir::AnonConst { def_id: anon_const, hir_id: const_id, @@ -1616,6 +1652,7 @@ impl<'hir> LoweringContext<'_, 'hir> { span, })), is_host_effect: true, + synthetic: true, }, colon_span: None, pure_wrt_drop: false, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 0a06304fcecfa..8fba46625ab9a 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -142,14 +142,19 @@ struct LoweringContext<'a, 'hir> { generics_def_id_map: Vec>, host_param_id: Option, + ast_index: &'a IndexSlice>, } impl<'a, 'hir> LoweringContext<'a, 'hir> { - fn new(tcx: TyCtxt<'hir>, resolver: &'a mut ResolverAstLowering) -> Self { + fn new( + tcx: TyCtxt<'hir>, + resolver: &'a mut ResolverAstLowering, + ast_index: &'a IndexSlice>, + ) -> Self { Self { // Pseudo-globals. tcx, - resolver: resolver, + resolver, arena: tcx.hir_arena, // HirId handling. @@ -185,6 +190,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { allow_async_iterator: [sym::gen_future, sym::async_iterator].into(), generics_def_id_map: Default::default(), host_param_id: None, + ast_index, } } @@ -2135,7 +2141,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { param: &GenericParam, source: hir::GenericParamSource, ) -> hir::GenericParam<'hir> { - let (name, kind) = self.lower_generic_param_kind(param, source); + let (name, kind) = self.lower_generic_param_kind( + param, + source, + attr::contains_name(¶m.attrs, sym::rustc_runtime), + ); let hir_id = self.lower_node_id(param.id); self.lower_attrs(hir_id, ¶m.attrs); @@ -2155,6 +2165,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, param: &GenericParam, source: hir::GenericParamSource, + is_host_effect: bool, ) -> (hir::ParamName, hir::GenericParamKind<'hir>) { match ¶m.kind { GenericParamKind::Lifetime => { @@ -2220,7 +2231,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ( hir::ParamName::Plain(self.lower_ident(param.ident)), - hir::GenericParamKind::Const { ty, default, is_host_effect: false }, + hir::GenericParamKind::Const { ty, default, is_host_effect, synthetic: false }, ) } } @@ -2607,78 +2618,6 @@ struct GenericArgsCtor<'hir> { } impl<'hir> GenericArgsCtor<'hir> { - fn push_constness( - &mut self, - lcx: &mut LoweringContext<'_, 'hir>, - constness: ast::BoundConstness, - ) { - if !lcx.tcx.features().effects { - return; - } - - let (span, body) = match constness { - BoundConstness::Never => return, - BoundConstness::Always(span) => { - let span = lcx.lower_span(span); - - let body = hir::ExprKind::Lit( - lcx.arena.alloc(hir::Lit { node: LitKind::Bool(false), span }), - ); - - (span, body) - } - BoundConstness::Maybe(span) => { - let span = lcx.lower_span(span); - - let Some(host_param_id) = lcx.host_param_id else { - lcx.dcx().span_delayed_bug( - span, - "no host param id for call in const yet no errors reported", - ); - return; - }; - - let hir_id = lcx.next_id(); - let res = Res::Def(DefKind::ConstParam, host_param_id.to_def_id()); - let body = hir::ExprKind::Path(hir::QPath::Resolved( - None, - lcx.arena.alloc(hir::Path { - span, - res, - segments: arena_vec![ - lcx; - hir::PathSegment::new( - Ident { name: sym::host, span }, - hir_id, - res - ) - ], - }), - )); - - (span, body) - } - }; - let body = lcx.lower_body(|lcx| (&[], lcx.expr(span, body))); - - let id = lcx.next_node_id(); - let hir_id = lcx.next_id(); - - let def_id = lcx.create_def( - lcx.current_hir_id_owner.def_id, - id, - kw::Empty, - DefKind::AnonConst, - span, - ); - - lcx.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id))); - self.args.push(hir::GenericArg::Const(hir::ConstArg { - value: lcx.arena.alloc(hir::AnonConst { def_id, hir_id, body, span }), - is_desugared_from_effects: true, - })) - } - fn is_empty(&self) -> bool { self.args.is_empty() && self.constraints.is_empty() diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 9d38e1e678471..9a1ca703699a8 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -107,8 +107,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { param_mode, parenthesized_generic_args, itctx, - // if this is the last segment, add constness to the trait path - if i == proj_start - 1 { modifiers.map(|m| m.constness) } else { None }, bound_modifier_allowed_features.clone(), ) }, @@ -165,7 +163,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ParenthesizedGenericArgs::Err, itctx, None, - None, )); let qpath = hir::QPath::TypeRelative(ty, hir_segment); @@ -208,7 +205,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ParenthesizedGenericArgs::Err, ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, - None, ) })), span: self.lower_span(p.span), @@ -222,7 +218,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { param_mode: ParamMode, parenthesized_generic_args: ParenthesizedGenericArgs, itctx: ImplTraitContext, - constness: Option, // Additional features ungated with a bound modifier like `async`. // This is passed down to the implicit associated type binding in // parenthesized bounds. @@ -289,10 +284,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) }; - if let Some(constness) = constness { - generic_args.push_constness(self, constness); - } - let has_lifetimes = generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_))); diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index ba4b6130b60c8..022f953c6e70f 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1,10 +1,20 @@ -// Validate AST before lowering it to HIR. -// -// This pass is supposed to catch things that fit into AST data structures, -// but not permitted by the language. It runs after expansion when AST is frozen, -// so it can check for erroneous constructions produced by syntax extensions. -// This pass is supposed to perform only simple checks not requiring name resolution -// or type checking or some other kind of complex analysis. +//! Validate AST before lowering it to HIR. +//! +//! This pass intends to check that the constructed AST is *syntactically valid* to allow the rest +//! of the compiler to assume that the AST is valid. These checks cannot be performed during parsing +//! because attribute macros are allowed to accept certain pieces of invalid syntax such as a +//! function without body outside of a trait definition: +//! +//! ```ignore (illustrative) +//! #[my_attribute] +//! mod foo { +//! fn missing_body(); +//! } +//! ``` +//! +//! These checks are run post-expansion, after AST is frozen, to be able to check for erroneous +//! constructions produced by proc macros. This pass is only intended for simple checks that do not +//! require name resolution or type checking, or other kinds of complex analysis. use itertools::{Either, Itertools}; use rustc_ast::ptr::P; @@ -459,13 +469,18 @@ impl<'a> AstValidator<'a> { fn check_item_safety(&self, span: Span, safety: Safety) { match self.extern_mod_safety { Some(extern_safety) => { - if matches!(safety, Safety::Unsafe(_) | Safety::Safe(_)) - && (extern_safety == Safety::Default || !self.features.unsafe_extern_blocks) - { - self.dcx().emit_err(errors::InvalidSafetyOnExtern { - item_span: span, - block: self.current_extern_span().shrink_to_lo(), - }); + if matches!(safety, Safety::Unsafe(_) | Safety::Safe(_)) { + if extern_safety == Safety::Default { + self.dcx().emit_err(errors::InvalidSafetyOnExtern { + item_span: span, + block: Some(self.current_extern_span().shrink_to_lo()), + }); + } else if !self.features.unsafe_extern_blocks { + self.dcx().emit_err(errors::InvalidSafetyOnExtern { + item_span: span, + block: None, + }); + } } } None => { @@ -1088,7 +1103,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } } else if let &Safety::Unsafe(span) = safety { - this.dcx().emit_err(errors::UnsafeItem { span, kind: "extern block" }); + let mut diag = this + .dcx() + .create_err(errors::UnsafeItem { span, kind: "extern block" }); + rustc_session::parse::add_feature_diagnostics( + &mut diag, + self.session, + sym::unsafe_extern_blocks, + ); + diag.emit(); } if abi.is_none() { diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 965d8fac712ae..bfb9047645011 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -222,7 +222,7 @@ pub struct InvalidSafetyOnExtern { #[primary_span] pub item_span: Span, #[suggestion(code = "unsafe ", applicability = "machine-applicable", style = "verbose")] - pub block: Span, + pub block: Option, } #[derive(Diagnostic)] diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index f26f8711dd40b..8eb44458137ff 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -6,8 +6,8 @@ use rustc_middle::span_bug; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; -impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> { - pub fn dcx(&self) -> DiagCtxtHandle<'tcx> { +impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { + pub fn dcx(&self) -> DiagCtxtHandle<'infcx> { self.infcx.dcx() } @@ -18,7 +18,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> { place: &str, borrow_place: &str, value_place: &str, - ) -> Diag<'tcx> { + ) -> Diag<'infcx> { self.dcx().create_err(crate::session_diagnostics::MoveBorrow { place, span, @@ -34,7 +34,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> { desc: &str, borrow_span: Span, borrow_desc: &str, - ) -> Diag<'tcx> { + ) -> Diag<'infcx> { struct_span_code_err!( self.dcx(), span, @@ -54,7 +54,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> { old_loan_span: Span, old_opt_via: &str, old_load_end_span: Option, - ) -> Diag<'tcx> { + ) -> Diag<'infcx> { let via = |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {msg})") }; let mut err = struct_span_code_err!( self.dcx(), @@ -101,7 +101,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> { desc: &str, old_loan_span: Span, old_load_end_span: Option, - ) -> Diag<'tcx> { + ) -> Diag<'infcx> { let mut err = struct_span_code_err!( self.dcx(), new_loan_span, @@ -134,7 +134,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> { noun_old: &str, old_opt_via: &str, previous_end_span: Option, - ) -> Diag<'tcx> { + ) -> Diag<'infcx> { let mut err = struct_span_code_err!( self.dcx(), new_loan_span, @@ -166,7 +166,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> { old_opt_via: &str, previous_end_span: Option, second_borrow_desc: &str, - ) -> Diag<'tcx> { + ) -> Diag<'infcx> { let mut err = struct_span_code_err!( self.dcx(), new_loan_span, @@ -198,7 +198,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> { kind_old: &str, msg_old: &str, old_load_end_span: Option, - ) -> Diag<'tcx> { + ) -> Diag<'infcx> { let via = |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {msg})") }; let mut err = struct_span_code_err!( self.dcx(), @@ -239,7 +239,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> { span: Span, borrow_span: Span, desc: &str, - ) -> Diag<'tcx> { + ) -> Diag<'infcx> { struct_span_code_err!( self.dcx(), span, @@ -256,12 +256,12 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> { span: Span, desc: &str, is_arg: bool, - ) -> Diag<'tcx> { + ) -> Diag<'infcx> { let msg = if is_arg { "to immutable argument" } else { "twice to immutable variable" }; struct_span_code_err!(self.dcx(), span, E0384, "cannot assign {} {}", msg, desc) } - pub(crate) fn cannot_assign(&self, span: Span, desc: &str) -> Diag<'tcx> { + pub(crate) fn cannot_assign(&self, span: Span, desc: &str) -> Diag<'infcx> { struct_span_code_err!(self.dcx(), span, E0594, "cannot assign to {}", desc) } @@ -269,7 +269,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> { &self, move_from_span: Span, move_from_desc: &str, - ) -> Diag<'tcx> { + ) -> Diag<'infcx> { struct_span_code_err!( self.dcx(), move_from_span, @@ -287,7 +287,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> { move_from_span: Span, ty: Ty<'_>, is_index: Option, - ) -> Diag<'tcx> { + ) -> Diag<'infcx> { let type_name = match (&ty.kind(), is_index) { (&ty::Array(_, _), Some(true)) | (&ty::Array(_, _), None) => "array", (&ty::Slice(_), _) => "slice", @@ -308,7 +308,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> { &self, move_from_span: Span, container_ty: Ty<'_>, - ) -> Diag<'tcx> { + ) -> Diag<'infcx> { struct_span_code_err!( self.dcx(), move_from_span, @@ -325,7 +325,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> { verb: &str, optional_adverb_for_moved: &str, moved_path: Option, - ) -> Diag<'tcx> { + ) -> Diag<'infcx> { let moved_path = moved_path.map(|mp| format!(": `{mp}`")).unwrap_or_default(); struct_span_code_err!( @@ -344,7 +344,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> { span: Span, path: &str, reason: &str, - ) -> Diag<'tcx> { + ) -> Diag<'infcx> { struct_span_code_err!( self.dcx(), span, @@ -362,7 +362,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> { immutable_place: &str, immutable_section: &str, action: &str, - ) -> Diag<'tcx> { + ) -> Diag<'infcx> { struct_span_code_err!( self.dcx(), mutate_span, @@ -380,7 +380,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> { &self, span: Span, yield_span: Span, - ) -> Diag<'tcx> { + ) -> Diag<'infcx> { let coroutine_kind = self.body.coroutine.as_ref().unwrap().coroutine_kind; struct_span_code_err!( self.dcx(), @@ -391,7 +391,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> { .with_span_label(yield_span, "possible yield occurs here") } - pub(crate) fn cannot_borrow_across_destructor(&self, borrow_span: Span) -> Diag<'tcx> { + pub(crate) fn cannot_borrow_across_destructor(&self, borrow_span: Span) -> Diag<'infcx> { struct_span_code_err!( self.dcx(), borrow_span, @@ -400,7 +400,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> { ) } - pub(crate) fn path_does_not_live_long_enough(&self, span: Span, path: &str) -> Diag<'tcx> { + pub(crate) fn path_does_not_live_long_enough(&self, span: Span, path: &str) -> Diag<'infcx> { struct_span_code_err!(self.dcx(), span, E0597, "{} does not live long enough", path,) } @@ -410,7 +410,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> { return_kind: &str, reference_desc: &str, path_desc: &str, - ) -> Diag<'tcx> { + ) -> Diag<'infcx> { struct_span_code_err!( self.dcx(), span, @@ -433,7 +433,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> { borrowed_path: &str, capture_span: Span, scope: &str, - ) -> Diag<'tcx> { + ) -> Diag<'infcx> { struct_span_code_err!( self.dcx(), closure_span, @@ -445,7 +445,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> { .with_span_label(closure_span, format!("may outlive borrowed value {borrowed_path}")) } - pub(crate) fn thread_local_value_does_not_live_long_enough(&self, span: Span) -> Diag<'tcx> { + pub(crate) fn thread_local_value_does_not_live_long_enough(&self, span: Span) -> Diag<'infcx> { struct_span_code_err!( self.dcx(), span, @@ -454,7 +454,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> { ) } - pub(crate) fn temporary_value_borrowed_for_too_long(&self, span: Span) -> Diag<'tcx> { + pub(crate) fn temporary_value_borrowed_for_too_long(&self, span: Span) -> Diag<'infcx> { struct_span_code_err!(self.dcx(), span, E0716, "temporary value dropped while borrowed",) } } diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index f2b5ddcd7827c..00a30dc2240a6 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -15,24 +15,24 @@ use std::fmt; use crate::{places_conflict, BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext}; /// The results of the dataflow analyses used by the borrow checker. -pub struct BorrowckResults<'mir, 'tcx> { - pub(crate) borrows: Results<'tcx, Borrows<'mir, 'tcx>>, - pub(crate) uninits: Results<'tcx, MaybeUninitializedPlaces<'mir, 'tcx>>, - pub(crate) ever_inits: Results<'tcx, EverInitializedPlaces<'mir, 'tcx>>, +pub struct BorrowckResults<'a, 'mir, 'tcx> { + pub(crate) borrows: Results<'tcx, Borrows<'a, 'mir, 'tcx>>, + pub(crate) uninits: Results<'tcx, MaybeUninitializedPlaces<'a, 'mir, 'tcx>>, + pub(crate) ever_inits: Results<'tcx, EverInitializedPlaces<'a, 'mir, 'tcx>>, } /// The transient state of the dataflow analyses used by the borrow checker. #[derive(Debug)] -pub struct BorrowckFlowState<'mir, 'tcx> { - pub(crate) borrows: as AnalysisDomain<'tcx>>::Domain, - pub(crate) uninits: as AnalysisDomain<'tcx>>::Domain, - pub(crate) ever_inits: as AnalysisDomain<'tcx>>::Domain, +pub struct BorrowckFlowState<'a, 'mir, 'tcx> { + pub(crate) borrows: as AnalysisDomain<'tcx>>::Domain, + pub(crate) uninits: as AnalysisDomain<'tcx>>::Domain, + pub(crate) ever_inits: as AnalysisDomain<'tcx>>::Domain, } -impl<'mir, 'tcx> ResultsVisitable<'tcx> for BorrowckResults<'mir, 'tcx> { +impl<'a, 'mir, 'tcx> ResultsVisitable<'tcx> for BorrowckResults<'a, 'mir, 'tcx> { // All three analyses are forward, but we have to use just one here. - type Direction = as AnalysisDomain<'tcx>>::Direction; - type FlowState = BorrowckFlowState<'mir, 'tcx>; + type Direction = as AnalysisDomain<'tcx>>::Direction; + type FlowState = BorrowckFlowState<'a, 'mir, 'tcx>; fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState { BorrowckFlowState { @@ -106,11 +106,11 @@ rustc_index::newtype_index! { /// `BorrowIndex`, and maps each such index to a `BorrowData` /// describing the borrow. These indexes are used for representing the /// borrows in compact bitvectors. -pub struct Borrows<'mir, 'tcx> { +pub struct Borrows<'a, 'mir, 'tcx> { tcx: TyCtxt<'tcx>, body: &'mir Body<'tcx>, - borrow_set: &'mir BorrowSet<'tcx>, + borrow_set: &'a BorrowSet<'tcx>, borrows_out_of_scope_at_location: FxIndexMap>, } @@ -389,12 +389,12 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> { } } -impl<'mir, 'tcx> Borrows<'mir, 'tcx> { +impl<'a, 'mir, 'tcx> Borrows<'a, 'mir, 'tcx> { pub fn new( tcx: TyCtxt<'tcx>, body: &'mir Body<'tcx>, - regioncx: &'mir RegionInferenceContext<'tcx>, - borrow_set: &'mir BorrowSet<'tcx>, + regioncx: &RegionInferenceContext<'tcx>, + borrow_set: &'a BorrowSet<'tcx>, ) -> Self { let mut borrows_out_of_scope_at_location = calculate_borrows_out_of_scope_at_location(body, regioncx, borrow_set); @@ -494,7 +494,7 @@ impl<'mir, 'tcx> Borrows<'mir, 'tcx> { } } -impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> { +impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, '_, 'tcx> { type Domain = BitSet; const NAME: &'static str = "borrows"; @@ -517,7 +517,7 @@ impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> { /// region stops containing the CFG points reachable from the issuing location. /// - we also kill loans of conflicting places when overwriting a shared path: e.g. borrows of /// `a.b.c` when `a` is overwritten. -impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> { +impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, '_, 'tcx> { type Idx = BorrowIndex; fn domain_size(&self, _: &mir::Body<'tcx>) -> usize { @@ -617,8 +617,8 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> { } } -impl DebugWithContext> for BorrowIndex { - fn fmt_with(&self, ctxt: &Borrows<'_, '_>, f: &mut fmt::Formatter<'_>) -> fmt::Result { +impl DebugWithContext> for BorrowIndex { + fn fmt_with(&self, ctxt: &Borrows<'_, '_, '_>, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}", ctxt.location(*self)) } } diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index d46febffba862..8bf3e670ff228 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -149,13 +149,13 @@ trait TypeOpInfo<'tcx> { fn base_universe(&self) -> ty::UniverseIndex; - fn nice_error( + fn nice_error<'infcx>( &self, - mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>, + mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>, cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option>, - ) -> Option>; + ) -> Option>; #[instrument(level = "debug", skip(self, mbcx))] fn report_error( @@ -231,18 +231,25 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> { self.base_universe } - fn nice_error( + fn nice_error<'infcx>( &self, - mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>, + mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>, cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option>, - ) -> Option> { + ) -> Option> { let (infcx, key, _) = mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query); let ocx = ObligationCtxt::new(&infcx); type_op_prove_predicate_with_cause(&ocx, key, cause); - try_extract_error_from_fulfill_cx(&ocx, mbcx.mir_def_id(), placeholder_region, error_region) + let diag = try_extract_error_from_fulfill_cx( + &ocx, + mbcx.mir_def_id(), + placeholder_region, + error_region, + )? + .with_dcx(mbcx.dcx()); + Some(diag) } } @@ -268,13 +275,13 @@ where self.base_universe } - fn nice_error( + fn nice_error<'infcx>( &self, - mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>, + mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>, cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option>, - ) -> Option> { + ) -> Option> { let (infcx, key, _) = mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query); let ocx = ObligationCtxt::new(&infcx); @@ -288,7 +295,14 @@ where let (param_env, value) = key.into_parts(); let _ = ocx.normalize(&cause, param_env, value.value); - try_extract_error_from_fulfill_cx(&ocx, mbcx.mir_def_id(), placeholder_region, error_region) + let diag = try_extract_error_from_fulfill_cx( + &ocx, + mbcx.mir_def_id(), + placeholder_region, + error_region, + )? + .with_dcx(mbcx.dcx()); + Some(diag) } } @@ -308,18 +322,25 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> { self.base_universe } - fn nice_error( + fn nice_error<'infcx>( &self, - mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>, + mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>, cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option>, - ) -> Option> { + ) -> Option> { let (infcx, key, _) = mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query); let ocx = ObligationCtxt::new(&infcx); type_op_ascribe_user_type_with_span(&ocx, key, Some(cause.span)).ok()?; - try_extract_error_from_fulfill_cx(&ocx, mbcx.mir_def_id(), placeholder_region, error_region) + let diag = try_extract_error_from_fulfill_cx( + &ocx, + mbcx.mir_def_id(), + placeholder_region, + error_region, + )? + .with_dcx(mbcx.dcx()); + Some(diag) } } @@ -334,13 +355,13 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> { self.base_universe.unwrap() } - fn nice_error( + fn nice_error<'infcx>( &self, - mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>, + mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>, _cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option>, - ) -> Option> { + ) -> Option> { try_extract_error_from_region_constraints( mbcx.infcx, mbcx.mir_def_id(), @@ -358,12 +379,12 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> { } #[instrument(skip(ocx), level = "debug")] -fn try_extract_error_from_fulfill_cx<'tcx>( - ocx: &ObligationCtxt<'_, 'tcx>, +fn try_extract_error_from_fulfill_cx<'a, 'tcx>( + ocx: &ObligationCtxt<'a, 'tcx>, generic_param_scope: LocalDefId, placeholder_region: ty::Region<'tcx>, error_region: Option>, -) -> Option> { +) -> Option> { // We generally shouldn't have errors here because the query was // already run, but there's no point using `span_delayed_bug` // when we're going to emit an error here anyway. @@ -381,15 +402,15 @@ fn try_extract_error_from_fulfill_cx<'tcx>( } #[instrument(level = "debug", skip(infcx, region_var_origin, universe_of_region))] -fn try_extract_error_from_region_constraints<'tcx>( - infcx: &InferCtxt<'tcx>, +fn try_extract_error_from_region_constraints<'a, 'tcx>( + infcx: &'a InferCtxt<'tcx>, generic_param_scope: LocalDefId, placeholder_region: ty::Region<'tcx>, error_region: Option>, region_constraints: &RegionConstraintData<'tcx>, mut region_var_origin: impl FnMut(RegionVid) -> RegionVariableOrigin, mut universe_of_region: impl FnMut(RegionVid) -> UniverseIndex, -) -> Option> { +) -> Option> { let placeholder_universe = match placeholder_region.kind() { ty::RePlaceholder(p) => p.universe, ty::ReVar(vid) => universe_of_region(vid), diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 1cc7fee718e87..44ab762f66e0a 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -73,7 +73,7 @@ enum StorageDeadOrDrop<'tcx> { Destructor(Ty<'tcx>), } -impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { +impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { pub(crate) fn report_use_of_moved_or_uninitialized( &mut self, location: Location, @@ -341,7 +341,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { fn suggest_ref_or_clone( &self, mpi: MovePathIndex, - err: &mut Diag<'tcx>, + err: &mut Diag<'infcx>, in_pattern: &mut bool, move_spans: UseSpans<'tcx>, ) { @@ -517,7 +517,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { desired_action: InitializationRequiringAction, span: Span, use_spans: UseSpans<'tcx>, - ) -> Diag<'tcx> { + ) -> Diag<'infcx> { // We need all statements in the body where the binding was assigned to later find all // the branching code paths where the binding *wasn't* assigned to. let inits = &self.move_data.init_path_map[mpi]; @@ -1288,7 +1288,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { return false; } // Try to find predicates on *generic params* that would allow copying `ty` - let suggestion = + let mut suggestion = if let Some(symbol) = tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) { format!(": {symbol}.clone()") } else { @@ -1296,6 +1296,8 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { }; let mut sugg = Vec::with_capacity(2); let mut inner_expr = expr; + let mut is_raw_ptr = false; + let typeck_result = self.infcx.tcx.typeck(self.mir_def_id()); // Remove uses of `&` and `*` when suggesting `.clone()`. while let hir::ExprKind::AddrOf(.., inner) | hir::ExprKind::Unary(hir::UnOp::Deref, inner) = &inner_expr.kind @@ -1306,14 +1308,32 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { return false; } inner_expr = inner; + if let Some(inner_type) = typeck_result.node_type_opt(inner.hir_id) { + if matches!(inner_type.kind(), ty::RawPtr(..)) { + is_raw_ptr = true; + break; + } + } } - if inner_expr.span.lo() != expr.span.lo() { + // Cloning the raw pointer doesn't make sense in some cases and would cause a type mismatch error. (see #126863) + if inner_expr.span.lo() != expr.span.lo() && !is_raw_ptr { + // Remove "(*" or "(&" sugg.push((expr.span.with_hi(inner_expr.span.lo()), String::new())); } + // Check whether `expr` is surrounded by parentheses or not. let span = if inner_expr.span.hi() != expr.span.hi() { // Account for `(*x)` to suggest `x.clone()`. - expr.span.with_lo(inner_expr.span.hi()) + if is_raw_ptr { + expr.span.shrink_to_hi() + } else { + // Remove the close parenthesis ")" + expr.span.with_lo(inner_expr.span.hi()) + } } else { + if is_raw_ptr { + sugg.push((expr.span.shrink_to_lo(), "(".to_string())); + suggestion = ").clone()".to_string(); + } expr.span.shrink_to_hi() }; sugg.push((span, suggestion)); @@ -1441,7 +1461,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { location: Location, (place, _span): (Place<'tcx>, Span), borrow: &BorrowData<'tcx>, - ) -> Diag<'tcx> { + ) -> Diag<'infcx> { let borrow_spans = self.retrieve_borrow_spans(borrow); let borrow_span = borrow_spans.args_or_use(); @@ -1491,7 +1511,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { (place, span): (Place<'tcx>, Span), gen_borrow_kind: BorrowKind, issued_borrow: &BorrowData<'tcx>, - ) -> Diag<'tcx> { + ) -> Diag<'infcx> { let issued_spans = self.retrieve_borrow_spans(issued_borrow); let issued_span = issued_spans.args_or_use(); @@ -1782,7 +1802,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { err } - fn suggest_copy_for_type_in_cloned_ref(&self, err: &mut Diag<'tcx>, place: Place<'tcx>) { + fn suggest_copy_for_type_in_cloned_ref(&self, err: &mut Diag<'infcx>, place: Place<'tcx>) { let tcx = self.infcx.tcx; let hir = tcx.hir(); let Some(body_id) = tcx.hir_node(self.mir_hir_id()).body_id() else { return }; @@ -2841,7 +2861,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { drop_span: Span, borrow_spans: UseSpans<'tcx>, explanation: BorrowExplanation<'tcx>, - ) -> Diag<'tcx> { + ) -> Diag<'infcx> { debug!( "report_local_value_does_not_live_long_enough(\ {:?}, {:?}, {:?}, {:?}, {:?}\ @@ -3016,7 +3036,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { &self, drop_span: Span, borrow_span: Span, - ) -> Diag<'tcx> { + ) -> Diag<'infcx> { debug!( "report_thread_local_value_does_not_live_long_enough(\ {:?}, {:?}\ @@ -3041,7 +3061,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { borrow_spans: UseSpans<'tcx>, proper_span: Span, explanation: BorrowExplanation<'tcx>, - ) -> Diag<'tcx> { + ) -> Diag<'infcx> { if let BorrowExplanation::MustBeValidFor { category, span, from_closure: false, .. } = explanation { @@ -3206,7 +3226,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { return_span: Span, category: ConstraintCategory<'tcx>, opt_place_desc: Option<&String>, - ) -> Result<(), Diag<'tcx>> { + ) -> Result<(), Diag<'infcx>> { let return_kind = match category { ConstraintCategory::Return(_) => "return", ConstraintCategory::Yield => "yield", @@ -3299,7 +3319,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { constraint_span: Span, captured_var: &str, scope: &str, - ) -> Diag<'tcx> { + ) -> Diag<'infcx> { let tcx = self.infcx.tcx; let args_span = use_span.args_or_use(); @@ -3411,7 +3431,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { upvar_span: Span, upvar_name: Symbol, escape_span: Span, - ) -> Diag<'tcx> { + ) -> Diag<'infcx> { let tcx = self.infcx.tcx; let escapes_from = tcx.def_descr(self.mir_def_id().to_def_id()); diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 842ed38f1e294..4567a014fe83d 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -69,7 +69,7 @@ pub(super) struct DescribePlaceOpt { pub(super) struct IncludingTupleField(pub(super) bool); -impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { +impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { /// Adds a suggestion when a closure is invoked twice with a moved variable or when a closure /// is moved after being invoked. /// @@ -86,7 +86,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { &self, location: Location, place: PlaceRef<'tcx>, - diag: &mut Diag<'_>, + diag: &mut Diag<'infcx>, ) -> bool { debug!("add_moved_or_invoked_closure_note: location={:?} place={:?}", location, place); let mut target = place.local_or_deref_local(); diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 12fa4c4f5ee05..c817a80a541f7 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -93,7 +93,7 @@ enum GroupedMoveError<'tcx> { }, } -impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { +impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { pub(crate) fn report_move_errors(&mut self) { let grouped_errors = self.group_move_errors(); for error in grouped_errors { @@ -291,7 +291,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { self.buffer_error(err); } - fn report_cannot_move_from_static(&mut self, place: Place<'tcx>, span: Span) -> Diag<'tcx> { + fn report_cannot_move_from_static(&mut self, place: Place<'tcx>, span: Span) -> Diag<'infcx> { let description = if place.projection.len() == 1 { format!("static item {}", self.describe_any_place(place.as_ref())) } else { @@ -428,7 +428,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { deref_target_place: Place<'tcx>, span: Span, use_spans: Option>, - ) -> Diag<'tcx> { + ) -> Diag<'infcx> { let tcx = self.infcx.tcx; // Inspect the type of the content behind the // borrow to provide feedback about why this @@ -639,12 +639,27 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { fn add_borrow_suggestions(&self, err: &mut Diag<'_>, span: Span) { match self.infcx.tcx.sess.source_map().span_to_snippet(span) { Ok(snippet) if snippet.starts_with('*') => { - err.span_suggestion_verbose( - span.with_hi(span.lo() + BytePos(1)), - "consider removing the dereference here", - String::new(), - Applicability::MaybeIncorrect, - ); + let sp = span.with_lo(span.lo() + BytePos(1)); + let inner = self.find_expr(sp); + let mut is_raw_ptr = false; + if let Some(inner) = inner { + let typck_result = self.infcx.tcx.typeck(self.mir_def_id()); + if let Some(inner_type) = typck_result.node_type_opt(inner.hir_id) { + if matches!(inner_type.kind(), ty::RawPtr(..)) { + is_raw_ptr = true; + } + } + } + // If the `inner` is a raw pointer, do not suggest removing the "*", see #126863 + // FIXME: need to check whether the assigned object can be a raw pointer, see `tests/ui/borrowck/issue-20801.rs`. + if !is_raw_ptr { + err.span_suggestion_verbose( + span.with_hi(span.lo() + BytePos(1)), + "consider removing the dereference here", + String::new(), + Applicability::MaybeIncorrect, + ); + } } _ => { err.span_suggestion_verbose( diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 93fac3181ba4b..19a4df0cd7b43 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -30,7 +30,7 @@ pub(crate) enum AccessKind { Mutate, } -impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { +impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { pub(crate) fn report_mutability_error( &mut self, access_place: Place<'tcx>, @@ -541,7 +541,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { } /// Suggest `map[k] = v` => `map.insert(k, v)` and the like. - fn suggest_map_index_mut_alternatives(&self, ty: Ty<'tcx>, err: &mut Diag<'tcx>, span: Span) { + fn suggest_map_index_mut_alternatives(&self, ty: Ty<'tcx>, err: &mut Diag<'infcx>, span: Span) { let Some(adt) = ty.ty_adt_def() else { return }; let did = adt.did(); if self.infcx.tcx.is_diagnostic_item(sym::HashMap, did) @@ -550,13 +550,13 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { /// Walks through the HIR, looking for the corresponding span for this error. /// When it finds it, see if it corresponds to assignment operator whose LHS /// is an index expr. - struct SuggestIndexOperatorAlternativeVisitor<'a, 'tcx> { + struct SuggestIndexOperatorAlternativeVisitor<'a, 'infcx, 'tcx> { assign_span: Span, - err: &'a mut Diag<'tcx>, + err: &'a mut Diag<'infcx>, ty: Ty<'tcx>, suggested: bool, } - impl<'a, 'tcx> Visitor<'tcx> for SuggestIndexOperatorAlternativeVisitor<'a, 'tcx> { + impl<'a, 'cx, 'tcx> Visitor<'tcx> for SuggestIndexOperatorAlternativeVisitor<'a, 'cx, 'tcx> { fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) { hir::intravisit::walk_stmt(self, stmt); let expr = match stmt.kind { diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index db78edc45b9de..fba18c381466b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -160,7 +160,7 @@ pub struct ErrorConstraintInfo<'tcx> { pub(super) span: Span, } -impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { +impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { /// Converts a region inference variable into a `ty::Region` that /// we can use for error reporting. If `r` is universally bound, /// then we use the name that we have on record for it. If `r` is @@ -360,7 +360,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { let named_key = self.regioncx.name_regions(self.infcx.tcx, key); let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region); let diag = unexpected_hidden_region_diagnostic( - self.infcx.tcx, + self.infcx, self.mir_def_id(), span, named_ty, @@ -589,7 +589,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { &self, errci: &ErrorConstraintInfo<'tcx>, kind: ReturnConstraint, - ) -> Diag<'tcx> { + ) -> Diag<'infcx> { let ErrorConstraintInfo { outlived_fr, span, .. } = errci; let mut output_ty = self.regioncx.universal_regions().unnormalized_output_ty; @@ -658,7 +658,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { /// | ^^^^^^^^^^ `x` escapes the function body here /// ``` #[instrument(level = "debug", skip(self))] - fn report_escaping_data_error(&self, errci: &ErrorConstraintInfo<'tcx>) -> Diag<'tcx> { + fn report_escaping_data_error(&self, errci: &ErrorConstraintInfo<'tcx>) -> Diag<'infcx> { let ErrorConstraintInfo { span, category, .. } = errci; let fr_name_and_span = self.regioncx.get_var_name_and_span_for_region( @@ -767,7 +767,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { /// | is returning data with lifetime `'b` /// ``` #[allow(rustc::diagnostic_outside_of_impl)] // FIXME - fn report_general_error(&self, errci: &ErrorConstraintInfo<'tcx>) -> Diag<'tcx> { + fn report_general_error(&self, errci: &ErrorConstraintInfo<'tcx>) -> Diag<'infcx> { let ErrorConstraintInfo { fr, fr_is_local, diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 69efee2fbdc14..e6f8ffd428d06 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -310,8 +310,8 @@ fn do_mir_borrowck<'tcx>( promoted_mbcx.report_move_errors(); diags = promoted_mbcx.diags; - struct MoveVisitor<'a, 'b, 'mir, 'cx, 'tcx> { - ctxt: &'a mut MirBorrowckCtxt<'b, 'mir, 'cx, 'tcx>, + struct MoveVisitor<'a, 'b, 'mir, 'infcx, 'tcx> { + ctxt: &'a mut MirBorrowckCtxt<'b, 'mir, 'infcx, 'tcx>, } impl<'tcx> Visitor<'tcx> for MoveVisitor<'_, '_, '_, '_, 'tcx> { @@ -528,8 +528,8 @@ impl<'tcx> Deref for BorrowckInferCtxt<'tcx> { } } -struct MirBorrowckCtxt<'a, 'mir, 'cx, 'tcx> { - infcx: &'cx BorrowckInferCtxt<'tcx>, +struct MirBorrowckCtxt<'a, 'mir, 'infcx, 'tcx> { + infcx: &'infcx BorrowckInferCtxt<'tcx>, param_env: ParamEnv<'tcx>, body: &'mir Body<'tcx>, move_data: &'a MoveData<'tcx>, @@ -596,7 +596,7 @@ struct MirBorrowckCtxt<'a, 'mir, 'cx, 'tcx> { /// Results of Polonius analysis. polonius_output: Option>, - diags: diags::BorrowckDiags<'tcx>, + diags: diags::BorrowckDiags<'infcx, 'tcx>, move_errors: Vec>, } @@ -605,15 +605,15 @@ struct MirBorrowckCtxt<'a, 'mir, 'cx, 'tcx> { // 2. loans made in overlapping scopes do not conflict // 3. assignments do not affect things loaned out as immutable // 4. moves do not affect things loaned out in any way -impl<'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R> - for MirBorrowckCtxt<'_, 'mir, '_, 'tcx> +impl<'a, 'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R> + for MirBorrowckCtxt<'a, 'mir, '_, 'tcx> { - type FlowState = Flows<'mir, 'tcx>; + type FlowState = Flows<'a, 'mir, 'tcx>; fn visit_statement_before_primary_effect( &mut self, _results: &mut R, - flow_state: &Flows<'mir, 'tcx>, + flow_state: &Flows<'_, 'mir, 'tcx>, stmt: &'mir Statement<'tcx>, location: Location, ) { @@ -683,7 +683,7 @@ impl<'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R> fn visit_terminator_before_primary_effect( &mut self, _results: &mut R, - flow_state: &Flows<'mir, 'tcx>, + flow_state: &Flows<'_, 'mir, 'tcx>, term: &'mir Terminator<'tcx>, loc: Location, ) { @@ -794,7 +794,7 @@ impl<'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R> fn visit_terminator_after_primary_effect( &mut self, _results: &mut R, - flow_state: &Flows<'mir, 'tcx>, + flow_state: &Flows<'_, 'mir, 'tcx>, term: &'mir Terminator<'tcx>, loc: Location, ) { @@ -988,7 +988,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { place_span: (Place<'tcx>, Span), kind: (AccessDepth, ReadOrWrite), is_local_mutation_allowed: LocalMutationIsAllowed, - flow_state: &Flows<'mir, 'tcx>, + flow_state: &Flows<'_, 'mir, 'tcx>, ) { let (sd, rw) = kind; @@ -1038,7 +1038,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { place_span: (Place<'tcx>, Span), sd: AccessDepth, rw: ReadOrWrite, - flow_state: &Flows<'mir, 'tcx>, + flow_state: &Flows<'_, 'mir, 'tcx>, ) -> bool { let mut error_reported = false; let borrow_set = Rc::clone(&self.borrow_set); @@ -1179,7 +1179,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { location: Location, place_span: (Place<'tcx>, Span), kind: AccessDepth, - flow_state: &Flows<'mir, 'tcx>, + flow_state: &Flows<'_, 'mir, 'tcx>, ) { // Write of P[i] or *P requires P init'd. self.check_if_assigned_path_is_moved(location, place_span, flow_state); @@ -1197,7 +1197,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { &mut self, location: Location, (rvalue, span): (&'mir Rvalue<'tcx>, Span), - flow_state: &Flows<'mir, 'tcx>, + flow_state: &Flows<'_, 'mir, 'tcx>, ) { match rvalue { &Rvalue::Ref(_ /*rgn*/, bk, place) => { @@ -1455,7 +1455,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { &mut self, location: Location, (operand, span): (&'mir Operand<'tcx>, Span), - flow_state: &Flows<'mir, 'tcx>, + flow_state: &Flows<'_, 'mir, 'tcx>, ) { match *operand { Operand::Copy(place) => { @@ -1579,7 +1579,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { &mut self, location: Location, span: Span, - flow_state: &Flows<'mir, 'tcx>, + flow_state: &Flows<'_, 'mir, 'tcx>, ) { // Two-phase borrow support: For each activation that is newly // generated at this statement, check if it interferes with @@ -1743,7 +1743,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { location: Location, desired_action: InitializationRequiringAction, place_span: (PlaceRef<'tcx>, Span), - flow_state: &Flows<'mir, 'tcx>, + flow_state: &Flows<'_, 'mir, 'tcx>, ) { let maybe_uninits = &flow_state.uninits; @@ -1848,7 +1848,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { location: Location, desired_action: InitializationRequiringAction, place_span: (PlaceRef<'tcx>, Span), - flow_state: &Flows<'mir, 'tcx>, + flow_state: &Flows<'_, 'mir, 'tcx>, ) { let maybe_uninits = &flow_state.uninits; @@ -1947,7 +1947,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { &mut self, location: Location, (place, span): (Place<'tcx>, Span), - flow_state: &Flows<'mir, 'tcx>, + flow_state: &Flows<'_, 'mir, 'tcx>, ) { debug!("check_if_assigned_path_is_moved place: {:?}", place); @@ -2013,7 +2013,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { location: Location, base: PlaceRef<'tcx>, span: Span, - flow_state: &Flows<'mir, 'tcx>, + flow_state: &Flows<'_, 'mir, 'tcx>, ) { // rust-lang/rust#21232: Until Rust allows reads from the // initialized parts of partially initialized structs, we @@ -2104,7 +2104,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { (place, span): (Place<'tcx>, Span), kind: ReadOrWrite, is_local_mutation_allowed: LocalMutationIsAllowed, - flow_state: &Flows<'mir, 'tcx>, + flow_state: &Flows<'_, 'mir, 'tcx>, location: Location, ) -> bool { debug!( @@ -2220,7 +2220,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { fn is_local_ever_initialized( &self, local: Local, - flow_state: &Flows<'mir, 'tcx>, + flow_state: &Flows<'_, 'mir, 'tcx>, ) -> Option { let mpi = self.move_data.rev_lookup.find_local(local)?; let ii = &self.move_data.init_path_map[mpi]; @@ -2228,7 +2228,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { } /// Adds the place into the used mutable variables set - fn add_used_mut(&mut self, root_place: RootPlace<'tcx>, flow_state: &Flows<'mir, 'tcx>) { + fn add_used_mut(&mut self, root_place: RootPlace<'tcx>, flow_state: &Flows<'_, 'mir, 'tcx>) { match root_place { RootPlace { place_local: local, place_projection: [], is_local_mutation_allowed } => { // If the local may have been initialized, and it is now currently being @@ -2428,12 +2428,12 @@ mod diags { use super::*; - enum BufferedDiag<'tcx> { - Error(Diag<'tcx>), - NonError(Diag<'tcx, ()>), + enum BufferedDiag<'infcx> { + Error(Diag<'infcx>), + NonError(Diag<'infcx, ()>), } - impl<'tcx> BufferedDiag<'tcx> { + impl<'infcx> BufferedDiag<'infcx> { fn sort_span(&self) -> Span { match self { BufferedDiag::Error(diag) => diag.sort_span, @@ -2442,7 +2442,7 @@ mod diags { } } - pub struct BorrowckDiags<'tcx> { + pub struct BorrowckDiags<'infcx, 'tcx> { /// This field keeps track of move errors that are to be reported for given move indices. /// /// There are situations where many errors can be reported for a single move out (see @@ -2457,15 +2457,15 @@ mod diags { /// `BTreeMap` is used to preserve the order of insertions when iterating. This is necessary /// when errors in the map are being re-added to the error buffer so that errors with the /// same primary span come out in a consistent order. - buffered_move_errors: BTreeMap, (PlaceRef<'tcx>, Diag<'tcx>)>, + buffered_move_errors: BTreeMap, (PlaceRef<'tcx>, Diag<'infcx>)>, - buffered_mut_errors: FxIndexMap, usize)>, + buffered_mut_errors: FxIndexMap, usize)>, /// Buffer of diagnostics to be reported. A mixture of error and non-error diagnostics. - buffered_diags: Vec>, + buffered_diags: Vec>, } - impl<'tcx> BorrowckDiags<'tcx> { + impl<'infcx, 'tcx> BorrowckDiags<'infcx, 'tcx> { pub fn new() -> Self { BorrowckDiags { buffered_move_errors: BTreeMap::new(), @@ -2474,28 +2474,28 @@ mod diags { } } - pub fn buffer_error(&mut self, diag: Diag<'tcx>) { + pub fn buffer_error(&mut self, diag: Diag<'infcx>) { self.buffered_diags.push(BufferedDiag::Error(diag)); } - pub fn buffer_non_error(&mut self, diag: Diag<'tcx, ()>) { + pub fn buffer_non_error(&mut self, diag: Diag<'infcx, ()>) { self.buffered_diags.push(BufferedDiag::NonError(diag)); } } - impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { - pub fn buffer_error(&mut self, diag: Diag<'tcx>) { + impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { + pub fn buffer_error(&mut self, diag: Diag<'infcx>) { self.diags.buffer_error(diag); } - pub fn buffer_non_error(&mut self, diag: Diag<'tcx, ()>) { + pub fn buffer_non_error(&mut self, diag: Diag<'infcx, ()>) { self.diags.buffer_non_error(diag); } pub fn buffer_move_error( &mut self, move_out_indices: Vec, - place_and_err: (PlaceRef<'tcx>, Diag<'tcx>), + place_and_err: (PlaceRef<'tcx>, Diag<'infcx>), ) -> bool { if let Some((_, diag)) = self.diags.buffered_move_errors.insert(move_out_indices, place_and_err) @@ -2508,12 +2508,12 @@ mod diags { } } - pub fn get_buffered_mut_error(&mut self, span: Span) -> Option<(Diag<'tcx>, usize)> { + pub fn get_buffered_mut_error(&mut self, span: Span) -> Option<(Diag<'infcx>, usize)> { // FIXME(#120456) - is `swap_remove` correct? self.diags.buffered_mut_errors.swap_remove(&span) } - pub fn buffer_mut_error(&mut self, span: Span, diag: Diag<'tcx>, count: usize) { + pub fn buffer_mut_error(&mut self, span: Span, diag: Diag<'infcx>, count: usize) { self.diags.buffered_mut_errors.insert(span, (diag, count)); } @@ -2554,7 +2554,7 @@ mod diags { pub fn has_move_error( &self, move_out_indices: &[MoveOutIndex], - ) -> Option<&(PlaceRef<'tcx>, Diag<'tcx>)> { + ) -> Option<&(PlaceRef<'tcx>, Diag<'infcx>)> { self.diags.buffered_move_errors.get(move_out_indices) } } diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 923cf7e940573..2ffa9ba5b4d32 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -81,7 +81,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>( promoted: &IndexSlice>, location_table: &LocationTable, param_env: ty::ParamEnv<'tcx>, - flow_inits: &mut ResultsCursor<'cx, 'tcx, MaybeInitializedPlaces<'cx, 'tcx>>, + flow_inits: &mut ResultsCursor<'cx, 'tcx, MaybeInitializedPlaces<'_, 'cx, 'tcx>>, move_data: &MoveData<'tcx>, borrow_set: &BorrowSet<'tcx>, upvars: &[&ty::CapturedPlace<'tcx>], @@ -262,13 +262,13 @@ pub(super) fn dump_mir_results<'tcx>( #[allow(rustc::diagnostic_outside_of_impl)] #[allow(rustc::untranslatable_diagnostic)] -pub(super) fn dump_annotation<'tcx>( - infcx: &BorrowckInferCtxt<'tcx>, +pub(super) fn dump_annotation<'tcx, 'cx>( + infcx: &'cx BorrowckInferCtxt<'tcx>, body: &Body<'tcx>, regioncx: &RegionInferenceContext<'tcx>, closure_region_requirements: &Option>, opaque_type_values: &FxIndexMap>, - diags: &mut crate::diags::BorrowckDiags<'tcx>, + diags: &mut crate::diags::BorrowckDiags<'cx, 'tcx>, ) { let tcx = infcx.tcx; let base_def_id = tcx.typeck_root_def_id(body.source.def_id()); @@ -285,7 +285,7 @@ pub(super) fn dump_annotation<'tcx>( let def_span = tcx.def_span(body.source.def_id()); let mut err = if let Some(closure_region_requirements) = closure_region_requirements { - let mut err = tcx.dcx().struct_span_note(def_span, "external requirements"); + let mut err = infcx.dcx().struct_span_note(def_span, "external requirements"); regioncx.annotate(tcx, &mut err); @@ -304,7 +304,7 @@ pub(super) fn dump_annotation<'tcx>( err } else { - let mut err = tcx.dcx().struct_span_note(def_span, "no external requirements"); + let mut err = infcx.dcx().struct_span_note(def_span, "no external requirements"); regioncx.annotate(tcx, &mut err); err diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 67e5c8352df0f..e195ceded1bf3 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -285,7 +285,7 @@ impl<'tcx> InferCtxt<'tcx> { } if let Err(guar) = - check_opaque_type_parameter_valid(self.tcx, opaque_type_key, instantiated_ty.span) + check_opaque_type_parameter_valid(self, opaque_type_key, instantiated_ty.span) { return Ty::new_error(self.tcx, guar); } @@ -294,6 +294,10 @@ impl<'tcx> InferCtxt<'tcx> { .remap_generic_params_to_declaration_params(opaque_type_key, self.tcx, false) .ty; + if let Err(e) = definition_ty.error_reported() { + return Ty::new_error(self.tcx, e); + } + // `definition_ty` does not live in of the current inference context, // so lets make sure that we don't accidentally misuse our current `infcx`. match check_opaque_type_well_formed( @@ -387,10 +391,11 @@ fn check_opaque_type_well_formed<'tcx>( /// [rustc-dev-guide chapter]: /// https://rustc-dev-guide.rust-lang.org/opaque-types-region-infer-restrictions.html fn check_opaque_type_parameter_valid<'tcx>( - tcx: TyCtxt<'tcx>, + infcx: &InferCtxt<'tcx>, opaque_type_key: OpaqueTypeKey<'tcx>, span: Span, ) -> Result<(), ErrorGuaranteed> { + let tcx = infcx.tcx; let opaque_generics = tcx.generics_of(opaque_type_key.def_id); let opaque_env = LazyOpaqueTyEnv::new(tcx, opaque_type_key.def_id); let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default(); @@ -420,7 +425,7 @@ fn check_opaque_type_parameter_valid<'tcx>( opaque_env.param_is_error(i)?; - return Err(tcx.dcx().emit_err(NonGenericOpaqueTypeParam { + return Err(infcx.dcx().emit_err(NonGenericOpaqueTypeParam { ty: arg, kind, span, @@ -438,7 +443,7 @@ fn check_opaque_type_parameter_valid<'tcx>( .collect(); #[allow(rustc::diagnostic_outside_of_impl)] #[allow(rustc::untranslatable_diagnostic)] - return Err(tcx + return Err(infcx .dcx() .struct_span_err(span, "non-defining opaque type use in defining scope") .with_span_note(spans, format!("{descr} used multiple times")) diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index b777e01f7a6c2..6d6425b5f19f0 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -34,7 +34,7 @@ pub(super) fn generate<'mir, 'tcx>( typeck: &mut TypeChecker<'_, 'tcx>, body: &Body<'tcx>, elements: &Rc, - flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>, + flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'_, 'mir, 'tcx>>, move_data: &MoveData<'tcx>, ) { debug!("liveness::generate"); diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index 359c4ea0eb1e2..eb86c8d06f113 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -43,7 +43,7 @@ pub(super) fn trace<'mir, 'tcx>( typeck: &mut TypeChecker<'_, 'tcx>, body: &Body<'tcx>, elements: &Rc, - flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>, + flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'_, 'mir, 'tcx>>, move_data: &MoveData<'tcx>, relevant_live_locals: Vec, boring_locals: Vec, @@ -101,7 +101,7 @@ pub(super) fn trace<'mir, 'tcx>( } /// Contextual state for the type-liveness coroutine. -struct LivenessContext<'me, 'typeck, 'flow, 'tcx> { +struct LivenessContext<'a, 'me, 'typeck, 'flow, 'tcx> { /// Current type-checker, giving us our inference context etc. typeck: &'me mut TypeChecker<'typeck, 'tcx>, @@ -119,7 +119,7 @@ struct LivenessContext<'me, 'typeck, 'flow, 'tcx> { /// Results of dataflow tracking which variables (and paths) have been /// initialized. - flow_inits: &'me mut ResultsCursor<'flow, 'tcx, MaybeInitializedPlaces<'flow, 'tcx>>, + flow_inits: &'me mut ResultsCursor<'flow, 'tcx, MaybeInitializedPlaces<'a, 'flow, 'tcx>>, /// Index indicating where each variable is assigned, used, or /// dropped. @@ -131,8 +131,8 @@ struct DropData<'tcx> { region_constraint_data: Option<&'tcx QueryRegionConstraints<'tcx>>, } -struct LivenessResults<'me, 'typeck, 'flow, 'tcx> { - cx: LivenessContext<'me, 'typeck, 'flow, 'tcx>, +struct LivenessResults<'a, 'me, 'typeck, 'flow, 'tcx> { + cx: LivenessContext<'a, 'me, 'typeck, 'flow, 'tcx>, /// Set of points that define the current local. defs: BitSet, @@ -153,8 +153,8 @@ struct LivenessResults<'me, 'typeck, 'flow, 'tcx> { stack: Vec, } -impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> { - fn new(cx: LivenessContext<'me, 'typeck, 'flow, 'tcx>) -> Self { +impl<'a, 'me, 'typeck, 'flow, 'tcx> LivenessResults<'a, 'me, 'typeck, 'flow, 'tcx> { + fn new(cx: LivenessContext<'a, 'me, 'typeck, 'flow, 'tcx>) -> Self { let num_points = cx.elements.num_points(); LivenessResults { cx, @@ -507,7 +507,7 @@ impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> { } } -impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { +impl<'tcx> LivenessContext<'_, '_, '_, '_, 'tcx> { /// Returns `true` if the local variable (or some part of it) is initialized at the current /// cursor position. Callers should call one of the `seek` methods immediately before to point /// the cursor to the desired location. diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 81bde14a82f4e..aa25e3adf28af 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -129,7 +129,7 @@ pub(crate) fn type_check<'mir, 'tcx>( location_table: &LocationTable, borrow_set: &BorrowSet<'tcx>, all_facts: &mut Option, - flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>, + flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'_, 'mir, 'tcx>>, move_data: &MoveData<'tcx>, elements: &Rc, upvars: &[&ty::CapturedPlace<'tcx>], diff --git a/compiler/rustc_borrowck/src/used_muts.rs b/compiler/rustc_borrowck/src/used_muts.rs index 25e1f6268e062..e2de6b8b4a929 100644 --- a/compiler/rustc_borrowck/src/used_muts.rs +++ b/compiler/rustc_borrowck/src/used_muts.rs @@ -45,10 +45,10 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { /// MIR visitor for collecting used mutable variables. /// The 'visit lifetime represents the duration of the MIR walk. -struct GatherUsedMutsVisitor<'visit, 'a, 'mir, 'cx, 'tcx> { +struct GatherUsedMutsVisitor<'visit, 'a, 'mir, 'infcx, 'tcx> { temporary_used_locals: FxIndexSet, never_initialized_mut_locals: &'visit mut FxIndexSet, - mbcx: &'visit mut MirBorrowckCtxt<'a, 'mir, 'cx, 'tcx>, + mbcx: &'visit mut MirBorrowckCtxt<'a, 'mir, 'infcx, 'tcx>, } impl GatherUsedMutsVisitor<'_, '_, '_, '_, '_> { diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml b/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml index b7063f35a3e80..1ed6f8fc359db 100644 --- a/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml +++ b/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml @@ -55,10 +55,6 @@ jobs: if: matrix.os == 'macos-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-apple-darwin' run: rustup set default-host x86_64-apple-darwin - - name: Select XCode version - if: matrix.os == 'macos-latest' - run: sudo xcode-select -s /Applications/Xcode_14.3.1.app - - name: Prepare dependencies run: ./y.sh prepare diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml index 1f5a6513f63b1..a2ae3d63fb907 100644 --- a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml +++ b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml @@ -66,6 +66,9 @@ jobs: env: TARGET_TRIPLE: aarch64-unknown-linux-gnu apt_deps: gcc-aarch64-linux-gnu qemu-user + - os: macos-latest + env: + TARGET_TRIPLE: aarch64-apple-darwin - os: ubuntu-latest env: TARGET_TRIPLE: s390x-unknown-linux-gnu @@ -108,10 +111,6 @@ jobs: sudo apt-get update sudo apt-get install -y ${{ matrix.apt_deps }} - - name: Select XCode version - if: matrix.os == 'macos-latest' - run: sudo xcode-select -s /Applications/Xcode_14.3.1.app - - name: Prepare dependencies run: ./y.sh prepare @@ -214,6 +213,9 @@ jobs: - os: macos-latest env: TARGET_TRIPLE: x86_64-apple-darwin + - os: macos-latest + env: + TARGET_TRIPLE: aarch64-apple-darwin # cross-compile from Linux to Windows using mingw - os: ubuntu-latest env: @@ -248,10 +250,6 @@ jobs: sudo apt-get update sudo apt-get install -y gcc-mingw-w64-x86-64 - - name: Select XCode version - if: matrix.os == 'macos-latest' - run: sudo xcode-select -s /Applications/Xcode_14.3.1.app - - name: Prepare dependencies run: ./y.sh prepare @@ -282,7 +280,8 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 if: ${{ github.ref == 'refs/heads/master' }} - needs: [rustfmt, test, bench, dist] + # FIXME add the bench job back to the dependency list once rust-lang/rust#125493 gets merged + needs: [rustfmt, test, dist] permissions: contents: write # for creating the dev tag and release diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock index 33fe52ddbdd64..15c9e9d66fac2 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/Cargo.lock @@ -46,18 +46,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" -version = "0.107.0" +version = "0.109.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79b27922a6879b5b5361d0a084cb0b1941bf109a98540addcb932da13b68bed4" +checksum = "0b6b33d7e757a887989eb18b35712b2a67d96171ec3149d1bfb657b29b7b367c" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.107.0" +version = "0.109.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "304c455b28bf56372729acb356afbb55d622f2b0f2f7837aa5e57c138acaac4d" +checksum = "b9acf15cb22be42d07c3b57d7856329cb228b7315d385346149df2566ad5e4aa" dependencies = [ "bumpalo", "cranelift-bforest", @@ -70,45 +70,46 @@ dependencies = [ "hashbrown 0.14.3", "log", "regalloc2", + "rustc-hash", "smallvec", "target-lexicon", ] [[package]] name = "cranelift-codegen-meta" -version = "0.107.0" +version = "0.109.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1653c56b99591d07f67c5ca7f9f25888948af3f4b97186bff838d687d666f613" +checksum = "e934d301392b73b3f8b0540391fb82465a0f179a3cee7c726482ac4727efcc97" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.107.0" +version = "0.109.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5b6a9cf6b6eb820ee3f973a0db313c05dc12d370f37b4fe9630286e1672573f" +checksum = "8afb2a2566b3d54b854dfb288b3b187f6d3d17d6f762c92898207eba302931da" [[package]] name = "cranelift-control" -version = "0.107.0" +version = "0.109.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9d06e6bf30075fb6bed9e034ec046475093392eea1aff90eb5c44c4a033d19a" +checksum = "0100f33b704cdacd01ad66ff41f8c5030d57cbff078e2a4e49ab1822591299fa" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.107.0" +version = "0.109.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29be04f931b73cdb9694874a295027471817f26f26d2f0ebe5454153176b6e3a" +checksum = "a8cfdc315e5d18997093e040a8d234bea1ac1e118a716d3e30f40d449e78207b" [[package]] name = "cranelift-frontend" -version = "0.107.0" +version = "0.109.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a07fd7393041d7faa2f37426f5dc7fc04003b70988810e8c063beefeff1cd8f9" +checksum = "0f74b84f16af2e982b0c0c72233503d9d55cbfe3865dbe807ca28dc6642a28b5" dependencies = [ "cranelift-codegen", "log", @@ -118,15 +119,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.107.0" +version = "0.109.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f341d7938caa6dff8149dac05bb2b53fc680323826b83b4cf175ab9f5139a3c9" +checksum = "adf306d3dde705fb94bd48082f01d38c4ededc74293a4c007805f610bf08bc6e" [[package]] name = "cranelift-jit" -version = "0.107.0" +version = "0.109.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42733555e06433f1461570e09dbd756dafc228b4dac75c597cdbdc518de07522" +checksum = "f5c5cfb8bbd3339cd25cca30e7516ff8fe5cb1feeddde6980cc4d5ef34df97bb" dependencies = [ "anyhow", "cranelift-codegen", @@ -144,9 +145,9 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.107.0" +version = "0.109.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84950af02bb85f3da764d53a953b43bb29a732e793d4fe24637a61591be9a024" +checksum = "7c9b0d4269b36fd858e6d8f20cd4938941186fb831488c361888cb2d6b33a9a6" dependencies = [ "anyhow", "cranelift-codegen", @@ -155,9 +156,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.107.0" +version = "0.109.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82af6066e6448d26eeabb7aa26a43f7ff79f8217b06bade4ee6ef230aecc8880" +checksum = "1ea0ebdef7aff4a79bcbc8b6495f31315f16b3bf311152f472eaa8d679352581" dependencies = [ "cranelift-codegen", "libc", @@ -166,9 +167,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.107.0" +version = "0.109.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00af56107039ed150391df6f753298c7b08f2b6a2e0727d216b5fa599d684d8b" +checksum = "19e33439ec20db058bc7cc3410f9748ab1ad90a35cef713d625c736f43e3820d" dependencies = [ "anyhow", "cranelift-codegen", @@ -278,9 +279,9 @@ checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "object" -version = "0.33.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8dd6c0cdf9429bce006e1362bfce61fa1bfd8c898a643ed8d2b471934701d3d" +checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" dependencies = [ "crc32fast", "hashbrown 0.14.3", @@ -410,10 +411,11 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wasmtime-jit-icache-coherence" -version = "20.0.0" +version = "22.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a9f93a3289057b26dc75eb84d6e60d7694f7d169c7c09597495de6e016a13ff" +checksum = "5afe2f0499542f9a4bcfa1b55bfdda803b6ade4e7c93c6b99e0f39dba44b0a91" dependencies = [ + "anyhow", "cfg-if", "libc", "windows-sys", diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml index 2015cdbcc2a74..2969a6cf6ecaa 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.toml +++ b/compiler/rustc_codegen_cranelift/Cargo.toml @@ -8,15 +8,15 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.107.0", default-features = false, features = ["std", "unwind", "all-arch"] } -cranelift-frontend = { version = "0.107.0" } -cranelift-module = { version = "0.107.0" } -cranelift-native = { version = "0.107.0" } -cranelift-jit = { version = "0.107.0", optional = true } -cranelift-object = { version = "0.107.0" } +cranelift-codegen = { version = "0.109.0", default-features = false, features = ["std", "unwind", "all-arch"] } +cranelift-frontend = { version = "0.109.0" } +cranelift-module = { version = "0.109.0" } +cranelift-native = { version = "0.109.0" } +cranelift-jit = { version = "0.109.0", optional = true } +cranelift-object = { version = "0.109.0" } target-lexicon = "0.12.0" gimli = { version = "0.28", default-features = false, features = ["write"]} -object = { version = "0.33", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } +object = { version = "0.36", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } indexmap = "2.0.0" libloading = { version = "0.8.0", optional = true } diff --git a/compiler/rustc_codegen_cranelift/Readme.md b/compiler/rustc_codegen_cranelift/Readme.md index 00ea15cb38cc2..eb21e027dd0e0 100644 --- a/compiler/rustc_codegen_cranelift/Readme.md +++ b/compiler/rustc_codegen_cranelift/Readme.md @@ -70,7 +70,7 @@ For more docs on how to build and test see [build_system/usage.txt](build_system |FreeBSD|✅[^no-rustup]|❓|❓|❓| |AIX|❌[^xcoff]|N/A|N/A|❌[^xcoff]| |Other unixes|❓|❓|❓|❓| -|macOS|✅|❌[^apple-silicon]|N/A|N/A| +|macOS|✅|✅[^no-rustup]|N/A|N/A| |Windows|✅[^no-rustup]|❌|N/A|N/A| ✅: Fully supported and tested @@ -80,7 +80,6 @@ For more docs on how to build and test see [build_system/usage.txt](build_system Not all targets are available as rustup component for nightly. See notes in the platform support matrix. [^xcoff]: XCOFF object file format is not supported. -[^apple-silicon]: Tracked in [#1248](https://github.com/rust-lang/rustc_codegen_cranelift/issues/1248). [^no-rustup]: Not available as rustup component for nightly. You can build it yourself. ## Usage diff --git a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs index 196ff8fda7544..dfbe0f51e7be2 100644 --- a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs +++ b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs @@ -267,10 +267,6 @@ fn build_clif_sysroot_for_triple( prefix.to_str().unwrap() )); } - rustflags.push("-Zunstable-options".to_owned()); - for (name, values) in EXTRA_CHECK_CFGS { - rustflags.push(check_cfg_arg(name, *values)); - } compiler.rustflags.extend(rustflags); let mut build_cmd = STANDARD_LIBRARY.build(&compiler, dirs); if channel == "release" { @@ -330,34 +326,3 @@ fn build_rtstartup(dirs: &Dirs, compiler: &Compiler) -> Option { Some(target_libs) } - -// Copied from https://github.com/rust-lang/rust/blob/4fd98a4b1b100f5329c6efae18031791f64372d2/src/bootstrap/src/utils/helpers.rs#L569-L585 -/// Create a `--check-cfg` argument invocation for a given name -/// and it's values. -fn check_cfg_arg(name: &str, values: Option<&[&str]>) -> String { - // Creating a string of the values by concatenating each value: - // ',values("tvos","watchos")' or '' (nothing) when there are no values. - let next = match values { - Some(values) => { - let mut tmp = values.iter().flat_map(|val| [",", "\"", val, "\""]).collect::(); - - tmp.insert_str(1, "values("); - tmp.push(')'); - tmp - } - None => "".to_string(), - }; - format!("--check-cfg=cfg({name}{next})") -} - -const EXTRA_CHECK_CFGS: &[(&str, Option<&[&str]>)] = &[ - ("bootstrap", None), - ("stdarch_intel_sde", None), - ("no_fp_fmt_parse", None), - ("no_global_oom_handling", None), - ("no_rc", None), - ("no_sync", None), - ("netbsd10", None), - ("backtrace_in_libstd", None), - ("target_arch", Some(&["xtensa"])), -]; diff --git a/compiler/rustc_codegen_cranelift/build_system/tests.rs b/compiler/rustc_codegen_cranelift/build_system/tests.rs index 278f334796a9b..790d9cbd9fc59 100644 --- a/compiler/rustc_codegen_cranelift/build_system/tests.rs +++ b/compiler/rustc_codegen_cranelift/build_system/tests.rs @@ -329,7 +329,6 @@ pub(crate) fn run_tests( struct TestRunner<'a> { is_native: bool, jit_supported: bool, - use_unstable_features: bool, skip_tests: &'a [&'a str], dirs: Dirs, target_compiler: Compiler, @@ -361,15 +360,7 @@ impl<'a> TestRunner<'a> { && target_compiler.triple.contains("x86_64") && !target_compiler.triple.contains("windows"); - Self { - is_native, - jit_supported, - use_unstable_features, - skip_tests, - dirs, - target_compiler, - stdlib_source, - } + Self { is_native, jit_supported, skip_tests, dirs, target_compiler, stdlib_source } } fn run_testsuite(&self, tests: &[TestCase]) { @@ -393,31 +384,13 @@ impl<'a> TestRunner<'a> { match *cmd { TestCaseCmd::Custom { func } => func(self), TestCaseCmd::BuildLib { source, crate_types } => { - if self.use_unstable_features { - self.run_rustc([source, "--crate-type", crate_types]); - } else { - self.run_rustc([ - source, - "--crate-type", - crate_types, - "--cfg", - "no_unstable_features", - ]); - } + self.run_rustc([source, "--crate-type", crate_types]); } TestCaseCmd::BuildBin { source } => { - if self.use_unstable_features { - self.run_rustc([source]); - } else { - self.run_rustc([source, "--cfg", "no_unstable_features"]); - } + self.run_rustc([source]); } TestCaseCmd::BuildBinAndRun { source, args } => { - if self.use_unstable_features { - self.run_rustc([source]); - } else { - self.run_rustc([source, "--cfg", "no_unstable_features"]); - } + self.run_rustc([source]); self.run_out_command( source.split('/').last().unwrap().split('.').next().unwrap(), args, @@ -472,7 +445,6 @@ impl<'a> TestRunner<'a> { cmd.arg(&self.target_compiler.triple); cmd.arg("-Cpanic=abort"); cmd.arg("-Zunstable-options"); - cmd.arg("--check-cfg=cfg(no_unstable_features)"); cmd.arg("--check-cfg=cfg(jit)"); cmd.args(args); cmd diff --git a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs index aab20f672487b..7d361a9ab2bb6 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs @@ -333,12 +333,7 @@ fn main() { #[cfg(all(not(jit), not(all(windows, target_env = "gnu"))))] test_tls(); - #[cfg(all( - not(jit), - not(no_unstable_features), - target_arch = "x86_64", - any(target_os = "linux", target_os = "macos") - ))] + #[cfg(all(not(jit), target_arch = "x86_64", any(target_os = "linux", target_os = "macos")))] unsafe { global_asm_test(); naked_test(); @@ -367,17 +362,12 @@ fn stack_val_align() { assert_eq!(&a as *const Foo as usize % 8192, 0); } -#[cfg(all( - not(jit), - not(no_unstable_features), - target_arch = "x86_64", - any(target_os = "linux", target_os = "macos") -))] +#[cfg(all(not(jit), target_arch = "x86_64", any(target_os = "linux", target_os = "macos")))] extern "C" { fn global_asm_test(); } -#[cfg(all(not(jit), not(no_unstable_features), target_arch = "x86_64", target_os = "linux"))] +#[cfg(all(not(jit), target_arch = "x86_64", target_os = "linux"))] global_asm! { " .global global_asm_test @@ -387,7 +377,7 @@ global_asm! { " } -#[cfg(all(not(jit), not(no_unstable_features), target_arch = "x86_64", target_os = "macos"))] +#[cfg(all(not(jit), target_arch = "x86_64", target_os = "macos"))] global_asm! { " .global _global_asm_test @@ -397,7 +387,7 @@ global_asm! { " } -#[cfg(all(not(jit), not(no_unstable_features), target_arch = "x86_64"))] +#[cfg(all(not(jit), target_arch = "x86_64"))] #[naked] extern "C" fn naked_test() { unsafe { diff --git a/compiler/rustc_codegen_cranelift/example/std_example.rs b/compiler/rustc_codegen_cranelift/example/std_example.rs index 7347b2e77899f..6cedd84adfe52 100644 --- a/compiler/rustc_codegen_cranelift/example/std_example.rs +++ b/compiler/rustc_codegen_cranelift/example/std_example.rs @@ -251,6 +251,9 @@ unsafe fn test_simd() { test_mm_add_epi8(); test_mm_add_pd(); test_mm_cvtepi8_epi16(); + #[cfg(not(jit))] + test_mm_cvtps_epi32(); + test_mm_cvttps_epi32(); test_mm_cvtsi128_si64(); test_mm_extract_epi8(); @@ -476,6 +479,41 @@ unsafe fn test_mm256_permutevar8x32_epi32() { assert_eq_m256i(r, e); } +#[cfg(target_arch = "x86_64")] +#[target_feature(enable = "avx2")] +#[cfg(not(jit))] +unsafe fn test_mm_cvtps_epi32() { + let floats: [f32; 4] = [1.5, -2.5, i32::MAX as f32 + 1.0, f32::NAN]; + + let float_vec = _mm_loadu_ps(floats.as_ptr()); + let int_vec = _mm_cvtps_epi32(float_vec); + + let mut ints: [i32; 4] = [0; 4]; + _mm_storeu_si128(ints.as_mut_ptr() as *mut __m128i, int_vec); + + // this is very different from `floats.map(|f| f as i32)`! + let expected_ints: [i32; 4] = [2, -2, i32::MIN, i32::MIN]; + + assert_eq!(ints, expected_ints); +} + +#[cfg(target_arch = "x86_64")] +#[target_feature(enable = "avx2")] +unsafe fn test_mm_cvttps_epi32() { + let floats: [f32; 4] = [1.5, -2.5, i32::MAX as f32 + 1.0, f32::NAN]; + + let float_vec = _mm_loadu_ps(floats.as_ptr()); + let int_vec = _mm_cvttps_epi32(float_vec); + + let mut ints: [i32; 4] = [0; 4]; + _mm_storeu_si128(ints.as_mut_ptr() as *mut __m128i, int_vec); + + // this is very different from `floats.map(|f| f as i32)`! + let expected_ints: [i32; 4] = [1, -2, i32::MIN, i32::MIN]; + + assert_eq!(ints, expected_ints); +} + fn test_checked_mul() { let u: Option = u8::from_str_radix("1000", 10).ok(); assert_eq!(u, None); diff --git a/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml b/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml index c8c7b45bc9a6f..9ea53e8f848d9 100644 --- a/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml +++ b/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml @@ -4,12 +4,12 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" dependencies = [ "compiler_builtins", - "gimli", + "gimli 0.29.0", "rustc-std-workspace-alloc", "rustc-std-workspace-core", ] @@ -133,6 +133,17 @@ dependencies = [ "rustc-std-workspace-core", ] +[[package]] +name = "gimli" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +dependencies = [ + "compiler_builtins", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", +] + [[package]] name = "hashbrown" version = "0.14.3" @@ -147,9 +158,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.9" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" dependencies = [ "compiler_builtins", "rustc-std-workspace-alloc", @@ -189,9 +200,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.1" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" dependencies = [ "compiler_builtins", "memchr", @@ -286,9 +297,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" dependencies = [ "compiler_builtins", "rustc-std-workspace-core", @@ -396,8 +407,6 @@ dependencies = [ "core", "getopts", "libc", - "panic_abort", - "panic_unwind", "std", ] @@ -430,7 +439,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37a19a21a537f635c16c7576f22d0f2f7d63353c1337ad4ce0d8001c7952a25b" dependencies = [ "compiler_builtins", - "gimli", + "gimli 0.28.1", "rustc-std-workspace-core", ] diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain index a2ba79cbe9038..cfa91744a0e8d 100644 --- a/compiler/rustc_codegen_cranelift/rust-toolchain +++ b/compiler/rustc_codegen_cranelift/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2024-05-13" +channel = "nightly-2024-06-30" components = ["rust-src", "rustc-dev", "llvm-tools"] diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh index 689cda21643cb..c1b7e4b0e0768 100755 --- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh +++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh @@ -36,9 +36,8 @@ rm tests/ui/parser/unclosed-delimiter-in-dep.rs # submodule contains //~ERROR rm tests/ui/asm/x86_64/evex512-implicit-feature.rs # unimplemented AVX512 x86 vendor intrinsic # exotic linkages -rm tests/ui/issues/issue-33992.rs # unsupported linkages -rm tests/incremental/hashes/function_interfaces.rs # same -rm tests/incremental/hashes/statics.rs # same +rm tests/incremental/hashes/function_interfaces.rs +rm tests/incremental/hashes/statics.rs # variadic arguments rm tests/ui/abi/mir/mir_codegen_calls_variadic.rs # requires float varargs @@ -60,13 +59,20 @@ rm tests/ui/asm/x86_64/goto.rs # inline asm labels not supported # requires LTO rm -r tests/run-make/cdylib -rm -r tests/run-make/issue-14500 -rm -r tests/run-make/issue-64153 rm -r tests/run-make/codegen-options-parsing rm -r tests/run-make/lto-* rm -r tests/run-make/reproducible-build-2 rm -r tests/run-make/issue-109934-lto-debuginfo rm -r tests/run-make/no-builtins-lto +rm -r tests/run-make/reachable-extern-fn-available-lto + +# coverage instrumentation +rm tests/ui/consts/precise-drop-with-coverage.rs +rm tests/ui/issues/issue-85461.rs +rm -r tests/ui/instrument-coverage/ + +# missing f16/f128 support +rm tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs # optimization tests # ================== @@ -74,6 +80,7 @@ rm tests/ui/codegen/issue-28950.rs # depends on stack size optimizations rm tests/ui/codegen/init-large-type.rs # same rm tests/ui/issues/issue-40883.rs # same rm -r tests/run-make/fmt-write-bloat/ # tests an optimization +rm tests/ui/statics/const_generics.rs # same # backend specific tests # ====================== @@ -85,6 +92,7 @@ rm -r tests/run-make/sepcomp-cci-copies # same rm -r tests/run-make/volatile-intrinsics # same rm -r tests/run-make/llvm-ident # same rm -r tests/run-make/no-builtins-attribute # same +rm -r tests/run-make/pgo-gen-no-imp-symbols # same rm tests/ui/abi/stack-protector.rs # requires stack protector support rm -r tests/run-make/emit-stack-sizes # requires support for -Z emit-stack-sizes rm -r tests/run-make/optimization-remarks-dir # remarks are LLVM specific @@ -93,13 +101,14 @@ rm -r tests/run-make/print-to-output # requires --print relocation-models # requires asm, llvm-ir and/or llvm-bc emit support # ============================================= rm -r tests/run-make/emit-named-files -rm -r tests/run-make/issue-30063 rm -r tests/run-make/multiple-emits rm -r tests/run-make/output-type-permutations rm -r tests/run-make/emit-to-stdout rm -r tests/run-make/compressed-debuginfo rm -r tests/run-make/symbols-include-type-name - +rm -r tests/run-make/notify-all-emit-artifacts +rm -r tests/run-make/reset-codegen-1 +rm -r tests/run-make/inline-always-many-cgu # giving different but possibly correct results # ============================================= @@ -118,6 +127,7 @@ rm -r tests/run-make/compiler-builtins # Expects lib/rustlib/src/rust to contain # ============ rm -r tests/run-make/extern-fn-explicit-align # argument alignment not yet supported rm -r tests/run-make/panic-abort-eh_frame # .eh_frame emitted with panic=abort +rm tests/ui/deprecation/deprecated_inline_threshold.rs # missing deprecation warning for -Cinline-threshold # bugs in the test suite # ====================== @@ -148,12 +158,12 @@ index 9607ff02f96..b7d97caf9a2 100644 --- a/src/tools/run-make-support/src/rustdoc.rs +++ b/src/tools/run-make-support/src/rustdoc.rs @@ -34,8 +34,6 @@ pub fn bare() -> Self { - /// Construct a \`rustdoc\` invocation with \`-L \$(TARGET_RPATH_DIR)\` set. + #[track_caller] pub fn new() -> Self { let mut cmd = setup_common(); -- let target_rpath_dir = env::var_os("TARGET_RPATH_DIR").unwrap(); +- let target_rpath_dir = env_var_os("TARGET_RPATH_DIR"); - cmd.arg(format!("-L{}", target_rpath_dir.to_string_lossy())); - Self { cmd, stdin: None } + Self { cmd } } EOF diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 695dbaf2804b1..0d7eee7afb41e 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -5,8 +5,9 @@ mod pass_mode; mod returning; use std::borrow::Cow; +use std::mem; -use cranelift_codegen::ir::SigRef; +use cranelift_codegen::ir::{ArgumentPurpose, SigRef}; use cranelift_codegen::isa::CallConv; use cranelift_module::ModuleError; use rustc_codegen_ssa::errors::CompilerBuiltinsCannotCall; @@ -17,7 +18,7 @@ use rustc_middle::ty::TypeVisitableExt; use rustc_monomorphize::is_call_from_compiler_builtins_to_upstream_monomorphization; use rustc_session::Session; use rustc_span::source_map::Spanned; -use rustc_target::abi::call::{Conv, FnAbi}; +use rustc_target::abi::call::{Conv, FnAbi, PassMode}; use rustc_target::spec::abi::Abi; use self::pass_mode::*; @@ -487,6 +488,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( let args = args; assert_eq!(fn_abi.args.len(), args.len()); + #[derive(Copy, Clone)] enum CallTarget { Direct(FuncRef), Indirect(SigRef, Value), @@ -532,7 +534,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( }; self::returning::codegen_with_call_return_arg(fx, &fn_abi.ret, ret_place, |fx, return_ptr| { - let call_args = return_ptr + let mut call_args = return_ptr .into_iter() .chain(first_arg_override.into_iter()) .chain( @@ -545,47 +547,118 @@ pub(crate) fn codegen_terminator_call<'tcx>( ) .collect::>(); - let call_inst = match func_ref { + // FIXME: Find a cleaner way to support varargs. + if fn_abi.c_variadic { + adjust_call_for_c_variadic(fx, &fn_abi, source_info, func_ref, &mut call_args); + } + + match func_ref { CallTarget::Direct(func_ref) => fx.bcx.ins().call(func_ref, &call_args), CallTarget::Indirect(sig, func_ptr) => { fx.bcx.ins().call_indirect(sig, func_ptr, &call_args) } + } + }); + + if let Some(dest) = target { + let ret_block = fx.get_block(dest); + fx.bcx.ins().jump(ret_block, &[]); + } else { + fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + } + + fn adjust_call_for_c_variadic<'tcx>( + fx: &mut FunctionCx<'_, '_, 'tcx>, + fn_abi: &FnAbi<'tcx, Ty<'tcx>>, + source_info: mir::SourceInfo, + target: CallTarget, + call_args: &mut Vec, + ) { + if fn_abi.conv != Conv::C { + fx.tcx.dcx().span_fatal( + source_info.span, + format!("Variadic call for non-C abi {:?}", fn_abi.conv), + ); + } + let sig_ref = match target { + CallTarget::Direct(func_ref) => fx.bcx.func.dfg.ext_funcs[func_ref].signature, + CallTarget::Indirect(sig_ref, _) => sig_ref, }; + // `mem::take()` the `params` so that `fx.bcx` can be used below. + let mut abi_params = mem::take(&mut fx.bcx.func.dfg.signatures[sig_ref].params); + + // Recalculate the parameters in the signature to ensure the signature contains the variadic arguments. + let has_return_arg = matches!(fn_abi.ret.mode, PassMode::Indirect { .. }); + // Drop everything except the return argument (if there is one). + abi_params.truncate(if has_return_arg { 1 } else { 0 }); + // Add the fixed arguments. + abi_params.extend( + fn_abi.args[..fn_abi.fixed_count as usize] + .iter() + .flat_map(|arg_abi| arg_abi.get_abi_param(fx.tcx).into_iter()), + ); + let fixed_arg_count = abi_params.len(); + // Add the variadic arguments. + abi_params.extend( + fn_abi.args[fn_abi.fixed_count as usize..] + .iter() + .flat_map(|arg_abi| arg_abi.get_abi_param(fx.tcx).into_iter()), + ); - // FIXME find a cleaner way to support varargs - if fn_sig.c_variadic() { - if !matches!(fn_sig.abi(), Abi::C { .. }) { + if fx.tcx.sess.target.is_like_osx && fx.tcx.sess.target.arch == "aarch64" { + // Add any padding arguments needed for Apple AArch64. + // There's no need to pad the argument list unless variadic arguments are actually being + // passed. + if abi_params.len() > fixed_arg_count { + // 128-bit integers take 2 registers, and everything else takes 1. + // FIXME: Add support for non-integer types + // This relies on the checks below to ensure all arguments are integer types and + // that the ABI is "C". + // The return argument isn't counted as it goes in its own dedicated register. + let integer_registers_used: usize = abi_params + [if has_return_arg { 1 } else { 0 }..fixed_arg_count] + .iter() + .map(|arg| if arg.value_type.bits() == 128 { 2 } else { 1 }) + .sum(); + // The ABI uses 8 registers before it starts pushing arguments to the stack. Pad out + // the registers if needed to ensure the variadic arguments are passed on the stack. + if integer_registers_used < 8 { + abi_params.splice( + fixed_arg_count..fixed_arg_count, + (integer_registers_used..8).map(|_| AbiParam::new(types::I64)), + ); + call_args.splice( + fixed_arg_count..fixed_arg_count, + (integer_registers_used..8).map(|_| fx.bcx.ins().iconst(types::I64, 0)), + ); + } + } + + // `StructArgument` is not currently used by the `aarch64` ABI, and is therefore not + // handled when calculating how many padding arguments to use. Assert that this remains + // the case. + assert!(abi_params.iter().all(|param| matches!( + param.purpose, + // The only purposes used are `Normal` and `StructReturn`. + ArgumentPurpose::Normal | ArgumentPurpose::StructReturn + ))); + } + + // Check all parameters are integers. + for param in abi_params.iter() { + if !param.value_type.is_int() { + // FIXME: Set %al to upperbound on float args once floats are supported. fx.tcx.dcx().span_fatal( source_info.span, - format!("Variadic call for non-C abi {:?}", fn_sig.abi()), + format!("Non int ty {:?} for variadic call", param.value_type), ); } - let sig_ref = fx.bcx.func.dfg.call_signature(call_inst).unwrap(); - let abi_params = call_args - .into_iter() - .map(|arg| { - let ty = fx.bcx.func.dfg.value_type(arg); - if !ty.is_int() { - // FIXME set %al to upperbound on float args once floats are supported - fx.tcx.dcx().span_fatal( - source_info.span, - format!("Non int ty {:?} for variadic call", ty), - ); - } - AbiParam::new(ty) - }) - .collect::>(); - fx.bcx.func.dfg.signatures[sig_ref].params = abi_params; } - call_inst - }); + assert_eq!(abi_params.len(), call_args.len()); - if let Some(dest) = target { - let ret_block = fx.get_block(dest); - fx.bcx.ins().jump(ret_block, &[]); - } else { - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + // Put the `AbiParam`s back in the signature. + fx.bcx.func.dfg.signatures[sig_ref].params = abi_params; } } diff --git a/compiler/rustc_codegen_cranelift/src/allocator.rs b/compiler/rustc_codegen_cranelift/src/allocator.rs index e8af3e8c2555f..b4a3825e9965f 100644 --- a/compiler/rustc_codegen_cranelift/src/allocator.rs +++ b/compiler/rustc_codegen_cranelift/src/allocator.rs @@ -11,15 +11,10 @@ use rustc_session::config::OomStrategy; use crate::prelude::*; /// Returns whether an allocator shim was created -pub(crate) fn codegen( - tcx: TyCtxt<'_>, - module: &mut impl Module, - unwind_context: &mut UnwindContext, -) -> bool { +pub(crate) fn codegen(tcx: TyCtxt<'_>, module: &mut dyn Module) -> bool { let Some(kind) = allocator_kind_for_codegen(tcx) else { return false }; codegen_inner( module, - unwind_context, kind, tcx.alloc_error_handler_kind(()).unwrap(), tcx.sess.opts.unstable_opts.oom, @@ -28,8 +23,7 @@ pub(crate) fn codegen( } fn codegen_inner( - module: &mut impl Module, - unwind_context: &mut UnwindContext, + module: &mut dyn Module, kind: AllocatorKind, alloc_error_handler_kind: AllocatorKind, oom_strategy: OomStrategy, @@ -67,7 +61,6 @@ fn codegen_inner( }; crate::common::create_wrapper_function( module, - unwind_context, sig, &global_fn_name(method.name), &default_fn_name(method.name), @@ -82,7 +75,6 @@ fn codegen_inner( }; crate::common::create_wrapper_function( module, - unwind_context, sig, "__rust_alloc_error_handler", &alloc_error_handler_name(alloc_error_handler_kind), diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index b117dc496c2bb..c5b4277015a9e 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -249,9 +249,7 @@ pub(crate) fn compile_fn( } // Define debuginfo for function - let isa = module.isa(); let debug_context = &mut cx.debug_context; - let unwind_context = &mut cx.unwind_context; cx.profiler.generic_activity("generate debug info").run(|| { if let Some(debug_context) = debug_context { codegened_func.func_debug_cx.unwrap().finalize( @@ -260,7 +258,6 @@ pub(crate) fn compile_fn( context, ); } - unwind_context.add_function(codegened_func.func_id, &context, isa); }); } @@ -909,7 +906,7 @@ fn codegen_stmt<'tcx>( | StatementKind::PlaceMention(..) | StatementKind::AscribeUserType(..) => {} - StatementKind::Coverage { .. } => fx.tcx.dcx().fatal("-Zcoverage is unimplemented"), + StatementKind::Coverage { .. } => unreachable!(), StatementKind::Intrinsic(ref intrinsic) => match &**intrinsic { // We ignore `assume` intrinsics, they are only useful for optimizations NonDivergingIntrinsic::Assume(_) => {} diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index 21d0cd2d30f2a..0931713993691 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -247,7 +247,6 @@ pub(crate) fn type_sign(ty: Ty<'_>) -> bool { pub(crate) fn create_wrapper_function( module: &mut dyn Module, - unwind_context: &mut UnwindContext, sig: Signature, wrapper_name: &str, callee_name: &str, @@ -280,7 +279,6 @@ pub(crate) fn create_wrapper_function( bcx.finalize(); } module.define_function(wrapper_func_id, &mut ctx).unwrap(); - unwind_context.add_function(wrapper_func_id, &ctx, module.isa()); } pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> { @@ -395,6 +393,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { // FIXME Don't force the size to a multiple of bytes once Cranelift gets // a way to specify stack slot alignment. size: (size + abi_align - 1) / abi_align * abi_align, + align_shift: 4, }); Pointer::stack_slot(stack_slot) } else { @@ -405,6 +404,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { // FIXME Don't force the size to a multiple of bytes once Cranelift gets // a way to specify stack slot alignment. size: (size + align) / abi_align * abi_align, + align_shift: 4, }); let base_ptr = self.bcx.ins().stack_addr(self.pointer_type, stack_slot, 0); let misalign_offset = self.bcx.ins().urem_imm(base_ptr, i64::from(align)); diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index dcafac21bc742..763d9a484077e 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -26,6 +26,7 @@ use rustc_session::Session; use crate::concurrency_limiter::{ConcurrencyLimiter, ConcurrencyLimiterToken}; use crate::debuginfo::TypeDebugContext; use crate::global_asm::GlobalAsmConfig; +use crate::unwind_module::UnwindModule; use crate::{prelude::*, BackendConfig}; struct ModuleCodegenResult { @@ -318,7 +319,11 @@ fn produce_final_output_artifacts( // These are used in linking steps and will be cleaned up afterward. } -fn make_module(sess: &Session, backend_config: &BackendConfig, name: String) -> ObjectModule { +fn make_module( + sess: &Session, + backend_config: &BackendConfig, + name: String, +) -> UnwindModule { let isa = crate::build_isa(sess, backend_config); let mut builder = @@ -327,16 +332,15 @@ fn make_module(sess: &Session, backend_config: &BackendConfig, name: String) -> // is important, while cg_clif cares more about compilation times. Enabling -Zfunction-sections // can easily double the amount of time necessary to perform linking. builder.per_function_section(sess.opts.unstable_opts.function_sections.unwrap_or(false)); - ObjectModule::new(builder) + UnwindModule::new(ObjectModule::new(builder), true) } fn emit_cgu( output_filenames: &OutputFilenames, prof: &SelfProfilerRef, name: String, - module: ObjectModule, + module: UnwindModule, debug: Option, - unwind_context: UnwindContext, global_asm_object_file: Option, producer: &str, ) -> Result { @@ -346,8 +350,6 @@ fn emit_cgu( debug.emit(&mut product); } - unwind_context.emit(&mut product); - let module_regular = emit_module( output_filenames, prof, @@ -494,7 +496,6 @@ fn module_codegen( let mut cx = crate::CodegenCx::new( tcx, - backend_config.clone(), module.isa(), tcx.sess.opts.debuginfo != DebugInfo::None, cgu_name, @@ -531,13 +532,7 @@ fn module_codegen( } } } - crate::main_shim::maybe_create_entry_wrapper( - tcx, - &mut module, - &mut cx.unwind_context, - false, - cgu.is_primary(), - ); + crate::main_shim::maybe_create_entry_wrapper(tcx, &mut module, false, cgu.is_primary()); let cgu_name = cgu.name().as_str().to_owned(); @@ -571,7 +566,6 @@ fn module_codegen( cgu_name, module, cx.debug_context, - cx.unwind_context, global_asm_object_file, &producer, ) @@ -665,13 +659,10 @@ pub(crate) fn run_aot( }); let mut allocator_module = make_module(tcx.sess, &backend_config, "allocator_shim".to_string()); - let mut allocator_unwind_context = UnwindContext::new(allocator_module.isa(), true); - let created_alloc_shim = - crate::allocator::codegen(tcx, &mut allocator_module, &mut allocator_unwind_context); + let created_alloc_shim = crate::allocator::codegen(tcx, &mut allocator_module); let allocator_module = if created_alloc_shim { - let mut product = allocator_module.finish(); - allocator_unwind_context.emit(&mut product); + let product = allocator_module.finish(); match emit_module( tcx.output_filenames(()), diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs index 4b149131b61aa..dfee8e714e64a 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs @@ -14,12 +14,12 @@ use rustc_session::Session; use rustc_span::Symbol; use crate::debuginfo::TypeDebugContext; +use crate::unwind_module::UnwindModule; use crate::{prelude::*, BackendConfig}; use crate::{CodegenCx, CodegenMode}; struct JitState { - backend_config: BackendConfig, - jit_module: JITModule, + jit_module: UnwindModule, } thread_local! { @@ -63,7 +63,7 @@ fn create_jit_module( tcx: TyCtxt<'_>, backend_config: &BackendConfig, hotswap: bool, -) -> (JITModule, CodegenCx) { +) -> (UnwindModule, CodegenCx) { let crate_info = CrateInfo::new(tcx, "dummy_target_cpu".to_string()); let isa = crate::build_isa(tcx.sess, backend_config); @@ -72,17 +72,11 @@ fn create_jit_module( crate::compiler_builtins::register_functions_for_jit(&mut jit_builder); jit_builder.symbol_lookup_fn(dep_symbol_lookup_fn(tcx.sess, crate_info)); jit_builder.symbol("__clif_jit_fn", clif_jit_fn as *const u8); - let mut jit_module = JITModule::new(jit_builder); + let mut jit_module = UnwindModule::new(JITModule::new(jit_builder), false); - let mut cx = crate::CodegenCx::new( - tcx, - backend_config.clone(), - jit_module.isa(), - false, - Symbol::intern("dummy_cgu_name"), - ); + let cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, Symbol::intern("dummy_cgu_name")); - crate::allocator::codegen(tcx, &mut jit_module, &mut cx.unwind_context); + crate::allocator::codegen(tcx, &mut jit_module); (jit_module, cx) } @@ -128,7 +122,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { ); } CodegenMode::JitLazy => { - codegen_shim(tcx, &mut cx, &mut cached_context, &mut jit_module, inst) + codegen_shim(tcx, &mut cached_context, &mut jit_module, inst) } }, MonoItem::Static(def_id) => { @@ -146,18 +140,11 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { tcx.dcx().fatal("Inline asm is not supported in JIT mode"); } - crate::main_shim::maybe_create_entry_wrapper( - tcx, - &mut jit_module, - &mut cx.unwind_context, - true, - true, - ); + crate::main_shim::maybe_create_entry_wrapper(tcx, &mut jit_module, true, true); tcx.dcx().abort_if_errors(); - jit_module.finalize_definitions().unwrap(); - unsafe { cx.unwind_context.register_jit(&jit_module) }; + jit_module.finalize_definitions(); println!( "Rustc codegen cranelift will JIT run the executable, because -Cllvm-args=mode=jit was passed" @@ -177,12 +164,12 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { call_conv: jit_module.target_config().default_call_conv, }; let start_func_id = jit_module.declare_function("main", Linkage::Import, &start_sig).unwrap(); - let finalized_start: *const u8 = jit_module.get_finalized_function(start_func_id); + let finalized_start: *const u8 = jit_module.module.get_finalized_function(start_func_id); LAZY_JIT_STATE.with(|lazy_jit_state| { let mut lazy_jit_state = lazy_jit_state.borrow_mut(); assert!(lazy_jit_state.is_none()); - *lazy_jit_state = Some(JitState { backend_config, jit_module }); + *lazy_jit_state = Some(JitState { jit_module }); }); let f: extern "C" fn(c_int, *const *const c_char) -> c_int = @@ -268,7 +255,6 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) -> let mut lazy_jit_state = lazy_jit_state.borrow_mut(); let lazy_jit_state = lazy_jit_state.as_mut().unwrap(); let jit_module = &mut lazy_jit_state.jit_module; - let backend_config = lazy_jit_state.backend_config.clone(); let name = tcx.symbol_name(instance).name; let sig = crate::abi::get_function_sig( @@ -278,7 +264,7 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) -> ); let func_id = jit_module.declare_function(name, Linkage::Export, &sig).unwrap(); - let current_ptr = jit_module.read_got_entry(func_id); + let current_ptr = jit_module.module.read_got_entry(func_id); // If the function's GOT entry has already been updated to point at something other // than the shim trampoline, don't re-jit but just return the new pointer instead. @@ -288,11 +274,10 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) -> return current_ptr; } - jit_module.prepare_for_function_redefine(func_id).unwrap(); + jit_module.module.prepare_for_function_redefine(func_id).unwrap(); let mut cx = crate::CodegenCx::new( tcx, - backend_config, jit_module.isa(), false, Symbol::intern("dummy_cgu_name"), @@ -300,9 +285,8 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) -> codegen_and_compile_fn(tcx, &mut cx, &mut Context::new(), jit_module, instance); assert!(cx.global_asm.is_empty()); - jit_module.finalize_definitions().unwrap(); - unsafe { cx.unwind_context.register_jit(&jit_module) }; - jit_module.get_finalized_function(func_id) + jit_module.finalize_definitions(); + jit_module.module.get_finalized_function(func_id) }) }) } @@ -310,7 +294,7 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) -> fn dep_symbol_lookup_fn( sess: &Session, crate_info: CrateInfo, -) -> Box Option<*const u8>> { +) -> Box Option<*const u8> + Send> { use rustc_middle::middle::dependency_format::Linkage; let mut dylib_paths = Vec::new(); @@ -362,9 +346,8 @@ fn dep_symbol_lookup_fn( fn codegen_shim<'tcx>( tcx: TyCtxt<'tcx>, - cx: &mut CodegenCx, cached_context: &mut Context, - module: &mut JITModule, + module: &mut UnwindModule, inst: Instance<'tcx>, ) { let pointer_type = module.target_config().pointer_type(); @@ -413,5 +396,4 @@ fn codegen_shim<'tcx>( trampoline_builder.ins().return_(&ret_vals); module.define_function(func_id, context).unwrap(); - cx.unwind_context.add_function(func_id, context, module.isa()); } diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs index c6b26dd873bdc..c88230c936056 100644 --- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs @@ -113,13 +113,7 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>( ); let sig = get_function_sig(fx.tcx, fx.target_config.default_call_conv, instance); - create_wrapper_function( - fx.module, - &mut fx.cx.unwind_context, - sig, - &wrapper_name, - symbol.name, - ); + create_wrapper_function(fx.module, sig, &wrapper_name, symbol.name); CInlineAsmOperand::Symbol { symbol: wrapper_name } } else { @@ -283,13 +277,7 @@ pub(crate) fn codegen_naked_asm<'tcx>( ); let sig = get_function_sig(tcx, module.target_config().default_call_conv, instance); - create_wrapper_function( - module, - &mut cx.unwind_context, - sig, - &wrapper_name, - symbol.name, - ); + create_wrapper_function(module, sig, &wrapper_name, symbol.name); CInlineAsmOperand::Symbol { symbol: wrapper_name } } else { diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs index d454f3c1de7e4..399518e58d8c5 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs @@ -459,11 +459,20 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( intrinsic_args!(fx, args => (a); intrinsic); let a = a.load_scalar(fx); + let value = fx.bcx.ins().x86_cvtt2dq(types::I32X4, a); + let cvalue = CValue::by_val(value, ret.layout()); + ret.write_cvalue(fx, cvalue); + } + "llvm.x86.sse2.cvtps2dq" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtps_epi32 + intrinsic_args!(fx, args => (a); intrinsic); + let a = a.load_scalar(fx); + // Using inline asm instead of fcvt_to_sint_sat as unrepresentable values are turned // into 0x80000000 for which Cranelift doesn't have a native instruction. codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String(format!("cvttps2dq xmm0, xmm0"))], + &[InlineAsmTemplatePiece::String(format!("cvtps2dq xmm0, xmm0"))], &[CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), _late: true, @@ -1416,6 +1425,36 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( ret.write_cvalue(fx, res); } + "llvm.x86.rdtsc" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_rdtsc&ig_expand=5273 + + let res_place = CPlace::new_stack_slot( + fx, + fx.layout_of(Ty::new_tup(fx.tcx, &[fx.tcx.types.u32, fx.tcx.types.u32])), + ); + let eax_place = res_place.place_field(fx, FieldIdx::new(0)); + let edx_place = res_place.place_field(fx, FieldIdx::new(1)); + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String("rdtsc".to_string())], + &[ + CInlineAsmOperand::Out { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)), + late: true, + place: Some(eax_place), + }, + CInlineAsmOperand::Out { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)), + late: true, + place: Some(edx_place), + }, + ], + InlineAsmOptions::NOSTACK | InlineAsmOptions::NOMEM, + ); + let res = res_place.to_cvalue(fx); + ret.write_cvalue_transmute(fx, res); + } + _ => { fx.tcx .dcx() diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 06ca52b390320..192e6c91ea38b 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -79,6 +79,7 @@ mod pretty_clif; mod toolchain; mod trap; mod unsize; +mod unwind_module; mod value_and_place; mod vtable; @@ -130,22 +131,13 @@ struct CodegenCx { global_asm: String, inline_asm_index: Cell, debug_context: Option, - unwind_context: UnwindContext, cgu_name: Symbol, } impl CodegenCx { - fn new( - tcx: TyCtxt<'_>, - backend_config: BackendConfig, - isa: &dyn TargetIsa, - debug_info: bool, - cgu_name: Symbol, - ) -> Self { + fn new(tcx: TyCtxt<'_>, isa: &dyn TargetIsa, debug_info: bool, cgu_name: Symbol) -> Self { assert_eq!(pointer_ty(tcx), isa.pointer_type()); - let unwind_context = - UnwindContext::new(isa, matches!(backend_config.codegen_mode, CodegenMode::Aot)); let debug_context = if debug_info && !tcx.sess.target.options.is_like_windows { Some(DebugContext::new(tcx, isa, cgu_name.as_str())) } else { @@ -158,7 +150,6 @@ impl CodegenCx { global_asm: String::new(), inline_asm_index: Cell::new(0), debug_context, - unwind_context, cgu_name, } } @@ -175,7 +166,7 @@ impl CodegenBackend for CraneliftCodegenBackend { } fn init(&self, sess: &Session) { - use rustc_session::config::Lto; + use rustc_session::config::{InstrumentCoverage, Lto}; match sess.lto() { Lto::No | Lto::ThinLocal => {} Lto::Thin | Lto::Fat => { @@ -183,6 +174,11 @@ impl CodegenBackend for CraneliftCodegenBackend { } } + if sess.opts.cg.instrument_coverage() != InstrumentCoverage::No { + sess.dcx() + .fatal("`-Cinstrument-coverage` is LLVM specific and not supported by Cranelift"); + } + let mut config = self.config.borrow_mut(); if config.is_none() { let new_config = BackendConfig::from_opts(&sess.opts.cg.llvm_args) diff --git a/compiler/rustc_codegen_cranelift/src/main_shim.rs b/compiler/rustc_codegen_cranelift/src/main_shim.rs index f9a729618a51a..33d3f9b8a90a3 100644 --- a/compiler/rustc_codegen_cranelift/src/main_shim.rs +++ b/compiler/rustc_codegen_cranelift/src/main_shim.rs @@ -11,8 +11,7 @@ use crate::prelude::*; /// users main function. pub(crate) fn maybe_create_entry_wrapper( tcx: TyCtxt<'_>, - module: &mut impl Module, - unwind_context: &mut UnwindContext, + module: &mut dyn Module, is_jit: bool, is_primary_cgu: bool, ) { @@ -36,12 +35,11 @@ pub(crate) fn maybe_create_entry_wrapper( return; } - create_entry_fn(tcx, module, unwind_context, main_def_id, is_jit, is_main_fn, sigpipe); + create_entry_fn(tcx, module, main_def_id, is_jit, is_main_fn, sigpipe); fn create_entry_fn( tcx: TyCtxt<'_>, - m: &mut impl Module, - unwind_context: &mut UnwindContext, + m: &mut dyn Module, rust_main_def_id: DefId, ignore_lang_start_wrapper: bool, is_main_fn: bool, @@ -170,7 +168,5 @@ pub(crate) fn maybe_create_entry_wrapper( if let Err(err) = m.define_function(cmain_func_id, &mut ctx) { tcx.dcx().fatal(format!("entry symbol `{entry_name}` defined multiple times: {err}")); } - - unwind_context.add_function(cmain_func_id, &ctx, m.isa()); } } diff --git a/compiler/rustc_codegen_cranelift/src/unwind_module.rs b/compiler/rustc_codegen_cranelift/src/unwind_module.rs new file mode 100644 index 0000000000000..b950aaa29ce04 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/src/unwind_module.rs @@ -0,0 +1,115 @@ +use cranelift_codegen::control::ControlPlane; +use cranelift_codegen::ir::{Function, Signature}; +use cranelift_codegen::isa::{TargetFrontendConfig, TargetIsa}; +use cranelift_codegen::{Context, FinalizedMachReloc}; +use cranelift_module::{ + DataDescription, DataId, FuncId, FuncOrDataId, Linkage, Module, ModuleDeclarations, + ModuleResult, +}; +use cranelift_object::{ObjectModule, ObjectProduct}; + +use crate::UnwindContext; + +/// A wrapper around a [Module] which adds any defined function to the [UnwindContext]. +pub(crate) struct UnwindModule { + pub(crate) module: T, + unwind_context: UnwindContext, +} + +impl UnwindModule { + pub(crate) fn new(module: T, pic_eh_frame: bool) -> Self { + let unwind_context = UnwindContext::new(module.isa(), pic_eh_frame); + UnwindModule { module, unwind_context } + } +} + +impl UnwindModule { + pub(crate) fn finish(self) -> ObjectProduct { + let mut product = self.module.finish(); + self.unwind_context.emit(&mut product); + product + } +} + +#[cfg(feature = "jit")] +impl UnwindModule { + pub(crate) fn finalize_definitions(&mut self) { + self.module.finalize_definitions().unwrap(); + let prev_unwind_context = std::mem::replace( + &mut self.unwind_context, + UnwindContext::new(self.module.isa(), false), + ); + unsafe { prev_unwind_context.register_jit(&self.module) }; + } +} + +impl Module for UnwindModule { + fn isa(&self) -> &dyn TargetIsa { + self.module.isa() + } + + fn declarations(&self) -> &ModuleDeclarations { + self.module.declarations() + } + + fn get_name(&self, name: &str) -> Option { + self.module.get_name(name) + } + + fn target_config(&self) -> TargetFrontendConfig { + self.module.target_config() + } + + fn declare_function( + &mut self, + name: &str, + linkage: Linkage, + signature: &Signature, + ) -> ModuleResult { + self.module.declare_function(name, linkage, signature) + } + + fn declare_anonymous_function(&mut self, signature: &Signature) -> ModuleResult { + self.module.declare_anonymous_function(signature) + } + + fn declare_data( + &mut self, + name: &str, + linkage: Linkage, + writable: bool, + tls: bool, + ) -> ModuleResult { + self.module.declare_data(name, linkage, writable, tls) + } + + fn declare_anonymous_data(&mut self, writable: bool, tls: bool) -> ModuleResult { + self.module.declare_anonymous_data(writable, tls) + } + + fn define_function_with_control_plane( + &mut self, + func: FuncId, + ctx: &mut Context, + ctrl_plane: &mut ControlPlane, + ) -> ModuleResult<()> { + self.module.define_function_with_control_plane(func, ctx, ctrl_plane)?; + self.unwind_context.add_function(func, ctx, self.module.isa()); + Ok(()) + } + + fn define_function_bytes( + &mut self, + _func_id: FuncId, + _func: &Function, + _alignment: u64, + _bytes: &[u8], + _relocs: &[FinalizedMachReloc], + ) -> ModuleResult<()> { + unimplemented!() + } + + fn define_data(&mut self, data_id: DataId, data: &DataDescription) -> ModuleResult<()> { + self.module.define_data(data_id, data) + } +} diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs index 548c23cc7948a..230fe4f5871e8 100644 --- a/compiler/rustc_codegen_gcc/src/common.rs +++ b/compiler/rustc_codegen_gcc/src/common.rs @@ -28,6 +28,19 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { global // TODO(antoyo): set linkage. } + + pub fn const_bitcast(&self, value: RValue<'gcc>, typ: Type<'gcc>) -> RValue<'gcc> { + if value.get_type() == self.bool_type.make_pointer() { + if let Some(pointee) = typ.get_pointee() { + if pointee.dyncast_vector().is_some() { + panic!() + } + } + } + // NOTE: since bitcast makes a value non-constant, don't bitcast if not necessary as some + // SIMD builtins require a constant value. + self.bitcast_if_needed(value, typ) + } } pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> RValue<'gcc> { @@ -239,19 +252,6 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> { const_alloc_to_gcc(self, alloc) } - fn const_bitcast(&self, value: RValue<'gcc>, typ: Type<'gcc>) -> RValue<'gcc> { - if value.get_type() == self.bool_type.make_pointer() { - if let Some(pointee) = typ.get_pointee() { - if pointee.dyncast_vector().is_some() { - panic!() - } - } - } - // NOTE: since bitcast makes a value non-constant, don't bitcast if not necessary as some - // SIMD builtins require a constant value. - self.bitcast_if_needed(value, typ) - } - fn const_ptr_byte_offset(&self, base_addr: Self::Value, offset: abi::Size) -> Self::Value { self.context .new_array_access(None, base_addr, self.const_usize(offset.bytes())) diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index 4a1f5188a8013..6231b09552cea 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -27,7 +27,6 @@ use crate::callee::get_fn; use crate::common::SignType; pub struct CodegenCx<'gcc, 'tcx> { - pub check_overflow: bool, pub codegen_unit: &'tcx CodegenUnit<'tcx>, pub context: &'gcc Context<'gcc>, @@ -134,8 +133,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { tcx: TyCtxt<'tcx>, supports_128bit_integers: bool, ) -> Self { - let check_overflow = tcx.sess.overflow_checks(); - let create_type = |ctype, rust_type| { let layout = tcx.layout_of(ParamEnv::reveal_all().and(rust_type)).unwrap(); let align = layout.align.abi.bytes(); @@ -271,7 +268,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { } let mut cx = Self { - check_overflow, codegen_unit, context, current_func: RefCell::new(None), @@ -511,10 +507,6 @@ impl<'gcc, 'tcx> MiscMethods<'tcx> for CodegenCx<'gcc, 'tcx> { &self.tcx.sess } - fn check_overflow(&self) -> bool { - self.check_overflow - } - fn codegen_unit(&self) -> &'tcx CodegenUnit<'tcx> { self.codegen_unit } diff --git a/compiler/rustc_codegen_gcc/src/type_.rs b/compiler/rustc_codegen_gcc/src/type_.rs index 68471b028beb8..4caff2e63106a 100644 --- a/compiler/rustc_codegen_gcc/src/type_.rs +++ b/compiler/rustc_codegen_gcc/src/type_.rs @@ -89,13 +89,34 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { ty::FloatTy::F128 => self.type_f128(), } } -} -impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> { - fn type_i1(&self) -> Type<'gcc> { + pub fn type_i1(&self) -> Type<'gcc> { self.bool_type } + pub fn type_struct(&self, fields: &[Type<'gcc>], packed: bool) -> Type<'gcc> { + let types = fields.to_vec(); + if let Some(typ) = self.struct_types.borrow().get(fields) { + return *typ; + } + let fields: Vec<_> = fields + .iter() + .enumerate() + .map(|(index, field)| { + self.context.new_field(None, *field, format!("field{}_TODO", index)) + }) + .collect(); + let typ = self.context.new_struct_type(None, "struct", &fields).as_type(); + if packed { + #[cfg(feature = "master")] + typ.set_packed(); + } + self.struct_types.borrow_mut().insert(types, typ); + typ + } +} + +impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> { fn type_i8(&self) -> Type<'gcc> { self.i8_type } @@ -131,7 +152,7 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> { fn type_f64(&self) -> Type<'gcc> { self.double_type } - + fn type_f128(&self) -> Type<'gcc> { unimplemented!("f16_f128") } @@ -140,27 +161,6 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> { self.context.new_function_pointer_type(None, return_type, params, false) } - fn type_struct(&self, fields: &[Type<'gcc>], packed: bool) -> Type<'gcc> { - let types = fields.to_vec(); - if let Some(typ) = self.struct_types.borrow().get(fields) { - return *typ; - } - let fields: Vec<_> = fields - .iter() - .enumerate() - .map(|(index, field)| { - self.context.new_field(None, *field, format!("field{}_TODO", index)) - }) - .collect(); - let typ = self.context.new_struct_type(None, "struct", &fields).as_type(); - if packed { - #[cfg(feature = "master")] - typ.set_packed(); - } - self.struct_types.borrow_mut().insert(types, typ); - typ - } - fn type_kind(&self, typ: Type<'gcc>) -> TypeKind { if self.is_int_type_or_bool(typ) { TypeKind::Integer diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index 4ffc92eb63356..d42c6ed827aec 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -329,10 +329,6 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { const_alloc_to_llvm(self, alloc, /*static*/ false) } - fn const_bitcast(&self, val: &'ll Value, ty: &'ll Type) -> &'ll Value { - self.const_bitcast(val, ty) - } - fn const_ptr_byte_offset(&self, base_addr: Self::Value, offset: abi::Size) -> Self::Value { unsafe { llvm::LLVMConstInBoundsGEP2( diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 7d92888feeed4..1a8e8efdae507 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -3,6 +3,7 @@ use crate::back::write::to_llvm_code_model; use crate::callee::get_fn; use crate::coverageinfo; use crate::debuginfo; +use crate::debuginfo::metadata::apply_vcall_visibility_metadata; use crate::llvm; use crate::llvm_util; use crate::type_::Type; @@ -43,7 +44,6 @@ use std::str; /// All other LLVM data structures in the `CodegenCx` are tied to that `llvm::Context`. pub struct CodegenCx<'ll, 'tcx> { pub tcx: TyCtxt<'tcx>, - pub check_overflow: bool, pub use_dll_storage_attrs: bool, pub tls_model: llvm::ThreadLocalMode, @@ -441,8 +441,6 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { // start) and then strongly recommending static linkage on Windows! let use_dll_storage_attrs = tcx.sess.target.is_like_windows; - let check_overflow = tcx.sess.overflow_checks(); - let tls_model = to_llvm_tls_model(tcx.sess.tls_model()); let (llcx, llmod) = (&*llvm_module.llcx, llvm_module.llmod()); @@ -466,7 +464,6 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { CodegenCx { tcx, - check_overflow, use_dll_storage_attrs, tls_model, llmod, @@ -522,6 +519,15 @@ impl<'ll, 'tcx> MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { &self.vtables } + fn apply_vcall_visibility_metadata( + &self, + ty: Ty<'tcx>, + poly_trait_ref: Option>, + vtable: &'ll Value, + ) { + apply_vcall_visibility_metadata(self, ty, poly_trait_ref, vtable); + } + fn get_fn(&self, instance: Instance<'tcx>) -> &'ll Value { get_fn(self, instance) } @@ -596,10 +602,6 @@ impl<'ll, 'tcx> MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { self.tcx.sess } - fn check_overflow(&self) -> bool { - self.check_overflow - } - fn codegen_unit(&self) -> &'tcx CodegenUnit<'tcx> { self.codegen_unit } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 8de4e0effad28..742bfd76590a4 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -1449,12 +1449,18 @@ fn build_vtable_type_di_node<'ll, 'tcx>( .di_node } -fn vcall_visibility_metadata<'ll, 'tcx>( +pub(crate) fn apply_vcall_visibility_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, trait_ref: Option>, vtable: &'ll Value, ) { + // FIXME(flip1995): The virtual function elimination optimization only works with full LTO in + // LLVM at the moment. + if !cx.sess().opts.unstable_opts.virtual_function_elimination || cx.sess().lto() != Lto::Fat { + return; + } + enum VCallVisibility { Public = 0, LinkageUnit = 1, @@ -1531,12 +1537,6 @@ pub fn create_vtable_di_node<'ll, 'tcx>( poly_trait_ref: Option>, vtable: &'ll Value, ) { - // FIXME(flip1995): The virtual function elimination optimization only works with full LTO in - // LLVM at the moment. - if cx.sess().opts.unstable_opts.virtual_function_elimination && cx.sess().lto() == Lto::Fat { - vcall_visibility_metadata(cx, ty, poly_trait_ref, vtable); - } - if cx.dbg_cx.is_none() { return; } diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 4b7a264300711..ed0989a0ba413 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -274,10 +274,11 @@ impl CodegenBackend for LlvmCodegenBackend { |tcx, ()| llvm_util::global_llvm_features(tcx.sess, true) } - fn print(&self, req: &PrintRequest, out: &mut dyn PrintBackendInfo, sess: &Session) { + fn print(&self, req: &PrintRequest, out: &mut String, sess: &Session) { + use std::fmt::Write; match req.kind { PrintKind::RelocationModels => { - writeln!(out, "Available relocation models:"); + writeln!(out, "Available relocation models:").unwrap(); for name in &[ "static", "pic", @@ -288,25 +289,25 @@ impl CodegenBackend for LlvmCodegenBackend { "ropi-rwpi", "default", ] { - writeln!(out, " {name}"); + writeln!(out, " {name}").unwrap(); } - writeln!(out); + writeln!(out).unwrap(); } PrintKind::CodeModels => { - writeln!(out, "Available code models:"); + writeln!(out, "Available code models:").unwrap(); for name in &["tiny", "small", "kernel", "medium", "large"] { - writeln!(out, " {name}"); + writeln!(out, " {name}").unwrap(); } - writeln!(out); + writeln!(out).unwrap(); } PrintKind::TlsModels => { - writeln!(out, "Available TLS models:"); + writeln!(out, "Available TLS models:").unwrap(); for name in &["global-dynamic", "local-dynamic", "initial-exec", "local-exec", "emulated"] { - writeln!(out, " {name}"); + writeln!(out, " {name}").unwrap(); } - writeln!(out); + writeln!(out).unwrap(); } PrintKind::StackProtectorStrategies => { writeln!( @@ -332,7 +333,8 @@ impl CodegenBackend for LlvmCodegenBackend { none Do not generate stack canaries. "# - ); + ) + .unwrap(); } _other => llvm_util::print(req, out, sess), } diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 7e0f264a4aedf..0e89e66be49a0 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -6,7 +6,6 @@ use crate::errors::{ use crate::llvm; use libc::c_int; use rustc_codegen_ssa::base::wants_wasm_eh; -use rustc_codegen_ssa::traits::PrintBackendInfo; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::small_c_str::SmallCStr; use rustc_fs_util::path_to_c_string; @@ -18,6 +17,7 @@ use rustc_target::spec::{MergeFunctions, PanicStrategy}; use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES; use std::ffi::{c_char, c_void, CStr, CString}; +use std::fmt::Write; use std::path::Path; use std::ptr; use std::slice; @@ -372,7 +372,7 @@ fn llvm_target_features(tm: &llvm::TargetMachine) -> Vec<(&str, &str)> { ret } -fn print_target_features(out: &mut dyn PrintBackendInfo, sess: &Session, tm: &llvm::TargetMachine) { +fn print_target_features(out: &mut String, sess: &Session, tm: &llvm::TargetMachine) { let mut llvm_target_features = llvm_target_features(tm); let mut known_llvm_target_features = FxHashSet::<&'static str>::default(); let mut rustc_target_features = sess @@ -412,24 +412,26 @@ fn print_target_features(out: &mut dyn PrintBackendInfo, sess: &Session, tm: &ll .max() .unwrap_or(0); - writeln!(out, "Features supported by rustc for this target:"); + writeln!(out, "Features supported by rustc for this target:").unwrap(); for (feature, desc) in &rustc_target_features { - writeln!(out, " {feature:max_feature_len$} - {desc}."); + writeln!(out, " {feature:max_feature_len$} - {desc}.").unwrap(); } - writeln!(out, "\nCode-generation features supported by LLVM for this target:"); + writeln!(out, "\nCode-generation features supported by LLVM for this target:").unwrap(); for (feature, desc) in &llvm_target_features { - writeln!(out, " {feature:max_feature_len$} - {desc}."); + writeln!(out, " {feature:max_feature_len$} - {desc}.").unwrap(); } if llvm_target_features.is_empty() { - writeln!(out, " Target features listing is not supported by this LLVM version."); + writeln!(out, " Target features listing is not supported by this LLVM version.") + .unwrap(); } - writeln!(out, "\nUse +feature to enable a feature, or -feature to disable it."); - writeln!(out, "For example, rustc -C target-cpu=mycpu -C target-feature=+feature1,-feature2\n"); - writeln!(out, "Code-generation features cannot be used in cfg or #[target_feature],"); - writeln!(out, "and may be renamed or removed in a future version of LLVM or rustc.\n"); + writeln!(out, "\nUse +feature to enable a feature, or -feature to disable it.").unwrap(); + writeln!(out, "For example, rustc -C target-cpu=mycpu -C target-feature=+feature1,-feature2\n") + .unwrap(); + writeln!(out, "Code-generation features cannot be used in cfg or #[target_feature],").unwrap(); + writeln!(out, "and may be renamed or removed in a future version of LLVM or rustc.\n").unwrap(); } -pub(crate) fn print(req: &PrintRequest, mut out: &mut dyn PrintBackendInfo, sess: &Session) { +pub(crate) fn print(req: &PrintRequest, mut out: &mut String, sess: &Session) { require_inited(); let tm = create_informational_target_machine(sess); match req.kind { @@ -440,9 +442,9 @@ pub(crate) fn print(req: &PrintRequest, mut out: &mut dyn PrintBackendInfo, sess let cpu_cstring = CString::new(handle_native(sess.target.cpu.as_ref())) .unwrap_or_else(|e| bug!("failed to convert to cstring: {}", e)); unsafe extern "C" fn callback(out: *mut c_void, string: *const c_char, len: usize) { - let out = &mut *(out as *mut &mut dyn PrintBackendInfo); + let out = &mut *(out as *mut &mut String); let bytes = slice::from_raw_parts(string as *const u8, len); - write!(out, "{}", String::from_utf8_lossy(bytes)); + write!(out, "{}", String::from_utf8_lossy(bytes)).unwrap(); } unsafe { llvm::LLVMRustPrintTargetCPUs( diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs index a00f09dc40da6..f1141c57cedd7 100644 --- a/compiler/rustc_codegen_llvm/src/type_.rs +++ b/compiler/rustc_codegen_llvm/src/type_.rs @@ -127,13 +127,24 @@ impl<'ll> CodegenCx<'ll, '_> { pub(crate) fn type_variadic_func(&self, args: &[&'ll Type], ret: &'ll Type) -> &'ll Type { unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, True) } } -} -impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { - fn type_i1(&self) -> &'ll Type { + pub(crate) fn type_i1(&self) -> &'ll Type { unsafe { llvm::LLVMInt1TypeInContext(self.llcx) } } + pub(crate) fn type_struct(&self, els: &[&'ll Type], packed: bool) -> &'ll Type { + unsafe { + llvm::LLVMStructTypeInContext( + self.llcx, + els.as_ptr(), + els.len() as c_uint, + packed as Bool, + ) + } + } +} + +impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn type_i8(&self) -> &'ll Type { unsafe { llvm::LLVMInt8TypeInContext(self.llcx) } } @@ -178,17 +189,6 @@ impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, False) } } - fn type_struct(&self, els: &[&'ll Type], packed: bool) -> &'ll Type { - unsafe { - llvm::LLVMStructTypeInContext( - self.llcx, - els.as_ptr(), - els.len() as c_uint, - packed as Bool, - ) - } - } - fn type_kind(&self, ty: &'ll Type) -> TypeKind { unsafe { llvm::LLVMRustGetTypeKind(ty).to_generic() } } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index d509e4ce56d5b..da4fa41e2aafc 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -45,7 +45,7 @@ use tempfile::Builder as TempFileBuilder; use itertools::Itertools; use std::collections::BTreeSet; -use std::ffi::{OsStr, OsString}; +use std::ffi::OsString; use std::fs::{read, File, OpenOptions}; use std::io::{BufWriter, Write}; use std::ops::Deref; @@ -1306,12 +1306,12 @@ fn link_sanitizer_runtime( let filename = format!("rustc{channel}_rt.{name}"); let path = find_sanitizer_runtime(sess, &filename); let rpath = path.to_str().expect("non-utf8 component in path"); - linker.args(&["-Wl,-rpath", "-Xlinker", rpath]); + linker.cc_args(&["-Wl,-rpath", "-Xlinker", rpath]); linker.link_dylib_by_name(&filename, false, true); } else if sess.target.is_like_msvc && flavor == LinkerFlavor::Msvc(Lld::No) && name == "asan" { // MSVC provides the `/INFERASANLIBS` argument to automatically find the // compatible ASAN library. - linker.arg("/INFERASANLIBS"); + linker.link_arg("/INFERASANLIBS"); } else { let filename = format!("librustc{channel}_rt.{name}.a"); let path = find_sanitizer_runtime(sess, &filename).join(&filename); @@ -1888,9 +1888,9 @@ fn add_post_link_objects( /// FIXME: Determine where exactly these args need to be inserted. fn add_pre_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { if let Some(args) = sess.target.pre_link_args.get(&flavor) { - cmd.args(args.iter().map(Deref::deref)); + cmd.verbatim_args(args.iter().map(Deref::deref)); } - cmd.args(&sess.opts.unstable_opts.pre_link_args); + cmd.verbatim_args(&sess.opts.unstable_opts.pre_link_args); } /// Add a link script embedded in the target, if applicable. @@ -1908,8 +1908,7 @@ fn add_link_script(cmd: &mut dyn Linker, sess: &Session, tmpdir: &Path, crate_ty sess.dcx().emit_fatal(errors::LinkScriptWriteFailure { path, error }); } - cmd.arg("--script"); - cmd.arg(path); + cmd.link_arg("--script").link_arg(path); } _ => {} } @@ -1918,7 +1917,7 @@ fn add_link_script(cmd: &mut dyn Linker, sess: &Session, tmpdir: &Path, crate_ty /// Add arbitrary "user defined" args defined from command line. /// FIXME: Determine where exactly these args need to be inserted. fn add_user_defined_link_args(cmd: &mut dyn Linker, sess: &Session) { - cmd.args(&sess.opts.cg.link_args); + cmd.verbatim_args(&sess.opts.cg.link_args); } /// Add arbitrary "late link" args defined by the target spec. @@ -1936,15 +1935,15 @@ fn add_late_link_args( }); if any_dynamic_crate { if let Some(args) = sess.target.late_link_args_dynamic.get(&flavor) { - cmd.args(args.iter().map(Deref::deref)); + cmd.verbatim_args(args.iter().map(Deref::deref)); } } else { if let Some(args) = sess.target.late_link_args_static.get(&flavor) { - cmd.args(args.iter().map(Deref::deref)); + cmd.verbatim_args(args.iter().map(Deref::deref)); } } if let Some(args) = sess.target.late_link_args.get(&flavor) { - cmd.args(args.iter().map(Deref::deref)); + cmd.verbatim_args(args.iter().map(Deref::deref)); } } @@ -1952,7 +1951,7 @@ fn add_late_link_args( /// FIXME: Determine where exactly these args need to be inserted. fn add_post_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { if let Some(args) = sess.target.post_link_args.get(&flavor) { - cmd.args(args.iter().map(Deref::deref)); + cmd.verbatim_args(args.iter().map(Deref::deref)); } } @@ -2097,6 +2096,10 @@ fn add_rpath_args( codegen_results: &CodegenResults, out_filename: &Path, ) { + if !sess.target.has_rpath { + return; + } + // FIXME (#2397): At some point we want to rpath our guesses as to // where extern libraries might live, based on the // add_lib_search_paths @@ -2115,11 +2118,10 @@ fn add_rpath_args( let rpath_config = RPathConfig { libs: &*libs, out_filename: out_filename.to_path_buf(), - has_rpath: sess.target.has_rpath, is_like_osx: sess.target.is_like_osx, linker_is_gnu: sess.target.linker_flavor.is_gnu(), }; - cmd.args(&rpath::get_rpath_flags(&rpath_config)); + cmd.cc_args(&rpath::get_rpath_flags(&rpath_config)); } } @@ -2378,7 +2380,7 @@ fn add_order_independent_options( } else { "" }; - cmd.arg(format!("--dynamic-linker={prefix}ld.so.1")); + cmd.link_arg(format!("--dynamic-linker={prefix}ld.so.1")); } if sess.target.eh_frame_header { @@ -2393,8 +2395,7 @@ fn add_order_independent_options( } if sess.target.os == "emscripten" { - cmd.arg("-s"); - cmd.arg(if sess.panic_strategy() == PanicStrategy::Abort { + cmd.cc_arg("-s").cc_arg(if sess.panic_strategy() == PanicStrategy::Abort { "DISABLE_EXCEPTION_CATCHING=1" } else { "DISABLE_EXCEPTION_CATCHING=0" @@ -2402,22 +2403,21 @@ fn add_order_independent_options( } if flavor == LinkerFlavor::Llbc { - cmd.arg("--target"); - cmd.arg(sess.target.llvm_target.as_ref()); - cmd.arg("--target-cpu"); - cmd.arg(&codegen_results.crate_info.target_cpu); + cmd.link_args(&[ + "--target", + sess.target.llvm_target.as_ref(), + "--target-cpu", + &codegen_results.crate_info.target_cpu, + ]); } else if flavor == LinkerFlavor::Ptx { - cmd.arg("--fallback-arch"); - cmd.arg(&codegen_results.crate_info.target_cpu); + cmd.link_args(&["--fallback-arch", &codegen_results.crate_info.target_cpu]); } else if flavor == LinkerFlavor::Bpf { - cmd.arg("--cpu"); - cmd.arg(&codegen_results.crate_info.target_cpu); + cmd.link_args(&["--cpu", &codegen_results.crate_info.target_cpu]); if let Some(feat) = [sess.opts.cg.target_feature.as_str(), &sess.target.options.features] .into_iter() .find(|feat| !feat.is_empty()) { - cmd.arg("--cpu-features"); - cmd.arg(feat); + cmd.link_args(&["--cpu-features", feat]); } } @@ -2618,7 +2618,11 @@ fn add_native_libs_from_crate( NativeLibKind::WasmImportModule => {} NativeLibKind::LinkArg => { if link_static { - cmd.linker_arg(OsStr::new(name), verbatim); + if verbatim { + cmd.verbatim_arg(name); + } else { + cmd.link_arg(name); + } } } } @@ -3012,10 +3016,10 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { // This is admittedly a bit strange, as on most targets // `-isysroot` only applies to include header files, but on Apple // targets this also applies to libraries and frameworks. - cmd.args(&["-isysroot", &sdk_root]); + cmd.cc_args(&["-isysroot", &sdk_root]); } LinkerFlavor::Darwin(Cc::No, _) => { - cmd.args(&["-syslibroot", &sdk_root]); + cmd.link_args(&["-syslibroot", &sdk_root]); } _ => unreachable!(), } @@ -3026,8 +3030,9 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { // search path. // The flags are called `-L` and `-F` both in Clang, ld64 and ldd. - cmd.arg(format!("-L{sdk_root}/System/iOSSupport/usr/lib")); - cmd.arg(format!("-F{sdk_root}/System/iOSSupport/System/Library/Frameworks")); + let sdk_root = Path::new(&sdk_root); + cmd.include_path(&sdk_root.join("System/iOSSupport/usr/lib")); + cmd.framework_path(&sdk_root.join("System/iOSSupport/System/Library/Frameworks")); } } @@ -3142,7 +3147,7 @@ fn add_lld_args( for path in sess.get_tools_search_paths(false) { let linker_path = path.join("gcc-ld"); linker_path_exists |= linker_path.exists(); - cmd.arg({ + cmd.cc_arg({ let mut arg = OsString::from("-B"); arg.push(linker_path); arg @@ -3162,7 +3167,7 @@ fn add_lld_args( // is to use LLD but the `wasm32-wasip2` target relies on a wrapper around // this, `wasm-component-ld`, which is overridden if this option is passed. if !sess.target.is_like_wasm { - cmd.arg("-fuse-ld=lld"); + cmd.cc_arg("-fuse-ld=lld"); } if !flavor.is_gnu() { @@ -3186,7 +3191,7 @@ fn add_lld_args( // targeting a different linker flavor on macOS, and that's also always // the case when targeting WASM. if sess.target.linker_flavor != sess.host.linker_flavor { - cmd.arg(format!("--target={}", sess.target.llvm_target)); + cmd.cc_arg(format!("--target={}", sess.target.llvm_target)); } } } diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index a82478900b17f..0f75ece9729cd 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -8,7 +8,7 @@ use std::fs::{self, File}; use std::io::prelude::*; use std::io::{self, BufWriter}; use std::path::{Path, PathBuf}; -use std::{env, mem, str}; +use std::{env, iter, mem, str}; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_metadata::find_native_static_library; @@ -159,6 +159,102 @@ pub fn get_linker<'a>( } } +// Note: Ideally neither these helper function, nor the macro-generated inherent methods below +// would exist, and these functions would live in `trait Linker`. +// Unfortunately, adding these functions to `trait Linker` make it `dyn`-incompatible. +// If the methods are added to the trait with `where Self: Sized` bounds, then even a separate +// implementation of them for `dyn Linker {}` wouldn't work due to a conflict with those +// uncallable methods in the trait. + +/// Just pass the arguments to the linker as is. +/// It is assumed that they are correctly prepared in advance. +fn verbatim_args( + l: &mut L, + args: impl IntoIterator>, +) -> &mut L { + for arg in args { + l.cmd().arg(arg); + } + l +} +/// Arguments for the underlying linker. +/// Add options to pass them through cc wrapper if `Linker` is a cc wrapper. +fn link_args( + l: &mut L, + args: impl IntoIterator, IntoIter: ExactSizeIterator>, +) -> &mut L { + let args = args.into_iter(); + if !l.is_cc() { + verbatim_args(l, args); + } else if args.len() != 0 { + // FIXME: Support arguments with commas, see `rpaths_to_flags` for the example. + let mut combined_arg = OsString::from("-Wl"); + for arg in args { + combined_arg.push(","); + combined_arg.push(arg); + } + l.cmd().arg(combined_arg); + } + l +} +/// Arguments for the cc wrapper specifically. +/// Check that it's indeed a cc wrapper and pass verbatim. +fn cc_args(l: &mut L, args: impl IntoIterator>) -> &mut L { + assert!(l.is_cc()); + verbatim_args(l, args) +} +/// Arguments supported by both underlying linker and cc wrapper, pass verbatim. +fn link_or_cc_args( + l: &mut L, + args: impl IntoIterator>, +) -> &mut L { + verbatim_args(l, args) +} + +macro_rules! generate_arg_methods { + ($($ty:ty)*) => { $( + impl $ty { + pub fn verbatim_args(&mut self, args: impl IntoIterator>) -> &mut Self { + verbatim_args(self, args) + } + pub fn verbatim_arg(&mut self, arg: impl AsRef) -> &mut Self { + verbatim_args(self, iter::once(arg)) + } + pub fn link_args(&mut self, args: impl IntoIterator, IntoIter: ExactSizeIterator>) -> &mut Self { + link_args(self, args) + } + pub fn link_arg(&mut self, arg: impl AsRef) -> &mut Self { + link_args(self, iter::once(arg)) + } + pub fn cc_args(&mut self, args: impl IntoIterator>) -> &mut Self { + cc_args(self, args) + } + pub fn cc_arg(&mut self, arg: impl AsRef) -> &mut Self { + cc_args(self, iter::once(arg)) + } + pub fn link_or_cc_args(&mut self, args: impl IntoIterator>) -> &mut Self { + link_or_cc_args(self, args) + } + pub fn link_or_cc_arg(&mut self, arg: impl AsRef) -> &mut Self { + link_or_cc_args(self, iter::once(arg)) + } + } + )* } +} + +generate_arg_methods! { + GccLinker<'_> + MsvcLinker<'_> + EmLinker<'_> + WasmLd<'_> + L4Bender<'_> + AixLinker<'_> + LlbcLinker<'_> + PtxLinker<'_> + BpfLinker<'_> + dyn Linker + '_ +} + /// Linker abstraction used by `back::link` to build up the command to invoke a /// linker. /// @@ -168,6 +264,9 @@ pub fn get_linker<'a>( /// MSVC linker (e.g., `link.exe`) is being used. pub trait Linker { fn cmd(&mut self) -> &mut Command; + fn is_cc(&self) -> bool { + false + } fn set_output_kind(&mut self, output_kind: LinkOutputKind, out_filename: &Path); fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, as_needed: bool); fn link_framework_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) { @@ -175,10 +274,18 @@ pub trait Linker { } fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool, whole_archive: bool); fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool); - fn include_path(&mut self, path: &Path); - fn framework_path(&mut self, path: &Path); - fn output_filename(&mut self, path: &Path); - fn add_object(&mut self, path: &Path); + fn include_path(&mut self, path: &Path) { + link_or_cc_args(link_or_cc_args(self, &["-L"]), &[path]); + } + fn framework_path(&mut self, _path: &Path) { + bug!("framework path set with unsupported linker") + } + fn output_filename(&mut self, path: &Path) { + link_or_cc_args(link_or_cc_args(self, &["-o"]), &[path]); + } + fn add_object(&mut self, path: &Path) { + link_or_cc_args(self, &[path]); + } fn gc_sections(&mut self, keep_metadata: bool); fn no_gc_sections(&mut self); fn full_relro(&mut self); @@ -198,25 +305,9 @@ pub trait Linker { fn add_no_exec(&mut self) {} fn add_as_needed(&mut self) {} fn reset_per_library_state(&mut self) {} - fn linker_arg(&mut self, arg: &OsStr, verbatim: bool) { - self.linker_args(&[arg], verbatim); - } - fn linker_args(&mut self, args: &[&OsStr], _verbatim: bool) { - args.into_iter().for_each(|a| { - self.cmd().arg(a); - }); - } } impl dyn Linker + '_ { - pub fn arg(&mut self, arg: impl AsRef) { - self.cmd().arg(arg); - } - - pub fn args(&mut self, args: impl IntoIterator>) { - self.cmd().args(args); - } - pub fn take_cmd(&mut self) -> Command { mem::replace(self.cmd(), Command::new("")) } @@ -233,14 +324,6 @@ pub struct GccLinker<'a> { } impl<'a> GccLinker<'a> { - fn linker_arg(&mut self, arg: impl AsRef) { - Linker::linker_arg(self, arg.as_ref(), false); - } - fn linker_args(&mut self, args: &[impl AsRef]) { - let args_vec: Vec<&OsStr> = args.iter().map(|x| x.as_ref()).collect(); - Linker::linker_args(self, &args_vec, false); - } - fn takes_hints(&self) -> bool { // Really this function only returns true if the underlying linker // configured for a compiler is binutils `ld.bfd` and `ld.gold`. We @@ -262,7 +345,7 @@ impl<'a> GccLinker<'a> { return; } if self.hinted_static != Some(true) { - self.linker_arg("-Bstatic"); + self.link_arg("-Bstatic"); self.hinted_static = Some(true); } } @@ -272,7 +355,7 @@ impl<'a> GccLinker<'a> { return; } if self.hinted_static != Some(false) { - self.linker_arg("-Bdynamic"); + self.link_arg("-Bdynamic"); self.hinted_static = Some(false); } } @@ -281,7 +364,7 @@ impl<'a> GccLinker<'a> { if let Some(plugin_path) = plugin_path { let mut arg = OsString::from("-plugin="); arg.push(plugin_path); - self.linker_arg(&arg); + self.link_arg(&arg); } let opt_level = match self.sess.opts.optimize { @@ -292,9 +375,9 @@ impl<'a> GccLinker<'a> { }; if let Some(path) = &self.sess.opts.unstable_opts.profile_sample_use { - self.linker_arg(&format!("-plugin-opt=sample-profile={}", path.display())); + self.link_arg(&format!("-plugin-opt=sample-profile={}", path.display())); }; - self.linker_args(&[ + self.link_args(&[ &format!("-plugin-opt={opt_level}"), &format!("-plugin-opt=mcpu={}", self.target_cpu), ]); @@ -304,10 +387,10 @@ impl<'a> GccLinker<'a> { // On mac we need to tell the linker to let this library be rpathed if self.sess.target.is_like_osx { if !self.is_ld { - self.cmd.arg("-dynamiclib"); + self.cc_arg("-dynamiclib"); } - self.linker_arg("-dylib"); + self.link_arg("-dylib"); // Note that the `osx_rpath_install_name` option here is a hack // purely to support rustbuild right now, we should get a more @@ -316,10 +399,10 @@ impl<'a> GccLinker<'a> { if self.sess.opts.cg.rpath || self.sess.opts.unstable_opts.osx_rpath_install_name { let mut rpath = OsString::from("@rpath/"); rpath.push(out_filename.file_name().unwrap()); - self.linker_args(&[OsString::from("-install_name"), rpath]); + self.link_arg("-install_name").link_arg(rpath); } } else { - self.cmd.arg("-shared"); + self.link_or_cc_arg("-shared"); if self.sess.target.is_like_windows { // The output filename already contains `dll_suffix` so // the resulting import library will have a name in the @@ -336,7 +419,7 @@ impl<'a> GccLinker<'a> { if let Some(implib_name) = implib_name { let implib = out_filename.parent().map(|dir| dir.join(&implib_name)); if let Some(implib) = implib { - self.linker_arg(&format!("--out-implib={}", (*implib).to_str().unwrap())); + self.link_arg(&format!("--out-implib={}", (*implib).to_str().unwrap())); } } } @@ -345,76 +428,56 @@ impl<'a> GccLinker<'a> { } impl<'a> Linker for GccLinker<'a> { - /// Passes a series of arguments directly to the linker. - /// - /// When the linker is ld-like, the arguments are simply appended to the command. When the - /// linker is not ld-like such as when using a compiler as a linker, the arguments are joined by - /// commas to form an argument that is then prepended with `-Wl`. In this situation, only a - /// single argument is appended to the command to ensure that the order of the arguments is - /// preserved by the compiler. - fn linker_args(&mut self, args: &[&OsStr], verbatim: bool) { - if self.is_ld || verbatim { - args.into_iter().for_each(|a| { - self.cmd.arg(a); - }); - } else { - if !args.is_empty() { - let mut s = OsString::from("-Wl"); - for a in args { - s.push(","); - s.push(a); - } - self.cmd.arg(s); - } - } - } - fn cmd(&mut self) -> &mut Command { &mut self.cmd } + fn is_cc(&self) -> bool { + !self.is_ld + } + fn set_output_kind(&mut self, output_kind: LinkOutputKind, out_filename: &Path) { match output_kind { LinkOutputKind::DynamicNoPicExe => { if !self.is_ld && self.is_gnu { - self.cmd.arg("-no-pie"); + self.cc_arg("-no-pie"); } } LinkOutputKind::DynamicPicExe => { // noop on windows w/ gcc & ld, error w/ lld if !self.sess.target.is_like_windows { // `-pie` works for both gcc wrapper and ld. - self.cmd.arg("-pie"); + self.link_or_cc_arg("-pie"); } } LinkOutputKind::StaticNoPicExe => { // `-static` works for both gcc wrapper and ld. - self.cmd.arg("-static"); + self.link_or_cc_arg("-static"); if !self.is_ld && self.is_gnu { - self.cmd.arg("-no-pie"); + self.cc_arg("-no-pie"); } } LinkOutputKind::StaticPicExe => { if !self.is_ld { // Note that combination `-static -pie` doesn't work as expected // for the gcc wrapper, `-static` in that case suppresses `-pie`. - self.cmd.arg("-static-pie"); + self.cc_arg("-static-pie"); } else { // `--no-dynamic-linker` and `-z text` are not strictly necessary for producing // a static pie, but currently passed because gcc and clang pass them. // The former suppresses the `INTERP` ELF header specifying dynamic linker, // which is otherwise implicitly injected by ld (but not lld). // The latter doesn't change anything, only ensures that everything is pic. - self.cmd.args(&["-static", "-pie", "--no-dynamic-linker", "-z", "text"]); + self.link_args(&["-static", "-pie", "--no-dynamic-linker", "-z", "text"]); } } LinkOutputKind::DynamicDylib => self.build_dylib(out_filename), LinkOutputKind::StaticDylib => { - self.cmd.arg("-static"); + self.link_or_cc_arg("-static"); self.build_dylib(out_filename); } LinkOutputKind::WasiReactorExe => { - self.linker_args(&["--entry", "_initialize"]); + self.link_args(&["--entry", "_initialize"]); } } // VxWorks compiler driver introduced `--static-crt` flag specifically for rustc, @@ -430,7 +493,7 @@ impl<'a> Linker for GccLinker<'a> { | LinkOutputKind::StaticDylib ) { - self.cmd.arg("--static-crt"); + self.cc_arg("--static-crt"); } } @@ -450,18 +513,18 @@ impl<'a> Linker for GccLinker<'a> { // but we have no way to detect that here. self.sess.dcx().emit_warn(errors::Ld64UnimplementedModifier); } else if self.is_gnu && !self.sess.target.is_like_windows { - self.linker_arg("--no-as-needed"); + self.link_arg("--no-as-needed"); } else { self.sess.dcx().emit_warn(errors::LinkerUnsupportedModifier); } } self.hint_dynamic(); - self.cmd.arg(format!("-l{}{name}", if verbatim && self.is_gnu { ":" } else { "" },)); + self.link_or_cc_arg(format!("-l{}{name}", if verbatim && self.is_gnu { ":" } else { "" },)); if !as_needed { if self.sess.target.is_like_osx { // See above FIXME comment } else if self.is_gnu && !self.sess.target.is_like_windows { - self.linker_arg("--as-needed"); + self.link_arg("--as-needed"); } } } @@ -471,63 +534,51 @@ impl<'a> Linker for GccLinker<'a> { if !as_needed { // FIXME(81490): ld64 as of macOS 11 supports the -needed_framework // flag but we have no way to detect that here. - // self.cmd.arg("-needed_framework").arg(name); + // self.link_or_cc_arg("-needed_framework").link_or_cc_arg(name); self.sess.dcx().emit_warn(errors::Ld64UnimplementedModifier); } - self.cmd.arg("-framework").arg(name); + self.link_or_cc_args(&["-framework", name]); } fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool, whole_archive: bool) { self.hint_static(); let colon = if verbatim && self.is_gnu { ":" } else { "" }; if !whole_archive { - self.cmd.arg(format!("-l{colon}{name}")); + self.link_or_cc_arg(format!("-l{colon}{name}")); } else if self.sess.target.is_like_osx { // -force_load is the macOS equivalent of --whole-archive, but it // involves passing the full path to the library to link. - self.linker_arg("-force_load"); - self.linker_arg(find_native_static_library(name, verbatim, self.sess)); + self.link_arg("-force_load"); + self.link_arg(find_native_static_library(name, verbatim, self.sess)); } else { - self.linker_arg("--whole-archive"); - self.cmd.arg(format!("-l{colon}{name}")); - self.linker_arg("--no-whole-archive"); + self.link_arg("--whole-archive") + .link_or_cc_arg(format!("-l{colon}{name}")) + .link_arg("--no-whole-archive"); } } fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) { self.hint_static(); if !whole_archive { - self.cmd.arg(path); + self.link_or_cc_arg(path); } else if self.sess.target.is_like_osx { - self.linker_arg("-force_load"); - self.linker_arg(path); + self.link_arg("-force_load").link_arg(path); } else { - self.linker_arg("--whole-archive"); - self.linker_arg(path); - self.linker_arg("--no-whole-archive"); + self.link_arg("--whole-archive").link_arg(path).link_arg("--no-whole-archive"); } } - fn include_path(&mut self, path: &Path) { - self.cmd.arg("-L").arg(path); - } fn framework_path(&mut self, path: &Path) { - self.cmd.arg("-F").arg(path); - } - fn output_filename(&mut self, path: &Path) { - self.cmd.arg("-o").arg(path); - } - fn add_object(&mut self, path: &Path) { - self.cmd.arg(path); + self.link_or_cc_arg("-F").link_or_cc_arg(path); } fn full_relro(&mut self) { - self.linker_args(&["-z", "relro", "-z", "now"]); + self.link_args(&["-z", "relro", "-z", "now"]); } fn partial_relro(&mut self) { - self.linker_args(&["-z", "relro"]); + self.link_args(&["-z", "relro"]); } fn no_relro(&mut self) { - self.linker_args(&["-z", "norelro"]); + self.link_args(&["-z", "norelro"]); } fn gc_sections(&mut self, keep_metadata: bool) { @@ -546,7 +597,7 @@ impl<'a> Linker for GccLinker<'a> { // for partial linking when using multiple codegen units (-r). So we // insert it here. if self.sess.target.is_like_osx { - self.linker_arg("-dead_strip"); + self.link_arg("-dead_strip"); // If we're building a dylib, we don't use --gc-sections because LLVM // has already done the best it can do, and we also don't want to @@ -554,13 +605,13 @@ impl<'a> Linker for GccLinker<'a> { // --gc-sections drops the size of hello world from 1.8MB to 597K, a 67% // reduction. } else if (self.is_gnu || self.sess.target.is_like_wasm) && !keep_metadata { - self.linker_arg("--gc-sections"); + self.link_arg("--gc-sections"); } } fn no_gc_sections(&mut self) { if self.is_gnu || self.sess.target.is_like_wasm { - self.linker_arg("--no-gc-sections"); + self.link_arg("--no-gc-sections"); } } @@ -574,7 +625,7 @@ impl<'a> Linker for GccLinker<'a> { if self.sess.opts.optimize == config::OptLevel::Default || self.sess.opts.optimize == config::OptLevel::Aggressive { - self.linker_arg("-O1"); + self.link_arg("-O1"); } } @@ -594,8 +645,7 @@ impl<'a> Linker for GccLinker<'a> { // // Though it may be worth to try to revert those changes upstream, since // the overhead of the initialization should be minor. - self.cmd.arg("-u"); - self.cmd.arg("__llvm_profile_runtime"); + self.link_or_cc_args(&["-u", "__llvm_profile_runtime"]); } fn control_flow_guard(&mut self) {} @@ -616,33 +666,33 @@ impl<'a> Linker for GccLinker<'a> { // The --strip-debug case is handled by running an external // `strip` utility as a separate step after linking. if !self.sess.target.is_like_solaris { - self.linker_arg("--strip-debug"); + self.link_arg("--strip-debug"); } } Strip::Symbols => { - self.linker_arg("--strip-all"); + self.link_arg("--strip-all"); } } match self.sess.opts.unstable_opts.debuginfo_compression { config::DebugInfoCompression::None => {} config::DebugInfoCompression::Zlib => { - self.linker_arg("--compress-debug-sections=zlib"); + self.link_arg("--compress-debug-sections=zlib"); } config::DebugInfoCompression::Zstd => { - self.linker_arg("--compress-debug-sections=zstd"); + self.link_arg("--compress-debug-sections=zstd"); } } } fn no_crt_objects(&mut self) { if !self.is_ld { - self.cmd.arg("-nostartfiles"); + self.cc_arg("-nostartfiles"); } } fn no_default_libraries(&mut self) { if !self.is_ld { - self.cmd.arg("-nodefaultlibs"); + self.cc_arg("-nodefaultlibs"); } } @@ -718,24 +768,22 @@ impl<'a> Linker for GccLinker<'a> { } if self.sess.target.is_like_osx { - self.linker_args(&[OsString::from("-exported_symbols_list"), path.into()]); + self.link_arg("-exported_symbols_list").link_arg(path); } else if self.sess.target.is_like_solaris { - self.linker_args(&[OsString::from("-M"), path.into()]); + self.link_arg("-M").link_arg(path); } else { if is_windows { - self.linker_arg(path); + self.link_arg(path); } else { let mut arg = OsString::from("--version-script="); arg.push(path); - self.linker_arg(arg); - self.linker_arg("--no-undefined-version"); + self.link_arg(arg).link_arg("--no-undefined-version"); } } } fn subsystem(&mut self, subsystem: &str) { - self.linker_arg("--subsystem"); - self.linker_arg(&subsystem); + self.link_args(&["--subsystem", subsystem]); } fn reset_per_library_state(&mut self) { @@ -760,23 +808,23 @@ impl<'a> Linker for GccLinker<'a> { // Some versions of `gcc` add it implicitly, some (e.g. `musl-gcc`) don't, // so we just always add it. fn add_eh_frame_header(&mut self) { - self.linker_arg("--eh-frame-hdr"); + self.link_arg("--eh-frame-hdr"); } fn add_no_exec(&mut self) { if self.sess.target.is_like_windows { - self.linker_arg("--nxcompat"); + self.link_arg("--nxcompat"); } else if self.is_gnu { - self.linker_args(&["-z", "noexecstack"]); + self.link_args(&["-z", "noexecstack"]); } } fn add_as_needed(&mut self) { if self.is_gnu && !self.sess.target.is_like_windows { - self.linker_arg("--as-needed"); + self.link_arg("--as-needed"); } else if self.sess.target.is_like_solaris { // -z ignore is the Solaris equivalent to the GNU ld --as-needed option - self.linker_args(&["-z", "ignore"]); + self.link_args(&["-z", "ignore"]); } } } @@ -798,10 +846,10 @@ impl<'a> Linker for MsvcLinker<'a> { | LinkOutputKind::StaticNoPicExe | LinkOutputKind::StaticPicExe => {} LinkOutputKind::DynamicDylib | LinkOutputKind::StaticDylib => { - self.cmd.arg("/DLL"); + self.link_arg("/DLL"); let mut arg: OsString = "/IMPLIB:".into(); arg.push(out_filename.with_extension("dll.lib")); - self.cmd.arg(arg); + self.link_arg(arg); } LinkOutputKind::WasiReactorExe => { panic!("can't link as reactor on non-wasi target"); @@ -810,44 +858,40 @@ impl<'a> Linker for MsvcLinker<'a> { } fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, _as_needed: bool) { - self.cmd.arg(format!("{}{}", name, if verbatim { "" } else { ".lib" })); + self.link_arg(format!("{}{}", name, if verbatim { "" } else { ".lib" })); } fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool, whole_archive: bool) { let prefix = if whole_archive { "/WHOLEARCHIVE:" } else { "" }; let suffix = if verbatim { "" } else { ".lib" }; - self.cmd.arg(format!("{prefix}{name}{suffix}")); + self.link_arg(format!("{prefix}{name}{suffix}")); } fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) { if !whole_archive { - self.cmd.arg(path); + self.link_arg(path); } else { let mut arg = OsString::from("/WHOLEARCHIVE:"); arg.push(path); - self.cmd.arg(arg); + self.link_arg(arg); } } - fn add_object(&mut self, path: &Path) { - self.cmd.arg(path); - } - fn gc_sections(&mut self, _keep_metadata: bool) { // MSVC's ICF (Identical COMDAT Folding) link optimization is // slow for Rust and thus we disable it by default when not in // optimization build. if self.sess.opts.optimize != config::OptLevel::No { - self.cmd.arg("/OPT:REF,ICF"); + self.link_arg("/OPT:REF,ICF"); } else { // It is necessary to specify NOICF here, because /OPT:REF // implies ICF by default. - self.cmd.arg("/OPT:REF,NOICF"); + self.link_arg("/OPT:REF,NOICF"); } } fn no_gc_sections(&mut self) { - self.cmd.arg("/OPT:NOREF,NOICF"); + self.link_arg("/OPT:NOREF,NOICF"); } fn full_relro(&mut self) { @@ -867,23 +911,19 @@ impl<'a> Linker for MsvcLinker<'a> { } fn no_default_libraries(&mut self) { - self.cmd.arg("/NODEFAULTLIB"); + self.link_arg("/NODEFAULTLIB"); } fn include_path(&mut self, path: &Path) { let mut arg = OsString::from("/LIBPATH:"); arg.push(path); - self.cmd.arg(&arg); + self.link_arg(&arg); } fn output_filename(&mut self, path: &Path) { let mut arg = OsString::from("/OUT:"); arg.push(path); - self.cmd.arg(&arg); - } - - fn framework_path(&mut self, _path: &Path) { - bug!("frameworks are not supported on windows") + self.link_arg(&arg); } fn optimize(&mut self) { @@ -895,19 +935,19 @@ impl<'a> Linker for MsvcLinker<'a> { } fn control_flow_guard(&mut self) { - self.cmd.arg("/guard:cf"); + self.link_arg("/guard:cf"); } fn ehcont_guard(&mut self) { if self.sess.target.pointer_width == 64 { - self.cmd.arg("/guard:ehcont"); + self.link_arg("/guard:ehcont"); } } fn debuginfo(&mut self, _strip: Strip, natvis_debugger_visualizers: &[PathBuf]) { // This will cause the Microsoft linker to generate a PDB file // from the CodeView line tables in the object files. - self.cmd.arg("/DEBUG"); + self.link_arg("/DEBUG"); // Default to emitting only the file name of the PDB file into // the binary instead of the full path. Emitting the full path @@ -916,7 +956,7 @@ impl<'a> Linker for MsvcLinker<'a> { // // This default behavior can be overridden by explicitly passing // `-Clink-arg=/PDBALTPATH:...` to rustc. - self.cmd.arg("/PDBALTPATH:%_PDB%"); + self.link_arg("/PDBALTPATH:%_PDB%"); // This will cause the Microsoft linker to embed .natvis info into the PDB file let natvis_dir_path = self.sess.sysroot.join("lib\\rustlib\\etc"); @@ -928,7 +968,7 @@ impl<'a> Linker for MsvcLinker<'a> { if path.extension() == Some("natvis".as_ref()) { let mut arg = OsString::from("/NATVIS:"); arg.push(path); - self.cmd.arg(arg); + self.link_arg(arg); } } Err(error) => { @@ -942,7 +982,7 @@ impl<'a> Linker for MsvcLinker<'a> { for path in natvis_debugger_visualizers { let mut arg = OsString::from("/NATVIS:"); arg.push(path); - self.cmd.arg(arg); + self.link_arg(arg); } } @@ -986,13 +1026,13 @@ impl<'a> Linker for MsvcLinker<'a> { } let mut arg = OsString::from("/DEF:"); arg.push(path); - self.cmd.arg(&arg); + self.link_arg(&arg); } fn subsystem(&mut self, subsystem: &str) { // Note that previous passes of the compiler validated this subsystem, // so we just blindly pass it to the linker. - self.cmd.arg(&format!("/SUBSYSTEM:{subsystem}")); + self.link_arg(&format!("/SUBSYSTEM:{subsystem}")); // Windows has two subsystems we're interested in right now, the console // and windows subsystems. These both implicitly have different entry @@ -1009,7 +1049,7 @@ impl<'a> Linker for MsvcLinker<'a> { // // For more information see RFC #1665 if subsystem == "windows" { - self.cmd.arg("/ENTRY:mainCRTStartup"); + self.link_arg("/ENTRY:mainCRTStartup"); } } @@ -1018,7 +1058,7 @@ impl<'a> Linker for MsvcLinker<'a> { } fn add_no_exec(&mut self) { - self.cmd.arg("/NXCOMPAT"); + self.link_arg("/NXCOMPAT"); } } @@ -1032,31 +1072,23 @@ impl<'a> Linker for EmLinker<'a> { &mut self.cmd } + fn is_cc(&self) -> bool { + true + } + fn set_output_kind(&mut self, _output_kind: LinkOutputKind, _out_filename: &Path) {} fn link_dylib_by_name(&mut self, name: &str, _verbatim: bool, _as_needed: bool) { // Emscripten always links statically - self.cmd.arg("-l").arg(name); + self.link_or_cc_args(&["-l", name]); } fn link_staticlib_by_name(&mut self, name: &str, _verbatim: bool, _whole_archive: bool) { - self.cmd.arg("-l").arg(name); + self.link_or_cc_args(&["-l", name]); } fn link_staticlib_by_path(&mut self, path: &Path, _whole_archive: bool) { - self.cmd.arg(path); - } - - fn include_path(&mut self, path: &Path) { - self.cmd.arg("-L").arg(path); - } - - fn output_filename(&mut self, path: &Path) { - self.cmd.arg("-o").arg(path); - } - - fn add_object(&mut self, path: &Path) { - self.cmd.arg(path); + self.link_or_cc_arg(path); } fn full_relro(&mut self) { @@ -1071,10 +1103,6 @@ impl<'a> Linker for EmLinker<'a> { // noop } - fn framework_path(&mut self, _path: &Path) { - bug!("frameworks are not supported on Emscripten") - } - fn gc_sections(&mut self, _keep_metadata: bool) { // noop } @@ -1085,7 +1113,7 @@ impl<'a> Linker for EmLinker<'a> { fn optimize(&mut self) { // Emscripten performs own optimizations - self.cmd.arg(match self.sess.opts.optimize { + self.cc_arg(match self.sess.opts.optimize { OptLevel::No => "-O0", OptLevel::Less => "-O1", OptLevel::Default => "-O2", @@ -1106,7 +1134,7 @@ impl<'a> Linker for EmLinker<'a> { fn debuginfo(&mut self, _strip: Strip, _: &[PathBuf]) { // Preserve names or generate source maps depending on debug info // For more information see https://emscripten.org/docs/tools_reference/emcc.html#emcc-g - self.cmd.arg(match self.sess.opts.debuginfo { + self.cc_arg(match self.sess.opts.debuginfo { DebugInfo::None => "-g0", DebugInfo::Limited | DebugInfo::LineTablesOnly | DebugInfo::LineDirectivesOnly => { "--profiling-funcs" @@ -1118,13 +1146,13 @@ impl<'a> Linker for EmLinker<'a> { fn no_crt_objects(&mut self) {} fn no_default_libraries(&mut self) { - self.cmd.arg("-nodefaultlibs"); + self.cc_arg("-nodefaultlibs"); } fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) { debug!("EXPORTED SYMBOLS:"); - self.cmd.arg("-s"); + self.cc_arg("-s"); let mut arg = OsString::from("EXPORTED_FUNCTIONS="); let encoded = serde_json::to_string( @@ -1135,7 +1163,7 @@ impl<'a> Linker for EmLinker<'a> { arg.push(encoded); - self.cmd.arg(arg); + self.cc_arg(arg); } fn subsystem(&mut self, _subsystem: &str) { @@ -1153,7 +1181,7 @@ pub struct WasmLd<'a> { } impl<'a> WasmLd<'a> { - fn new(mut cmd: Command, sess: &'a Session) -> WasmLd<'a> { + fn new(cmd: Command, sess: &'a Session) -> WasmLd<'a> { // If the atomics feature is enabled for wasm then we need a whole bunch // of flags: // @@ -1172,18 +1200,19 @@ impl<'a> WasmLd<'a> { // On wasm32-unknown-unknown, we also export symbols for glue code to use: // * `--export=*tls*` - when `#[thread_local]` symbols are used these // symbols are how the TLS segments are initialized and configured. + let mut wasm_ld = WasmLd { cmd, sess }; if sess.target_features.contains(&sym::atomics) { - cmd.arg("--shared-memory"); - cmd.arg("--max-memory=1073741824"); - cmd.arg("--import-memory"); + wasm_ld.link_args(&["--shared-memory", "--max-memory=1073741824", "--import-memory"]); if sess.target.os == "unknown" { - cmd.arg("--export=__wasm_init_tls"); - cmd.arg("--export=__tls_size"); - cmd.arg("--export=__tls_align"); - cmd.arg("--export=__tls_base"); + wasm_ld.link_args(&[ + "--export=__wasm_init_tls", + "--export=__tls_size", + "--export=__tls_align", + "--export=__tls_base", + ]); } } - WasmLd { cmd, sess } + wasm_ld } } @@ -1199,51 +1228,36 @@ impl<'a> Linker for WasmLd<'a> { | LinkOutputKind::StaticNoPicExe | LinkOutputKind::StaticPicExe => {} LinkOutputKind::DynamicDylib | LinkOutputKind::StaticDylib => { - self.cmd.arg("--no-entry"); + self.link_arg("--no-entry"); } LinkOutputKind::WasiReactorExe => { - self.cmd.arg("--entry"); - self.cmd.arg("_initialize"); + self.link_args(&["--entry", "_initialize"]); } } } fn link_dylib_by_name(&mut self, name: &str, _verbatim: bool, _as_needed: bool) { - self.cmd.arg("-l").arg(name); + self.link_or_cc_args(&["-l", name]); } fn link_staticlib_by_name(&mut self, name: &str, _verbatim: bool, whole_archive: bool) { if !whole_archive { - self.cmd.arg("-l").arg(name); + self.link_or_cc_args(&["-l", name]); } else { - self.cmd.arg("--whole-archive").arg("-l").arg(name).arg("--no-whole-archive"); + self.link_arg("--whole-archive") + .link_or_cc_args(&["-l", name]) + .link_arg("--no-whole-archive"); } } fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) { if !whole_archive { - self.cmd.arg(path); + self.link_or_cc_arg(path); } else { - self.cmd.arg("--whole-archive").arg(path).arg("--no-whole-archive"); + self.link_arg("--whole-archive").link_or_cc_arg(path).link_arg("--no-whole-archive"); } } - fn include_path(&mut self, path: &Path) { - self.cmd.arg("-L").arg(path); - } - - fn framework_path(&mut self, _path: &Path) { - panic!("frameworks not supported") - } - - fn output_filename(&mut self, path: &Path) { - self.cmd.arg("-o").arg(path); - } - - fn add_object(&mut self, path: &Path) { - self.cmd.arg(path); - } - fn full_relro(&mut self) {} fn partial_relro(&mut self) {} @@ -1251,17 +1265,17 @@ impl<'a> Linker for WasmLd<'a> { fn no_relro(&mut self) {} fn gc_sections(&mut self, _keep_metadata: bool) { - self.cmd.arg("--gc-sections"); + self.link_arg("--gc-sections"); } fn no_gc_sections(&mut self) { - self.cmd.arg("--no-gc-sections"); + self.link_arg("--no-gc-sections"); } fn optimize(&mut self) { // The -O flag is, as of late 2023, only used for merging of strings and debuginfo, and // only differentiates -O0 and -O1. It does not apply to LTO. - self.cmd.arg(match self.sess.opts.optimize { + self.link_arg(match self.sess.opts.optimize { OptLevel::No => "-O0", OptLevel::Less => "-O1", OptLevel::Default => "-O2", @@ -1279,10 +1293,10 @@ impl<'a> Linker for WasmLd<'a> { match strip { Strip::None => {} Strip::Debuginfo => { - self.cmd.arg("--strip-debug"); + self.link_arg("--strip-debug"); } Strip::Symbols => { - self.cmd.arg("--strip-all"); + self.link_arg("--strip-all"); } } } @@ -1297,7 +1311,7 @@ impl<'a> Linker for WasmLd<'a> { fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) { for sym in symbols { - self.cmd.arg("--export").arg(&sym); + self.link_args(&["--export", sym]); } // LLD will hide these otherwise-internal symbols since it only exports @@ -1305,8 +1319,7 @@ impl<'a> Linker for WasmLd<'a> { // others. Various bits and pieces of wasm32-unknown-unknown tooling use // this, so be sure these symbols make their way out of the linker as well. if self.sess.target.os == "unknown" { - self.cmd.arg("--export=__heap_base"); - self.cmd.arg("--export=__data_end"); + self.link_args(&["--export=__heap_base", "--export=__data_end"]); } } @@ -1337,7 +1350,7 @@ impl<'a> WasmLd<'a> { // wasm-ld only handles integer LTO opt levels. Use O2 config::OptLevel::Size | config::OptLevel::SizeMin => "O2", }; - self.cmd.arg(&format!("--lto-{opt_level}")); + self.link_arg(&format!("--lto-{opt_level}")); } } @@ -1362,56 +1375,43 @@ impl<'a> Linker for L4Bender<'a> { fn link_staticlib_by_name(&mut self, name: &str, _verbatim: bool, whole_archive: bool) { self.hint_static(); if !whole_archive { - self.cmd.arg(format!("-PC{name}")); + self.link_arg(format!("-PC{name}")); } else { - self.cmd.arg("--whole-archive").arg(format!("-l{name}")).arg("--no-whole-archive"); + self.link_arg("--whole-archive") + .link_or_cc_arg(format!("-l{name}")) + .link_arg("--no-whole-archive"); } } fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) { self.hint_static(); if !whole_archive { - self.cmd.arg(path); + self.link_or_cc_arg(path); } else { - self.cmd.arg("--whole-archive").arg(path).arg("--no-whole-archive"); + self.link_arg("--whole-archive").link_or_cc_arg(path).link_arg("--no-whole-archive"); } } - fn include_path(&mut self, path: &Path) { - self.cmd.arg("-L").arg(path); - } - fn framework_path(&mut self, _: &Path) { - bug!("frameworks are not supported on L4Re"); - } - fn output_filename(&mut self, path: &Path) { - self.cmd.arg("-o").arg(path); - } - - fn add_object(&mut self, path: &Path) { - self.cmd.arg(path); - } - fn full_relro(&mut self) { - self.cmd.arg("-z").arg("relro"); - self.cmd.arg("-z").arg("now"); + self.link_args(&["-z", "relro", "-z", "now"]); } fn partial_relro(&mut self) { - self.cmd.arg("-z").arg("relro"); + self.link_args(&["-z", "relro"]); } fn no_relro(&mut self) { - self.cmd.arg("-z").arg("norelro"); + self.link_args(&["-z", "norelro"]); } fn gc_sections(&mut self, keep_metadata: bool) { if !keep_metadata { - self.cmd.arg("--gc-sections"); + self.link_arg("--gc-sections"); } } fn no_gc_sections(&mut self) { - self.cmd.arg("--no-gc-sections"); + self.link_arg("--no-gc-sections"); } fn optimize(&mut self) { @@ -1420,7 +1420,7 @@ impl<'a> Linker for L4Bender<'a> { if self.sess.opts.optimize == config::OptLevel::Default || self.sess.opts.optimize == config::OptLevel::Aggressive { - self.cmd.arg("-O1"); + self.link_arg("-O1"); } } @@ -1430,16 +1430,16 @@ impl<'a> Linker for L4Bender<'a> { match strip { Strip::None => {} Strip::Debuginfo => { - self.cmd().arg("--strip-debug"); + self.link_arg("--strip-debug"); } Strip::Symbols => { - self.cmd().arg("--strip-all"); + self.link_arg("--strip-all"); } } } fn no_default_libraries(&mut self) { - self.cmd.arg("-nostdlib"); + self.cc_arg("-nostdlib"); } fn export_symbols(&mut self, _: &Path, _: CrateType, _: &[String]) { @@ -1449,7 +1449,7 @@ impl<'a> Linker for L4Bender<'a> { } fn subsystem(&mut self, subsystem: &str) { - self.cmd.arg(&format!("--subsystem {subsystem}")); + self.link_arg(&format!("--subsystem {subsystem}")); } fn reset_per_library_state(&mut self) { @@ -1467,12 +1467,12 @@ impl<'a> Linker for L4Bender<'a> { impl<'a> L4Bender<'a> { pub fn new(cmd: Command, sess: &'a Session) -> L4Bender<'a> { - L4Bender { cmd: cmd, sess: sess, hinted_static: false } + L4Bender { cmd, sess: sess, hinted_static: false } } fn hint_static(&mut self) { if !self.hinted_static { - self.cmd.arg("-static"); + self.link_or_cc_arg("-static"); self.hinted_static = true; } } @@ -1487,29 +1487,28 @@ pub struct AixLinker<'a> { impl<'a> AixLinker<'a> { pub fn new(cmd: Command, sess: &'a Session) -> AixLinker<'a> { - AixLinker { cmd: cmd, sess: sess, hinted_static: None } + AixLinker { cmd, sess: sess, hinted_static: None } } fn hint_static(&mut self) { if self.hinted_static != Some(true) { - self.cmd.arg("-bstatic"); + self.link_arg("-bstatic"); self.hinted_static = Some(true); } } fn hint_dynamic(&mut self) { if self.hinted_static != Some(false) { - self.cmd.arg("-bdynamic"); + self.link_arg("-bdynamic"); self.hinted_static = Some(false); } } fn build_dylib(&mut self, _out_filename: &Path) { - self.cmd.arg("-bM:SRE"); - self.cmd.arg("-bnoentry"); + self.link_args(&["-bM:SRE", "-bnoentry"]); // FIXME: Use CreateExportList utility to create export list // and remove -bexpfull. - self.cmd.arg("-bexpfull"); + self.link_arg("-bexpfull"); } } @@ -1534,47 +1533,31 @@ impl<'a> Linker for AixLinker<'a> { fn link_dylib_by_name(&mut self, name: &str, _verbatim: bool, _as_needed: bool) { self.hint_dynamic(); - self.cmd.arg(format!("-l{name}")); + self.link_or_cc_arg(format!("-l{name}")); } fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool, whole_archive: bool) { self.hint_static(); if !whole_archive { - self.cmd.arg(format!("-l{name}")); + self.link_or_cc_arg(format!("-l{name}")); } else { let mut arg = OsString::from("-bkeepfile:"); arg.push(find_native_static_library(name, verbatim, self.sess)); - self.cmd.arg(arg); + self.link_or_cc_arg(arg); } } fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) { self.hint_static(); if !whole_archive { - self.cmd.arg(path); + self.link_or_cc_arg(path); } else { let mut arg = OsString::from("-bkeepfile:"); arg.push(path); - self.cmd.arg(arg); + self.link_arg(arg); } } - fn include_path(&mut self, path: &Path) { - self.cmd.arg("-L").arg(path); - } - - fn framework_path(&mut self, _: &Path) { - bug!("frameworks are not supported on AIX"); - } - - fn output_filename(&mut self, path: &Path) { - self.cmd.arg("-o").arg(path); - } - - fn add_object(&mut self, path: &Path) { - self.cmd.arg(path); - } - fn full_relro(&mut self) {} fn partial_relro(&mut self) {} @@ -1582,17 +1565,17 @@ impl<'a> Linker for AixLinker<'a> { fn no_relro(&mut self) {} fn gc_sections(&mut self, _keep_metadata: bool) { - self.cmd.arg("-bgc"); + self.link_arg("-bgc"); } fn no_gc_sections(&mut self) { - self.cmd.arg("-bnogc"); + self.link_arg("-bnogc"); } fn optimize(&mut self) {} fn pgo_gen(&mut self) { - self.cmd.arg("-bdbg:namedsects:ss"); + self.link_arg("-bdbg:namedsects:ss"); } fn control_flow_guard(&mut self) {} @@ -1618,7 +1601,7 @@ impl<'a> Linker for AixLinker<'a> { if let Err(e) = res { self.sess.dcx().fatal(format!("failed to write export file: {e}")); } - self.cmd.arg(format!("-bE:{}", path.to_str().unwrap())); + self.link_arg(format!("-bE:{}", path.to_str().unwrap())); } fn subsystem(&mut self, _subsystem: &str) {} @@ -1747,39 +1730,27 @@ impl<'a> Linker for PtxLinker<'a> { } fn link_staticlib_by_path(&mut self, path: &Path, _whole_archive: bool) { - self.cmd.arg("--rlib").arg(path); - } - - fn include_path(&mut self, path: &Path) { - self.cmd.arg("-L").arg(path); + self.link_arg("--rlib").link_arg(path); } fn debuginfo(&mut self, _strip: Strip, _: &[PathBuf]) { - self.cmd.arg("--debug"); + self.link_arg("--debug"); } fn add_object(&mut self, path: &Path) { - self.cmd.arg("--bitcode").arg(path); + self.link_arg("--bitcode").link_arg(path); } fn optimize(&mut self) { match self.sess.lto() { Lto::Thin | Lto::Fat | Lto::ThinLocal => { - self.cmd.arg("-Olto"); + self.link_arg("-Olto"); } Lto::No => {} } } - fn output_filename(&mut self, path: &Path) { - self.cmd.arg("-o").arg(path); - } - - fn framework_path(&mut self, _path: &Path) { - panic!("frameworks not supported") - } - fn full_relro(&mut self) {} fn partial_relro(&mut self) {} @@ -1829,19 +1800,11 @@ impl<'a> Linker for LlbcLinker<'a> { } fn link_staticlib_by_path(&mut self, path: &Path, _whole_archive: bool) { - self.cmd.arg(path); - } - - fn include_path(&mut self, path: &Path) { - self.cmd.arg("-L").arg(path); + self.link_or_cc_arg(path); } fn debuginfo(&mut self, _strip: Strip, _: &[PathBuf]) { - self.cmd.arg("--debug"); - } - - fn add_object(&mut self, path: &Path) { - self.cmd.arg(path); + self.link_arg("--debug"); } fn optimize(&mut self) { @@ -1855,14 +1818,6 @@ impl<'a> Linker for LlbcLinker<'a> { }; } - fn output_filename(&mut self, path: &Path) { - self.cmd.arg("-o").arg(path); - } - - fn framework_path(&mut self, _path: &Path) { - panic!("frameworks not supported") - } - fn full_relro(&mut self) {} fn partial_relro(&mut self) {} @@ -1887,7 +1842,7 @@ impl<'a> Linker for LlbcLinker<'a> { match _crate_type { CrateType::Cdylib => { for sym in symbols { - self.cmd.arg("--export-symbol").arg(sym); + self.link_args(&["--export-symbol", sym]); } } _ => (), @@ -1920,23 +1875,15 @@ impl<'a> Linker for BpfLinker<'a> { } fn link_staticlib_by_path(&mut self, path: &Path, _whole_archive: bool) { - self.cmd.arg(path); - } - - fn include_path(&mut self, path: &Path) { - self.cmd.arg("-L").arg(path); + self.link_or_cc_arg(path); } fn debuginfo(&mut self, _strip: Strip, _: &[PathBuf]) { - self.cmd.arg("--debug"); - } - - fn add_object(&mut self, path: &Path) { - self.cmd.arg(path); + self.link_arg("--debug"); } fn optimize(&mut self) { - self.cmd.arg(match self.sess.opts.optimize { + self.link_arg(match self.sess.opts.optimize { OptLevel::No => "-O0", OptLevel::Less => "-O1", OptLevel::Default => "-O2", @@ -1946,14 +1893,6 @@ impl<'a> Linker for BpfLinker<'a> { }); } - fn output_filename(&mut self, path: &Path) { - self.cmd.arg("-o").arg(path); - } - - fn framework_path(&mut self, _path: &Path) { - panic!("frameworks not supported") - } - fn full_relro(&mut self) {} fn partial_relro(&mut self) {} @@ -1985,7 +1924,7 @@ impl<'a> Linker for BpfLinker<'a> { if let Err(error) = res { self.sess.dcx().emit_fatal(errors::SymbolFileWriteFailure { error }); } else { - self.cmd.arg("--export-symbols").arg(&path); + self.link_arg("--export-symbols").link_arg(&path); } } diff --git a/compiler/rustc_codegen_ssa/src/back/rpath.rs b/compiler/rustc_codegen_ssa/src/back/rpath.rs index f499bbcf85339..82070d4453b28 100644 --- a/compiler/rustc_codegen_ssa/src/back/rpath.rs +++ b/compiler/rustc_codegen_ssa/src/back/rpath.rs @@ -9,16 +9,10 @@ pub struct RPathConfig<'a> { pub libs: &'a [&'a Path], pub out_filename: PathBuf, pub is_like_osx: bool, - pub has_rpath: bool, pub linker_is_gnu: bool, } pub fn get_rpath_flags(config: &RPathConfig<'_>) -> Vec { - // No rpath on windows - if !config.has_rpath { - return Vec::new(); - } - debug!("preparing the RPATH!"); let rpaths = get_rpaths(config); diff --git a/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs b/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs index 0de90a1036ec5..c620e92db1f08 100644 --- a/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs +++ b/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs @@ -37,7 +37,6 @@ fn test_rpath_relative() { if cfg!(target_os = "macos") { let config = &mut RPathConfig { libs: &[], - has_rpath: true, is_like_osx: true, linker_is_gnu: false, out_filename: PathBuf::from("bin/rustc"), @@ -48,7 +47,6 @@ fn test_rpath_relative() { let config = &mut RPathConfig { libs: &[], out_filename: PathBuf::from("bin/rustc"), - has_rpath: true, is_like_osx: false, linker_is_gnu: true, }; @@ -62,7 +60,6 @@ fn test_rpath_relative_issue_119571() { let config = &mut RPathConfig { libs: &[], out_filename: PathBuf::from("rustc"), - has_rpath: true, is_like_osx: false, linker_is_gnu: true, }; diff --git a/compiler/rustc_codegen_ssa/src/meth.rs b/compiler/rustc_codegen_ssa/src/meth.rs index ddc6797388e77..febc8ee2be248 100644 --- a/compiler/rustc_codegen_ssa/src/meth.rs +++ b/compiler/rustc_codegen_ssa/src/meth.rs @@ -133,6 +133,7 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>( let align = cx.data_layout().pointer_align.abi; let vtable = cx.static_addr_of(vtable_const, align, Some("vtable")); + cx.apply_vcall_visibility_metadata(ty, trait_ref, vtable); cx.create_vtable_debuginfo(ty, trait_ref, vtable); cx.vtables().borrow_mut().insert((ty, trait_ref), vtable); vtable diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 57138d3b9dbdb..b1c22faf1ae9d 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -658,7 +658,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // with #[rustc_inherit_overflow_checks] and inlined from // another crate (mostly core::num generic/#[inline] fns), // while the current crate doesn't use overflow checks. - if !bx.cx().check_overflow() && msg.is_optional_overflow_check() { + if !bx.sess().overflow_checks() && msg.is_optional_overflow_check() { const_cond = Some(expected); } @@ -751,7 +751,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &mut self, helper: &TerminatorCodegenHelper<'tcx>, bx: &mut Bx, - intrinsic: Option, + intrinsic: ty::IntrinsicDef, instance: Option>, source_info: mir::SourceInfo, target: Option, @@ -761,8 +761,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Emit a panic or a no-op for `assert_*` intrinsics. // These are intrinsics that compile to panics so that we can get a message // which mentions the offending type, even from a const context. - let panic_intrinsic = intrinsic.and_then(|i| ValidityRequirement::from_intrinsic(i.name)); - if let Some(requirement) = panic_intrinsic { + if let Some(requirement) = ValidityRequirement::from_intrinsic(intrinsic.name) { let ty = instance.unwrap().args.type_at(0); let do_panic = !bx @@ -869,12 +868,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let sig = callee.layout.ty.fn_sig(bx.tcx()); let abi = sig.abi(); - // Handle intrinsics old codegen wants Expr's for, ourselves. - let intrinsic = match def { - Some(ty::InstanceKind::Intrinsic(def_id)) => Some(bx.tcx().intrinsic(def_id).unwrap()), - _ => None, - }; - let extra_args = &args[sig.inputs().skip_binder().len()..]; let extra_args = bx.tcx().mk_type_list_from_iter(extra_args.iter().map(|op_arg| { let op_ty = op_arg.node.ty(self.mir, bx.tcx()); @@ -886,50 +879,25 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { None => bx.fn_abi_of_fn_ptr(sig, extra_args), }; - if let Some(merging_succ) = self.codegen_panic_intrinsic( - &helper, - bx, - intrinsic, - instance, - source_info, - target, - unwind, - mergeable_succ, - ) { - return merging_succ; - } - // The arguments we'll be passing. Plus one to account for outptr, if used. let arg_count = fn_abi.args.len() + fn_abi.ret.is_indirect() as usize; - if matches!(intrinsic, Some(ty::IntrinsicDef { name: sym::caller_location, .. })) { - return if let Some(target) = target { - let location = - self.get_caller_location(bx, mir::SourceInfo { span: fn_span, ..source_info }); - - let mut llargs = Vec::with_capacity(arg_count); - let ret_dest = self.make_return_dest( + let instance = match def { + Some(ty::InstanceKind::Intrinsic(def_id)) => { + let intrinsic = bx.tcx().intrinsic(def_id).unwrap(); + if let Some(merging_succ) = self.codegen_panic_intrinsic( + &helper, bx, - destination, - &fn_abi.ret, - &mut llargs, intrinsic, - Some(target), - ); - assert_eq!(llargs, []); - if let ReturnDest::IndirectOperand(tmp, _) = ret_dest { - location.val.store(bx, tmp); + instance, + source_info, + target, + unwind, + mergeable_succ, + ) { + return merging_succ; } - self.store_return(bx, ret_dest, &fn_abi.ret, location.immediate()); - helper.funclet_br(self, bx, target, mergeable_succ) - } else { - MergingSucc::False - }; - } - let instance = match intrinsic { - None => instance, - Some(intrinsic) => { let mut llargs = Vec::with_capacity(1); let ret_dest = self.make_return_dest( bx, @@ -971,6 +939,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }) .collect(); + if matches!(intrinsic, ty::IntrinsicDef { name: sym::caller_location, .. }) { + let location = self + .get_caller_location(bx, mir::SourceInfo { span: fn_span, ..source_info }); + + assert_eq!(llargs, []); + if let ReturnDest::IndirectOperand(tmp, _) = ret_dest { + location.val.store(bx, tmp); + } + self.store_return(bx, ret_dest, &fn_abi.ret, location.immediate()); + return helper.funclet_br(self, bx, target.unwrap(), mergeable_succ); + } + let instance = *instance.as_ref().unwrap(); match Self::codegen_intrinsic_call(bx, instance, fn_abi, &args, dest, span) { Ok(()) => { @@ -997,6 +977,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } } + _ => instance, }; let mut llargs = Vec::with_capacity(arg_count); diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index e8b9490d4010a..3770bd11cf9b2 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -22,8 +22,6 @@ use rustc_session::{ use rustc_span::symbol::Symbol; use rustc_target::abi::call::FnAbi; -use std::fmt; - pub trait BackendTypes { type Value: CodegenObject; type Function: CodegenObject; @@ -62,7 +60,7 @@ pub trait CodegenBackend { fn locale_resource(&self) -> &'static str; fn init(&self, _sess: &Session) {} - fn print(&self, _req: &PrintRequest, _out: &mut dyn PrintBackendInfo, _sess: &Session) {} + fn print(&self, _req: &PrintRequest, _out: &mut String, _sess: &Session) {} fn target_features(&self, _sess: &Session, _allow_unstable: bool) -> Vec { vec![] } @@ -150,19 +148,3 @@ pub trait ExtraBackendMethods: std::thread::Builder::new().name(name).spawn(f) } } - -pub trait PrintBackendInfo { - fn infallible_write_fmt(&mut self, args: fmt::Arguments<'_>); -} - -impl PrintBackendInfo for String { - fn infallible_write_fmt(&mut self, args: fmt::Arguments<'_>) { - fmt::Write::write_fmt(self, args).unwrap(); - } -} - -impl dyn PrintBackendInfo + '_ { - pub fn write_fmt(&mut self, args: fmt::Arguments<'_>) { - self.infallible_write_fmt(args); - } -} diff --git a/compiler/rustc_codegen_ssa/src/traits/consts.rs b/compiler/rustc_codegen_ssa/src/traits/consts.rs index 8cb17a5b37a89..3da732602c520 100644 --- a/compiler/rustc_codegen_ssa/src/traits/consts.rs +++ b/compiler/rustc_codegen_ssa/src/traits/consts.rs @@ -37,6 +37,5 @@ pub trait ConstMethods<'tcx>: BackendTypes { fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, llty: Self::Type) -> Self::Value; - fn const_bitcast(&self, val: Self::Value, ty: Self::Type) -> 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 04e2b8796c46a..0ace28ed3ba5e 100644 --- a/compiler/rustc_codegen_ssa/src/traits/misc.rs +++ b/compiler/rustc_codegen_ssa/src/traits/misc.rs @@ -9,7 +9,13 @@ pub trait MiscMethods<'tcx>: BackendTypes { fn vtables( &self, ) -> &RefCell, Option>), Self::Value>>; - fn check_overflow(&self) -> bool; + fn apply_vcall_visibility_metadata( + &self, + _ty: Ty<'tcx>, + _poly_trait_ref: Option>, + _vtable: Self::Value, + ) { + } fn get_fn(&self, instance: Instance<'tcx>) -> Self::Function; fn get_fn_addr(&self, instance: Instance<'tcx>) -> Self::Value; fn eh_personality(&self) -> Self::Value; diff --git a/compiler/rustc_codegen_ssa/src/traits/mod.rs b/compiler/rustc_codegen_ssa/src/traits/mod.rs index 728c2bc8c49bc..8cb58bd4c704d 100644 --- a/compiler/rustc_codegen_ssa/src/traits/mod.rs +++ b/compiler/rustc_codegen_ssa/src/traits/mod.rs @@ -30,9 +30,7 @@ mod write; pub use self::abi::AbiBuilderMethods; pub use self::asm::{AsmBuilderMethods, AsmMethods, GlobalAsmOperandRef, InlineAsmOperandRef}; -pub use self::backend::{ - Backend, BackendTypes, CodegenBackend, ExtraBackendMethods, PrintBackendInfo, -}; +pub use self::backend::{Backend, BackendTypes, CodegenBackend, ExtraBackendMethods}; pub use self::builder::{BuilderMethods, OverflowOp}; pub use self::consts::ConstMethods; pub use self::coverageinfo::CoverageInfoBuilderMethods; diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs index 403f6a7327715..b1bad6cfa6f58 100644 --- a/compiler/rustc_codegen_ssa/src/traits/type_.rs +++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs @@ -12,7 +12,6 @@ use rustc_target::abi::{AddressSpace, Float, Integer}; // This depends on `Backend` and not `BackendTypes`, because consumers will probably want to use // `LayoutOf` or `HasTyCtxt`. This way, they don't have to add a constraint on it themselves. pub trait BaseTypeMethods<'tcx>: Backend<'tcx> { - fn type_i1(&self) -> Self::Type; fn type_i8(&self) -> Self::Type; fn type_i16(&self) -> Self::Type; fn type_i32(&self) -> Self::Type; @@ -27,7 +26,6 @@ pub trait BaseTypeMethods<'tcx>: Backend<'tcx> { fn type_array(&self, ty: Self::Type, len: u64) -> Self::Type; fn type_func(&self, args: &[Self::Type], ret: Self::Type) -> Self::Type; - fn type_struct(&self, els: &[Self::Type], packed: bool) -> Self::Type; fn type_kind(&self, ty: Self::Type) -> TypeKind; fn type_ptr(&self) -> Self::Type; fn type_ptr_ext(&self, address_space: AddressSpace) -> Self::Type; @@ -115,8 +113,8 @@ pub trait LayoutTypeMethods<'tcx>: Backend<'tcx> { /// The backend type used for a rust type when it's in an SSA register. /// /// For nearly all types this is the same as the [`Self::backend_type`], however - /// `bool` (and other `0`-or-`1` values) are kept as [`BaseTypeMethods::type_i1`] - /// in registers but as [`BaseTypeMethods::type_i8`] in memory. + /// `bool` (and other `0`-or-`1` values) are kept as `i1` in registers but as + /// [`BaseTypeMethods::type_i8`] in memory. /// /// Converting values between the two different backend types is done using /// [`from_immediate`](super::BuilderMethods::from_immediate) and diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs index 8c66888d1007e..7acd08e0cceb6 100644 --- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs @@ -42,10 +42,7 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness { | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) => { hir::Constness::Const } - hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }) => tcx - .generics_of(def_id) - .host_effect_index - .map_or(hir::Constness::NotConst, |_| hir::Constness::Const), + hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) => impl_.constness, hir::Node::ForeignItem(hir::ForeignItem { kind: hir::ForeignItemKind::Fn(..), .. }) => { // Intrinsics use `rustc_const_{un,}stable` attributes to indicate constness. All other // foreign items cannot be evaluated at compile-time. diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index a13630ce084d5..83b61ab17492c 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -1,6 +1,6 @@ use std::assert_matches::assert_matches; -use rustc_apfloat::ieee::{Double, Single}; +use rustc_apfloat::ieee::{Double, Half, Quad, Single}; use rustc_apfloat::{Float, FloatConvert}; use rustc_middle::mir::interpret::{InterpResult, PointerArithmetic, Scalar}; use rustc_middle::mir::CastKind; @@ -187,10 +187,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { bug!("FloatToFloat/FloatToInt cast: source type {} is not a float type", src.layout.ty) }; let val = match fty { - FloatTy::F16 => unimplemented!("f16_f128"), + FloatTy::F16 => self.cast_from_float(src.to_scalar().to_f16()?, cast_to.ty), FloatTy::F32 => self.cast_from_float(src.to_scalar().to_f32()?, cast_to.ty), FloatTy::F64 => self.cast_from_float(src.to_scalar().to_f64()?, cast_to.ty), - FloatTy::F128 => unimplemented!("f16_f128"), + FloatTy::F128 => self.cast_from_float(src.to_scalar().to_f128()?, cast_to.ty), }; Ok(ImmTy::from_scalar(val, cast_to)) } @@ -296,18 +296,18 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { Float(fty) if signed => { let v = v as i128; match fty { - FloatTy::F16 => unimplemented!("f16_f128"), + FloatTy::F16 => Scalar::from_f16(Half::from_i128(v).value), FloatTy::F32 => Scalar::from_f32(Single::from_i128(v).value), FloatTy::F64 => Scalar::from_f64(Double::from_i128(v).value), - FloatTy::F128 => unimplemented!("f16_f128"), + FloatTy::F128 => Scalar::from_f128(Quad::from_i128(v).value), } } // unsigned int -> float Float(fty) => match fty { - FloatTy::F16 => unimplemented!("f16_f128"), + FloatTy::F16 => Scalar::from_f16(Half::from_u128(v).value), FloatTy::F32 => Scalar::from_f32(Single::from_u128(v).value), FloatTy::F64 => Scalar::from_f64(Double::from_u128(v).value), - FloatTy::F128 => unimplemented!("f16_f128"), + FloatTy::F128 => Scalar::from_f128(Quad::from_u128(v).value), }, // u8 -> char @@ -321,7 +321,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// Low-level cast helper function. Converts an apfloat `f` into int or float types. fn cast_from_float(&self, f: F, dest_ty: Ty<'tcx>) -> Scalar where - F: Float + Into> + FloatConvert + FloatConvert, + F: Float + + Into> + + FloatConvert + + FloatConvert + + FloatConvert + + FloatConvert, { use rustc_type_ir::TyKind::*; @@ -358,10 +363,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } // float -> float Float(fty) => match fty { - FloatTy::F16 => unimplemented!("f16_f128"), + FloatTy::F16 => Scalar::from_f16(adjust_nan(self, f, f.convert(&mut false).value)), FloatTy::F32 => Scalar::from_f32(adjust_nan(self, f, f.convert(&mut false).value)), FloatTy::F64 => Scalar::from_f64(adjust_nan(self, f, f.convert(&mut false).value)), - FloatTy::F128 => unimplemented!("f16_f128"), + FloatTy::F128 => { + Scalar::from_f128(adjust_nan(self, f, f.convert(&mut false).value)) + } }, // That's it. _ => span_bug!(self.cur_span(), "invalid float to {} cast", dest_ty), diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index f525510030b4a..c4b2e067bbeb4 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -50,7 +50,7 @@ libc = "0.2" memmap2 = "0.2.1" # tidy-alphabetical-end -[target.'cfg(any(target_arch = "mips", target_arch = "powerpc", target_arch = "sparc"))'.dependencies] +[target.'cfg(not(target_has_atomic = "64"))'.dependencies] portable-atomic = "1.5.1" [features] diff --git a/compiler/rustc_data_structures/src/marker.rs b/compiler/rustc_data_structures/src/marker.rs index 32fad0de1aa3e..83fdaff515b03 100644 --- a/compiler/rustc_data_structures/src/marker.rs +++ b/compiler/rustc_data_structures/src/marker.rs @@ -147,14 +147,13 @@ cfg_match! { [crate::owned_slice::OwnedSlice] ); - // MIPS, PowerPC and SPARC platforms with 32-bit pointers do not - // have AtomicU64 type. - #[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc", target_arch = "sparc")))] + // Use portable AtomicU64 for targets without native 64-bit atomics + #[cfg(target_has_atomic = "64")] already_sync!( [std::sync::atomic::AtomicU64] ); - #[cfg(any(target_arch = "mips", target_arch = "powerpc", target_arch = "sparc"))] + #[cfg(not(target_has_atomic = "64"))] already_sync!( [portable_atomic::AtomicU64] ); diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index 5ae79ca988f14..79ceb28abb518 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -270,12 +270,11 @@ cfg_match! { pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU32}; - // MIPS, PowerPC and SPARC platforms with 32-bit pointers do not - // have AtomicU64 type. - #[cfg(not(any(target_arch = "mips", target_arch = "powerpc", target_arch = "sparc")))] + // Use portable AtomicU64 for targets without native 64-bit atomics + #[cfg(target_has_atomic = "64")] pub use std::sync::atomic::AtomicU64; - #[cfg(any(target_arch = "mips", target_arch = "powerpc", target_arch = "sparc"))] + #[cfg(not(target_has_atomic = "64"))] pub use portable_atomic::AtomicU64; pub use std::sync::Arc as Lrc; diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index e580910af7799..d500f6d88a01b 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -510,7 +510,7 @@ pub struct Diag<'a, G: EmissionGuarantee = ErrorGuaranteed> { // would be bad. impl !Clone for Diag<'_, G> {} -rustc_data_structures::static_assert_size!(Diag<'_, ()>, 2 * std::mem::size_of::()); +rustc_data_structures::static_assert_size!(Diag<'_, ()>, 3 * std::mem::size_of::()); impl Deref for Diag<'_, G> { type Target = DiagInner; @@ -582,6 +582,11 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { Self::new_diagnostic(dcx, DiagInner::new(level, message)) } + /// Allow moving diagnostics between different error tainting contexts + pub fn with_dcx(mut self, dcx: DiagCtxtHandle<'_>) -> Diag<'_, G> { + Diag { dcx, diag: self.diag.take(), _marker: PhantomData } + } + /// Creates a new `Diag` with an already constructed diagnostic. #[track_caller] pub(crate) fn new_diagnostic(dcx: DiagCtxtHandle<'a>, diag: DiagInner) -> Self { diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 91112a572770e..2086d4030f905 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -63,6 +63,7 @@ use rustc_span::source_map::SourceMap; use rustc_span::{Loc, Span, DUMMY_SP}; use std::backtrace::{Backtrace, BacktraceStatus}; use std::borrow::Cow; +use std::cell::Cell; use std::error::Report; use std::fmt; use std::hash::Hash; @@ -98,9 +99,9 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" } // `PResult` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_pointer_width = "64")] -rustc_data_structures::static_assert_size!(PResult<'_, ()>, 16); +rustc_data_structures::static_assert_size!(PResult<'_, ()>, 24); #[cfg(target_pointer_width = "64")] -rustc_data_structures::static_assert_size!(PResult<'_, bool>, 16); +rustc_data_structures::static_assert_size!(PResult<'_, bool>, 24); #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Encodable, Decodable)] pub enum SuggestionStyle { @@ -417,6 +418,9 @@ pub struct DiagCtxt { #[derive(Copy, Clone)] pub struct DiagCtxtHandle<'a> { dcx: &'a DiagCtxt, + /// Some contexts create `DiagCtxtHandle` with this field set, and thus all + /// errors emitted with it will automatically taint when emitting errors. + tainted_with_errors: Option<&'a Cell>>, } impl<'a> std::ops::Deref for DiagCtxtHandle<'a> { @@ -752,7 +756,17 @@ impl DiagCtxt { } pub fn handle<'a>(&'a self) -> DiagCtxtHandle<'a> { - DiagCtxtHandle { dcx: self } + DiagCtxtHandle { dcx: self, tainted_with_errors: None } + } + + /// Link this to a taintable context so that emitting errors will automatically set + /// the `Option` instead of having to do that manually at every error + /// emission site. + pub fn taintable_handle<'a>( + &'a self, + tainted_with_errors: &'a Cell>, + ) -> DiagCtxtHandle<'a> { + DiagCtxtHandle { dcx: self, tainted_with_errors: Some(tainted_with_errors) } } } @@ -795,7 +809,9 @@ impl<'a> DiagCtxtHandle<'a> { // can be used to create a backtrace at the stashing site insted of whenever the // diagnostic context is dropped and thus delayed bugs are emitted. Error => Some(self.span_delayed_bug(span, format!("stashing {key:?}"))), - DelayedBug => return self.inner.borrow_mut().emit_diagnostic(diag), + DelayedBug => { + return self.inner.borrow_mut().emit_diagnostic(diag, self.tainted_with_errors); + } ForceWarning(_) | Warning | Note | OnceNote | Help | OnceHelp | FailureNote | Allow | Expect(_) => None, }; @@ -947,16 +963,19 @@ impl<'a> DiagCtxtHandle<'a> { (0, _) => { // Use `ForceWarning` rather than `Warning` to guarantee emission, e.g. with a // configuration like `--cap-lints allow --force-warn bare_trait_objects`. - inner.emit_diagnostic(DiagInner::new( - ForceWarning(None), - DiagMessage::Str(warnings), - )); + inner.emit_diagnostic( + DiagInner::new(ForceWarning(None), DiagMessage::Str(warnings)), + None, + ); } (_, 0) => { - inner.emit_diagnostic(DiagInner::new(Error, errors)); + inner.emit_diagnostic(DiagInner::new(Error, errors), self.tainted_with_errors); } (_, _) => { - inner.emit_diagnostic(DiagInner::new(Error, format!("{errors}; {warnings}"))); + inner.emit_diagnostic( + DiagInner::new(Error, format!("{errors}; {warnings}")), + self.tainted_with_errors, + ); } } @@ -987,14 +1006,14 @@ impl<'a> DiagCtxtHandle<'a> { "For more information about an error, try `rustc --explain {}`.", &error_codes[0] ); - inner.emit_diagnostic(DiagInner::new(FailureNote, msg1)); - inner.emit_diagnostic(DiagInner::new(FailureNote, msg2)); + inner.emit_diagnostic(DiagInner::new(FailureNote, msg1), None); + inner.emit_diagnostic(DiagInner::new(FailureNote, msg2), None); } else { let msg = format!( "For more information about this error, try `rustc --explain {}`.", &error_codes[0] ); - inner.emit_diagnostic(DiagInner::new(FailureNote, msg)); + inner.emit_diagnostic(DiagInner::new(FailureNote, msg), None); } } } @@ -1020,7 +1039,7 @@ impl<'a> DiagCtxtHandle<'a> { } pub fn emit_diagnostic(&self, diagnostic: DiagInner) -> Option { - self.inner.borrow_mut().emit_diagnostic(diagnostic) + self.inner.borrow_mut().emit_diagnostic(diagnostic, self.tainted_with_errors) } pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) { @@ -1080,7 +1099,7 @@ impl<'a> DiagCtxtHandle<'a> { // Here the diagnostic is given back to `emit_diagnostic` where it was first // intercepted. Now it should be processed as usual, since the unstable expectation // id is now stable. - inner.emit_diagnostic(diag); + inner.emit_diagnostic(diag, self.tainted_with_errors); } } @@ -1430,13 +1449,17 @@ impl DiagCtxtInner { continue; } } - guar = guar.or(self.emit_diagnostic(diag)); + guar = guar.or(self.emit_diagnostic(diag, None)); } guar } // Return value is only `Some` if the level is `Error` or `DelayedBug`. - fn emit_diagnostic(&mut self, mut diagnostic: DiagInner) -> Option { + fn emit_diagnostic( + &mut self, + mut diagnostic: DiagInner, + taint: Option<&Cell>>, + ) -> Option { match diagnostic.level { Expect(expect_id) | ForceWarning(Some(expect_id)) => { // The `LintExpectationId` can be stable or unstable depending on when it was @@ -1609,6 +1632,9 @@ impl DiagCtxtInner { if is_lint { self.lint_err_guars.push(guar); } else { + if let Some(taint) = taint { + taint.set(Some(guar)); + } self.err_guars.push(guar); } self.panic_if_treat_err_as_bug(); @@ -1718,8 +1744,8 @@ impl DiagCtxtInner { // `-Ztreat-err-as-bug`, which we don't want. let note1 = "no errors encountered even though delayed bugs were created"; let note2 = "those delayed bugs will now be shown as internal compiler errors"; - self.emit_diagnostic(DiagInner::new(Note, note1)); - self.emit_diagnostic(DiagInner::new(Note, note2)); + self.emit_diagnostic(DiagInner::new(Note, note1), None); + self.emit_diagnostic(DiagInner::new(Note, note2), None); for bug in bugs { if let Some(out) = &mut out { @@ -1752,7 +1778,7 @@ impl DiagCtxtInner { } bug.level = Bug; - self.emit_diagnostic(bug); + self.emit_diagnostic(bug, None); } // Panic with `DelayedBugPanic` to avoid "unexpected panic" messages. diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index f884f99692779..910402d5499fd 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -833,6 +833,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_const_panic_str, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes, INTERNAL_UNSTABLE ), + rustc_attr!( + rustc_runtime, Normal, template!(Word), WarnFollowing, + EncodeCrossCrate::No, INTERNAL_UNSTABLE + ), // ========================================================================== // Internal attributes, Layout related: @@ -1113,6 +1117,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ TEST, rustc_dump_predicates, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No ), + rustc_attr!( + TEST, rustc_dump_def_parents, Normal, template!(Word), + WarnFollowing, EncodeCrossCrate::No + ), rustc_attr!( TEST, rustc_object_lifetime_default, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 22a6c06bba323..6cccdec94c0b5 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -526,6 +526,7 @@ pub enum GenericParamKind<'hir> { /// Optional default value for the const generic param default: Option<&'hir AnonConst>, is_host_effect: bool, + synthetic: bool, }, } @@ -3364,6 +3365,7 @@ pub enum ItemKind<'hir> { /// Refer to [`ImplItem`] for an associated item within an impl block. #[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Impl<'hir> { + pub constness: Constness, pub safety: Safety, pub polarity: ImplPolarity, pub defaultness: Defaultness, diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 065ecc5d7b7ba..9bb3245ae05af 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -543,6 +543,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V:: try_visit!(visitor.visit_enum_def(enum_definition, item.hir_id())); } ItemKind::Impl(Impl { + constness: _, safety: _, defaultness: _, polarity: _, @@ -915,7 +916,7 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>( match param.kind { GenericParamKind::Lifetime { .. } => {} GenericParamKind::Type { ref default, .. } => visit_opt!(visitor, visit_ty, default), - GenericParamKind::Const { ref ty, ref default, is_host_effect: _ } => { + GenericParamKind::Const { ref ty, ref default, is_host_effect: _, synthetic: _ } => { try_visit!(visitor.visit_ty(ty)); if let Some(ref default) = default { try_visit!(visitor.visit_const_param_default(param.hir_id, default)); diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 69461957f804d..3c44acb16577a 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -393,6 +393,14 @@ language_item_table! { String, sym::String, string, Target::Struct, GenericRequirement::None; CStr, sym::CStr, c_str, Target::Struct, GenericRequirement::None; + + EffectsRuntime, sym::EffectsRuntime, effects_runtime, Target::Struct, GenericRequirement::None; + EffectsNoRuntime, sym::EffectsNoRuntime, effects_no_runtime, Target::Struct, GenericRequirement::None; + EffectsMaybe, sym::EffectsMaybe, effects_maybe, Target::Struct, GenericRequirement::None; + EffectsIntersection, sym::EffectsIntersection, effects_intersection, Target::Trait, GenericRequirement::None; + EffectsIntersectionOutput, sym::EffectsIntersectionOutput, effects_intersection_output, Target::AssocTy, GenericRequirement::None; + EffectsCompat, sym::EffectsCompat, effects_compat, Target::Trait, GenericRequirement::Exact(1); + EffectsTyCompat, sym::EffectsTyCompat, effects_ty_compat, Target::Trait, GenericRequirement::Exact(1); } pub enum GenericRequirement { diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 7ed32fb9d9f37..064d9c077b0a6 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -120,6 +120,10 @@ hir_analysis_drop_impl_reservation = reservation `Drop` impls are not supported hir_analysis_duplicate_precise_capture = cannot capture parameter `{$name}` twice .label = parameter captured again here +hir_analysis_effects_without_next_solver = using `#![feature(effects)]` without enabling next trait solver globally + .note = the next trait solver must be enabled globally for the effects feature to work correctly + .help = use `-Znext-solver` to enable + hir_analysis_empty_specialization = specialization impl does not specialize any associated items .note = impl is a specialization of this impl diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs index 7f0d72b3a8d4d..c7ee89e73c273 100644 --- a/compiler/rustc_hir_analysis/src/bounds.rs +++ b/compiler/rustc_hir_analysis/src/bounds.rs @@ -1,9 +1,13 @@ //! Bounds are restrictions applied to some types after they've been lowered from the HIR to the //! [`rustc_middle::ty`] form. +use rustc_data_structures::fx::FxIndexMap; +use rustc_hir::def::DefKind; use rustc_hir::LangItem; +use rustc_middle::ty::fold::FnMutDelegate; use rustc_middle::ty::{self, Ty, TyCtxt, Upcast}; -use rustc_span::Span; +use rustc_span::def_id::DefId; +use rustc_span::{sym, Span}; /// Collects together a list of type bounds. These lists of bounds occur in many places /// in Rust's syntax: @@ -24,6 +28,7 @@ use rustc_span::Span; #[derive(Default, PartialEq, Eq, Clone, Debug)] pub struct Bounds<'tcx> { clauses: Vec<(ty::Clause<'tcx>, Span)>, + effects_min_tys: FxIndexMap, Span>, } impl<'tcx> Bounds<'tcx> { @@ -40,12 +45,14 @@ impl<'tcx> Bounds<'tcx> { pub fn push_trait_bound( &mut self, tcx: TyCtxt<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, + defining_def_id: DefId, + bound_trait_ref: ty::PolyTraitRef<'tcx>, span: Span, polarity: ty::PredicatePolarity, + constness: ty::BoundConstness, ) { let clause = ( - trait_ref + bound_trait_ref .map_bound(|trait_ref| { ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity }) }) @@ -53,11 +60,98 @@ impl<'tcx> Bounds<'tcx> { span, ); // FIXME(-Znext-solver): We can likely remove this hack once the new trait solver lands. - if tcx.is_lang_item(trait_ref.def_id(), LangItem::Sized) { + if tcx.is_lang_item(bound_trait_ref.def_id(), LangItem::Sized) { self.clauses.insert(0, clause); } else { self.clauses.push(clause); } + + if !tcx.features().effects { + return; + } + // For `T: ~const Tr` or `T: const Tr`, we need to add an additional bound on the + // associated type of `` and make sure that the effect is compatible. + let compat_val = match (tcx.def_kind(defining_def_id), constness) { + // FIXME(effects): revisit the correctness of this + (_, ty::BoundConstness::Const) => tcx.consts.false_, + // body owners that can have trait bounds + (DefKind::Const | DefKind::Fn | DefKind::AssocFn, ty::BoundConstness::ConstIfConst) => { + tcx.expected_host_effect_param_for_body(defining_def_id) + } + + (_, ty::BoundConstness::NotConst) => { + if !tcx.has_attr(bound_trait_ref.def_id(), sym::const_trait) { + return; + } + tcx.consts.true_ + } + + ( + DefKind::Trait | DefKind::Impl { of_trait: true }, + ty::BoundConstness::ConstIfConst, + ) => { + // this is either a where clause on an impl/trait header or on a trait. + // push `::Effects` into the set for the `Min` bound. + let Some(assoc) = tcx.associated_type_for_effects(bound_trait_ref.def_id()) else { + tcx.dcx().span_delayed_bug(span, "`~const` on trait without Effects assoc"); + return; + }; + + let ty = bound_trait_ref + .map_bound(|trait_ref| Ty::new_projection(tcx, assoc, trait_ref.args)); + + // When the user has written `for<'a, T> X<'a, T>: ~const Foo`, replace the + // binders to dummy ones i.e. `X<'static, ()>` so they can be referenced in + // the `Min` associated type properly (which doesn't allow using `for<>`) + // This should work for any bound variables as long as they don't have any + // bounds e.g. `for`. + // FIXME(effects) reconsider this approach to allow compatibility with `for` + let ty = tcx.replace_bound_vars_uncached( + ty, + FnMutDelegate { + regions: &mut |_| tcx.lifetimes.re_static, + types: &mut |_| tcx.types.unit, + consts: &mut |_| unimplemented!("`~const` does not support const binders"), + }, + ); + + self.effects_min_tys.insert(ty, span); + return; + } + // for + // ``` + // trait Foo { type Bar: ~const Trait } + // ``` + // ensure that `::Effects: TyCompat`. + // + // FIXME(effects) this is equality for now, which wouldn't be helpful for a non-const implementor + // that uses a `Bar` that implements `Trait` with `Maybe` effects. + (DefKind::AssocTy, ty::BoundConstness::ConstIfConst) => { + // FIXME(effects): implement this + return; + } + // probably illegal in this position. + (_, ty::BoundConstness::ConstIfConst) => { + tcx.dcx().span_delayed_bug(span, "invalid `~const` encountered"); + return; + } + }; + // create a new projection type `::Effects` + let Some(assoc) = tcx.associated_type_for_effects(bound_trait_ref.def_id()) else { + tcx.dcx().span_delayed_bug( + span, + "`~const` trait bound has no effect assoc yet no errors encountered?", + ); + return; + }; + let self_ty = Ty::new_projection(tcx, assoc, bound_trait_ref.skip_binder().args); + // make `::Effects: Compat` + let new_trait_ref = ty::TraitRef::new( + tcx, + tcx.require_lang_item(LangItem::EffectsCompat, Some(span)), + [ty::GenericArg::from(self_ty), compat_val.into()], + ); + self.clauses.push((bound_trait_ref.rebind(new_trait_ref).upcast(tcx), span)); } pub fn push_projection_bound( @@ -79,7 +173,15 @@ impl<'tcx> Bounds<'tcx> { self.clauses.insert(0, (trait_ref.upcast(tcx), span)); } - pub fn clauses(&self) -> impl Iterator, Span)> + '_ { + pub fn clauses( + &self, + // FIXME(effects): remove tcx + _tcx: TyCtxt<'tcx>, + ) -> impl Iterator, Span)> + '_ { self.clauses.iter().cloned() } + + pub fn effects_min_tys(&self) -> impl Iterator> + '_ { + self.effects_min_tys.keys().copied() + } } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index e13ea1a1935b4..f93777eda529e 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -879,7 +879,8 @@ pub(super) fn check_specialization_validity<'tcx>( let result = opt_result.unwrap_or(Ok(())); if let Err(parent_impl) = result { - if !tcx.is_impl_trait_in_trait(impl_item) { + // FIXME(effects) the associated type from effects could be specialized + if !tcx.is_impl_trait_in_trait(impl_item) && !tcx.is_effects_desugared_assoc_ty(impl_item) { report_forbidden_specialization(tcx, impl_item, parent_impl); } else { tcx.dcx().delayed_bug(format!("parent item: {parent_impl:?} not marked as default")); 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 7fa5c96bc9ab4..b5b68471b9d16 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -1985,10 +1985,10 @@ pub(super) fn check_type_bounds<'tcx>( let infcx = tcx.infer_ctxt().build(); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); - // A synthetic impl Trait for RPITIT desugaring has no HIR, which we currently use to get the - // span for an impl's associated type. Instead, for these, use the def_span for the synthesized - // associated type. - let impl_ty_span = if impl_ty.is_impl_trait_in_trait() { + // A synthetic impl Trait for RPITIT desugaring or assoc type for effects desugaring has no HIR, + // which we currently use to get the span for an impl's associated type. Instead, for these, + // use the def_span for the synthesized associated type. + let impl_ty_span = if impl_ty.is_impl_trait_in_trait() || impl_ty.is_effects_desugaring { tcx.def_span(impl_ty_def_id) } else { match tcx.hir_node_by_def_id(impl_ty_def_id) { diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index a188c1b12aeb6..2230528a5ae11 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -913,7 +913,12 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(), hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. } => Ok(()), // Const parameters are well formed if their type is structural match. - hir::GenericParamKind::Const { ty: hir_ty, default: _, is_host_effect: _ } => { + hir::GenericParamKind::Const { + ty: hir_ty, + default: _, + is_host_effect: _, + synthetic: _, + } => { let ty = tcx.type_of(param.def_id).instantiate_identity(); if tcx.features().adt_const_params { diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index e7892f1766067..41fbef489405c 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -70,10 +70,10 @@ pub fn provide(providers: &mut Providers) { predicates_of: predicates_of::predicates_of, predicates_defined_on, explicit_predicates_of: predicates_of::explicit_predicates_of, - super_predicates_of: predicates_of::super_predicates_of, - implied_predicates_of: predicates_of::implied_predicates_of, - super_predicates_that_define_assoc_item: - predicates_of::super_predicates_that_define_assoc_item, + explicit_super_predicates_of: predicates_of::explicit_super_predicates_of, + explicit_implied_predicates_of: predicates_of::explicit_implied_predicates_of, + explicit_supertraits_containing_assoc_item: + predicates_of::explicit_supertraits_containing_assoc_item, trait_explicit_predicates_and_bounds: predicates_of::trait_explicit_predicates_and_bounds, type_param_predicates: predicates_of::type_param_predicates, trait_def, @@ -691,14 +691,14 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { hir::ItemKind::Trait(..) => { tcx.ensure().generics_of(def_id); tcx.ensure().trait_def(def_id); - tcx.at(it.span).super_predicates_of(def_id); + tcx.at(it.span).explicit_super_predicates_of(def_id); tcx.ensure().predicates_of(def_id); tcx.ensure().associated_items(def_id); } hir::ItemKind::TraitAlias(..) => { tcx.ensure().generics_of(def_id); - tcx.at(it.span).implied_predicates_of(def_id); - tcx.at(it.span).super_predicates_of(def_id); + tcx.at(it.span).explicit_implied_predicates_of(def_id); + tcx.at(it.span).explicit_super_predicates_of(def_id); tcx.ensure().predicates_of(def_id); } hir::ItemKind::Struct(struct_def, _) | hir::ItemKind::Union(struct_def, _) => { @@ -1459,8 +1459,25 @@ fn infer_return_ty_for_fn_sig<'tcx>( Some(ty) => { let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id]; // Typeck doesn't expect erased regions to be returned from `type_of`. + // This is a heuristic approach. If the scope has region paramters, + // we should change fn_sig's lifetime from `ReErased` to `ReError`, + // otherwise to `ReStatic`. + let has_region_params = generics.params.iter().any(|param| match param.kind { + GenericParamKind::Lifetime { .. } => true, + _ => false, + }); let fn_sig = tcx.fold_regions(fn_sig, |r, _| match *r { - ty::ReErased => tcx.lifetimes.re_static, + ty::ReErased => { + if has_region_params { + ty::Region::new_error_with_message( + tcx, + DUMMY_SP, + "erased region is not allowed here in return type", + ) + } else { + tcx.lifetimes.re_static + } + } _ => r, }); @@ -1638,44 +1655,19 @@ fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option) { } } } + +pub(crate) fn def_parents(tcx: TyCtxt<'_>) { + for did in tcx.hir().body_owners() { + if tcx.has_attr(did, sym::rustc_dump_def_parents) { + struct AnonConstFinder<'tcx> { + tcx: TyCtxt<'tcx>, + anon_consts: Vec, + } + + impl<'tcx> intravisit::Visitor<'tcx> for AnonConstFinder<'tcx> { + type NestedFilter = OnlyBodies; + + fn nested_visit_map(&mut self) -> Self::Map { + self.tcx.hir() + } + + fn visit_anon_const(&mut self, c: &'tcx rustc_hir::AnonConst) { + self.anon_consts.push(c.def_id); + intravisit::walk_anon_const(self, c) + } + } + + // Look for any anon consts inside of this body owner as there is no way to apply + // the `rustc_dump_def_parents` attribute to the anon const so it would not be possible + // to see what its def parent is. + let mut anon_ct_finder = AnonConstFinder { tcx, anon_consts: vec![] }; + intravisit::walk_expr(&mut anon_ct_finder, tcx.hir().body_owned_by(did).value); + + for did in [did].into_iter().chain(anon_ct_finder.anon_consts) { + let span = tcx.def_span(did); + + let mut diag = tcx.dcx().struct_span_err( + span, + format!("{}: {did:?}", sym::rustc_dump_def_parents.as_str()), + ); + + let mut current_did = did.to_def_id(); + while let Some(parent_did) = tcx.opt_parent(current_did) { + current_did = parent_did; + diag.span_note(tcx.def_span(parent_did), format!("{parent_did:?}")); + } + diag.emit(); + } + } + } +} diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 303fa23dbc1e8..9b02c1a61fa97 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -354,7 +354,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { kind, }) } - GenericParamKind::Const { ty: _, default, is_host_effect } => { + GenericParamKind::Const { ty: _, default, is_host_effect, synthetic } => { if !matches!(allow_defaults, Defaults::Allowed) && default.is_some() // `host` effect params are allowed to have defaults. @@ -388,6 +388,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { kind: ty::GenericParamDefKind::Const { has_default: default.is_some(), is_host_effect, + synthetic, }, }) } @@ -541,7 +542,8 @@ struct AnonConstInParamTyDetector { impl<'v> Visitor<'v> for AnonConstInParamTyDetector { fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) { - if let GenericParamKind::Const { ty, default: _, is_host_effect: _ } = p.kind { + if let GenericParamKind::Const { ty, default: _, is_host_effect: _, synthetic: _ } = p.kind + { let prev = self.in_param_ty; self.in_param_ty = true; self.visit_ty(ty); diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index d084d3aefeb17..c03e074c80b7a 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -8,6 +8,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFold use rustc_middle::{bug, span_bug}; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::Span; +use rustc_type_ir::Upcast; /// For associated types we include both bounds written on the type /// (`type X: Trait`) and predicates from the trait: `where Self::X: Trait`. @@ -46,7 +47,7 @@ fn associated_type_bounds<'tcx>( } }); - let all_bounds = tcx.arena.alloc_from_iter(bounds.clauses().chain(bounds_from_parent)); + let all_bounds = tcx.arena.alloc_from_iter(bounds.clauses(tcx).chain(bounds_from_parent)); debug!( "associated_type_bounds({}) = {:?}", tcx.def_path_str(assoc_item_def_id.to_def_id()), @@ -75,7 +76,7 @@ fn opaque_type_bounds<'tcx>( icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span); debug!(?bounds); - tcx.arena.alloc_from_iter(bounds.clauses()) + tcx.arena.alloc_from_iter(bounds.clauses(tcx)) }) } @@ -124,6 +125,32 @@ pub(super) fn explicit_item_bounds_with_filter( None => {} } + if tcx.is_effects_desugared_assoc_ty(def_id.to_def_id()) { + let mut predicates = Vec::new(); + + let parent = tcx.local_parent(def_id); + + let preds = tcx.explicit_predicates_of(parent); + + if let ty::AssocItemContainer::TraitContainer = tcx.associated_item(def_id).container { + // for traits, emit `type Effects: TyCompat<<(T1::Effects, ..) as Min>::Output>` + let tup = Ty::new(tcx, ty::Tuple(preds.effects_min_tys)); + // FIXME(effects) span + let span = tcx.def_span(def_id); + let assoc = tcx.require_lang_item(hir::LangItem::EffectsIntersectionOutput, Some(span)); + let proj = Ty::new_projection(tcx, assoc, [tup]); + let self_proj = Ty::new_projection( + tcx, + def_id.to_def_id(), + ty::GenericArgs::identity_for_item(tcx, def_id), + ); + let trait_ = tcx.require_lang_item(hir::LangItem::EffectsTyCompat, Some(span)); + let trait_ref = ty::TraitRef::new(tcx, trait_, [self_proj, proj]); + predicates.push((ty::Binder::dummy(trait_ref).upcast(tcx), span)); + } + return ty::EarlyBinder::bind(tcx.arena.alloc_from_iter(predicates)); + } + let bounds = match tcx.hir_node_by_def_id(def_id) { hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Type(bounds, _), diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 3421c8da4e9f3..b89d034fc2e3f 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -57,6 +57,7 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic #[instrument(level = "trace", skip(tcx), ret)] fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::GenericPredicates<'_> { use rustc_hir::*; + use rustc_middle::ty::Ty; match tcx.opt_rpitit_info(def_id.to_def_id()) { Some(ImplTraitInTraitData::Trait { fn_def_id, .. }) => { @@ -84,6 +85,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen return ty::GenericPredicates { parent: Some(tcx.parent(def_id.to_def_id())), predicates: tcx.arena.alloc_from_iter(predicates), + effects_min_tys: ty::List::empty(), }; } @@ -105,6 +107,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen return ty::GenericPredicates { parent: Some(impl_def_id), predicates: tcx.arena.alloc_from_iter(impl_predicates), + effects_min_tys: ty::List::empty(), }; } @@ -124,6 +127,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen // We use an `IndexSet` to preserve order of insertion. // Preserving the order of insertion is important here so as not to break UI tests. let mut predicates: FxIndexSet<(ty::Clause<'_>, Span)> = FxIndexSet::default(); + let mut effects_min_tys = Vec::new(); let hir_generics = node.generics().unwrap_or(NO_GENERICS); if let Node::Item(item) = node { @@ -150,11 +154,13 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen // on a trait we must also consider the bounds that follow the trait's name, // like `trait Foo: A + B + C`. if let Some(self_bounds) = is_trait { - predicates.extend( - icx.lowerer() - .lower_mono_bounds(tcx.types.self_param, self_bounds, PredicateFilter::All) - .clauses(), + let bounds = icx.lowerer().lower_mono_bounds( + tcx.types.self_param, + self_bounds, + PredicateFilter::All, ); + predicates.extend(bounds.clauses(tcx)); + effects_min_tys.extend(bounds.effects_min_tys()); } // In default impls, we can assume that the self type implements @@ -187,7 +193,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen param.span, ); trace!(?bounds); - predicates.extend(bounds.clauses()); + predicates.extend(bounds.clauses(tcx)); trace!(?predicates); } hir::GenericParamKind::Const { .. } => { @@ -238,7 +244,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen bound_vars, OnlySelfBounds(false), ); - predicates.extend(bounds.clauses()); + predicates.extend(bounds.clauses(tcx)); + effects_min_tys.extend(bounds.effects_min_tys()); } hir::WherePredicate::RegionPredicate(region_pred) => { @@ -297,7 +304,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen // and the duplicated parameter, to ensure that they do not get out of sync. if let Node::Item(&Item { kind: ItemKind::OpaqueTy(..), .. }) = node { let opaque_ty_node = tcx.parent_hir_node(hir_id); - let Node::Ty(&Ty { kind: TyKind::OpaqueDef(_, lifetimes, _), .. }) = opaque_ty_node else { + let Node::Ty(&hir::Ty { kind: TyKind::OpaqueDef(_, lifetimes, _), .. }) = opaque_ty_node + else { bug!("unexpected {opaque_ty_node:?}") }; debug!(?lifetimes); @@ -306,9 +314,30 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen debug!(?predicates); } + // add `Self::Effects: Compat` to ensure non-const impls don't get called + // in const contexts. + if let Node::TraitItem(&TraitItem { kind: TraitItemKind::Fn(..), .. }) = node + && let Some(host_effect_index) = generics.host_effect_index + { + let parent = generics.parent.unwrap(); + let Some(assoc_def_id) = tcx.associated_type_for_effects(parent) else { + bug!("associated_type_for_effects returned None when there is host effect in generics"); + }; + let effects = + Ty::new_projection(tcx, assoc_def_id, ty::GenericArgs::identity_for_item(tcx, parent)); + let param = generics.param_at(host_effect_index, tcx); + let span = tcx.def_span(param.def_id); + let host = ty::Const::new_param(tcx, ty::ParamConst::for_def(param)); + let compat = tcx.require_lang_item(LangItem::EffectsCompat, Some(span)); + let trait_ref = + ty::TraitRef::new(tcx, compat, [ty::GenericArg::from(effects), host.into()]); + predicates.push((ty::Binder::dummy(trait_ref).upcast(tcx), span)); + } + ty::GenericPredicates { parent: generics.parent, predicates: tcx.arena.alloc_from_iter(predicates), + effects_min_tys: tcx.mk_type_list(&effects_min_tys), } } @@ -459,6 +488,7 @@ pub(super) fn explicit_predicates_of<'tcx>( ty::GenericPredicates { parent: predicates_and_bounds.parent, predicates: tcx.arena.alloc_slice(&predicates), + effects_min_tys: predicates_and_bounds.effects_min_tys, } } } else { @@ -510,6 +540,7 @@ pub(super) fn explicit_predicates_of<'tcx>( return GenericPredicates { parent: parent_preds.parent, predicates: { tcx.arena.alloc_from_iter(filtered_predicates) }, + effects_min_tys: parent_preds.effects_min_tys, }; } gather_explicit_predicates_of(tcx, def_id) @@ -519,21 +550,21 @@ pub(super) fn explicit_predicates_of<'tcx>( /// Ensures that the super-predicates of the trait with a `DefId` /// of `trait_def_id` are lowered and stored. This also ensures that /// the transitive super-predicates are lowered. -pub(super) fn super_predicates_of( +pub(super) fn explicit_super_predicates_of( tcx: TyCtxt<'_>, trait_def_id: LocalDefId, ) -> ty::GenericPredicates<'_> { implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::SelfOnly) } -pub(super) fn super_predicates_that_define_assoc_item( +pub(super) fn explicit_supertraits_containing_assoc_item( tcx: TyCtxt<'_>, (trait_def_id, assoc_name): (DefId, Ident), ) -> ty::GenericPredicates<'_> { implied_predicates_with_filter(tcx, trait_def_id, PredicateFilter::SelfThatDefines(assoc_name)) } -pub(super) fn implied_predicates_of( +pub(super) fn explicit_implied_predicates_of( tcx: TyCtxt<'_>, trait_def_id: LocalDefId, ) -> ty::GenericPredicates<'_> { @@ -560,7 +591,7 @@ pub(super) fn implied_predicates_with_filter( // if `assoc_name` is None, then the query should've been redirected to an // external provider assert!(matches!(filter, PredicateFilter::SelfThatDefines(_))); - return tcx.super_predicates_of(trait_def_id); + return tcx.explicit_super_predicates_of(trait_def_id); }; let Node::Item(item) = tcx.hir_node_by_def_id(trait_def_id) else { @@ -587,7 +618,7 @@ pub(super) fn implied_predicates_with_filter( // Combine the two lists to form the complete set of superbounds: let implied_bounds = - &*tcx.arena.alloc_from_iter(superbounds.clauses().chain(where_bounds_that_match)); + &*tcx.arena.alloc_from_iter(superbounds.clauses(tcx).chain(where_bounds_that_match)); debug!(?implied_bounds); // Now require that immediate supertraits are lowered, which will, in @@ -601,7 +632,7 @@ pub(super) fn implied_predicates_with_filter( if let ty::ClauseKind::Trait(bound) = pred.kind().skip_binder() && bound.polarity == ty::PredicatePolarity::Positive { - tcx.at(span).super_predicates_of(bound.def_id()); + tcx.at(span).explicit_super_predicates_of(bound.def_id()); } } } @@ -611,14 +642,18 @@ pub(super) fn implied_predicates_with_filter( if let ty::ClauseKind::Trait(bound) = pred.kind().skip_binder() && bound.polarity == ty::PredicatePolarity::Positive { - tcx.at(span).implied_predicates_of(bound.def_id()); + tcx.at(span).explicit_implied_predicates_of(bound.def_id()); } } } _ => {} } - ty::GenericPredicates { parent: None, predicates: implied_bounds } + ty::GenericPredicates { + parent: None, + predicates: implied_bounds, + effects_min_tys: ty::List::empty(), + } } /// Returns the predicates defined on `item_def_id` of the form @@ -744,7 +779,7 @@ impl<'tcx> ItemCtxt<'tcx> { ); } - bounds.clauses().collect() + bounds.clauses(self.tcx).collect() } #[instrument(level = "trace", skip(self))] 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 abc3bb838db3e..cad7870a0a1d8 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -951,7 +951,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { self.visit_ty(ty); } } - GenericParamKind::Const { ty, default, is_host_effect: _ } => { + GenericParamKind::Const { ty, default, .. } => { self.visit_ty(ty); if let Some(default) = default { self.visit_body(self.tcx.hir().body(default.body)); @@ -1760,7 +1760,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { if let Some(assoc_item) = trait_defines_associated_item_named(def_id) { break Some((bound_vars.into_iter().collect(), assoc_item)); } - let predicates = tcx.super_predicates_that_define_assoc_item((def_id, assoc_name)); + let predicates = tcx.explicit_supertraits_containing_assoc_item((def_id, assoc_name)); let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| { let bound_predicate = pred.kind(); match bound_predicate.skip_binder() { diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 44025c3cd61c1..3ffb51fa9926a 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1699,3 +1699,9 @@ pub struct InvalidReceiverTy<'tcx> { pub span: Span, pub receiver_ty: Ty<'tcx>, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_effects_without_next_solver)] +#[note] +#[help] +pub struct EffectsWithoutNextSolver; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs index 3f888c4e2722b..e92c377f0ce2a 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs @@ -256,6 +256,7 @@ pub fn lower_generic_args<'tcx: 'a, 'a>( | GenericParamDefKind::Lifetime, _, ) => { + // FIXME(effects): this should be removed // SPECIAL CASE FOR DESUGARED EFFECT PARAMS // This comes from the following example: // @@ -445,7 +446,7 @@ pub(crate) fn check_generic_arg_count( .own_params .iter() .filter(|param| { - matches!(param.kind, ty::GenericParamDefKind::Const { is_host_effect: true, .. }) + matches!(param.kind, ty::GenericParamDefKind::Const { synthetic: true, .. }) }) .count(); let named_const_param_count = param_counts.consts - synth_const_param_count; 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 24ea328889c6b..2a68d3915bbbc 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -698,7 +698,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ); debug!(?poly_trait_ref); - bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity); + bounds.push_trait_bound( + tcx, + self.item_def_id().to_def_id(), + poly_trait_ref, + span, + polarity, + constness, + ); let mut dup_constraints = FxIndexMap::default(); for constraint in trait_segment.args().constraints { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs index 34924f09d09ed..df69c1938dd75 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs @@ -59,7 +59,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let mut trait_bounds = vec![]; let mut projection_bounds = vec![]; - for (pred, span) in bounds.clauses() { + for (pred, span) in bounds.clauses(tcx) { let bound_pred = pred.kind(); match bound_pred.skip_binder() { ty::ClauseKind::Trait(trait_pred) => { @@ -133,7 +133,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { tcx.associated_items(pred.def_id()) .in_definition_order() .filter(|item| item.kind == ty::AssocKind::Type) - .filter(|item| !item.is_impl_trait_in_trait()) + .filter(|item| { + !item.is_impl_trait_in_trait() && !item.is_effects_desugaring + }) .map(|item| item.def_id), ); } diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 0428abcdf24e8..44f1830a3b17b 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -151,6 +151,12 @@ pub fn provide(providers: &mut Providers) { pub fn check_crate(tcx: TyCtxt<'_>) { let _prof_timer = tcx.sess.timer("type_check_crate"); + // FIXME(effects): remove once effects is implemented in old trait solver + // or if the next solver is stabilized. + if tcx.features().effects && !tcx.next_trait_solver_globally() { + tcx.dcx().emit_err(errors::EffectsWithoutNextSolver); + } + tcx.sess.time("coherence_checking", || { tcx.hir().par_for_each_module(|module| { let _ = tcx.ensure().check_mod_type_wf(module); @@ -169,6 +175,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) { tcx.sess.time("variance_dumping", || variance::dump::variances(tcx)); collect::dump::opaque_hidden_types(tcx); collect::dump::predicates_and_item_bounds(tcx); + collect::dump::def_parents(tcx); } // Make sure we evaluate all static and (non-associated) const items, even if unused. diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 25b0cbdc026af..5105d60ae188c 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -585,6 +585,7 @@ impl<'a> State<'a> { self.print_struct(struct_def, generics, item.ident.name, item.span, true); } hir::ItemKind::Impl(&hir::Impl { + constness, safety, polarity, defaultness, @@ -599,6 +600,10 @@ impl<'a> State<'a> { self.print_safety(safety); self.word_nbsp("impl"); + if let hir::Constness::Const = constness { + self.word_nbsp("const"); + } + if !generics.params.is_empty() { self.print_generic_params(generics.params); self.space(); @@ -2144,7 +2149,7 @@ impl<'a> State<'a> { self.print_type(default); } } - GenericParamKind::Const { ty, ref default, is_host_effect: _ } => { + GenericParamKind::Const { ty, ref default, is_host_effect: _, synthetic: _ } => { self.word_space(":"); self.print_type(ty); if let Some(default) = default { diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 92f2d3254bb22..cb1a412d17eef 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -319,7 +319,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { } else { errors::CannotCastToBoolHelp::Unsupported(self.span) }; - fcx.tcx.dcx().emit_err(errors::CannotCastToBool { span: self.span, expr_ty, help }); + fcx.dcx().emit_err(errors::CannotCastToBool { span: self.span, expr_ty, help }); } CastError::CastToChar => { let mut err = type_error_struct!( diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 0551b9bc1f0b4..f72e8a4afdef6 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1797,16 +1797,16 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { err.subdiagnostic(SuggestBoxingForReturnImplTrait::BoxReturnExpr { starts, ends }); } - fn report_return_mismatched_types<'a>( + fn report_return_mismatched_types<'infcx>( &self, cause: &ObligationCause<'tcx>, expected: Ty<'tcx>, found: Ty<'tcx>, ty_err: TypeError<'tcx>, - fcx: &FnCtxt<'a, 'tcx>, + fcx: &'infcx FnCtxt<'_, 'tcx>, block_or_return_id: hir::HirId, expression: Option<&'tcx hir::Expr<'tcx>>, - ) -> Diag<'a> { + ) -> Diag<'infcx> { let mut err = fcx.err_ctxt().report_mismatched_types(cause, expected, found, ty_err); let due_to_block = matches!(fcx.tcx.hir_node(block_or_return_id), hir::Node::Block(..)); diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index f9720c9c30795..ad9c1e2821172 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -172,21 +172,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } pub fn demand_suptype_diag( - &self, + &'a self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>, - ) -> Result<(), Diag<'tcx>> { + ) -> Result<(), Diag<'a>> { self.demand_suptype_with_origin(&self.misc(sp), expected, actual) } #[instrument(skip(self), level = "debug")] pub fn demand_suptype_with_origin( - &self, + &'a self, cause: &ObligationCause<'tcx>, expected: Ty<'tcx>, actual: Ty<'tcx>, - ) -> Result<(), Diag<'tcx>> { + ) -> Result<(), Diag<'a>> { self.at(cause, self.param_env) .sup(DefineOpaqueTypes::Yes, expected, actual) .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) @@ -200,20 +200,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } pub fn demand_eqtype_diag( - &self, + &'a self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>, - ) -> Result<(), Diag<'tcx>> { + ) -> Result<(), Diag<'a>> { self.demand_eqtype_with_origin(&self.misc(sp), expected, actual) } pub fn demand_eqtype_with_origin( - &self, + &'a self, cause: &ObligationCause<'tcx>, expected: Ty<'tcx>, actual: Ty<'tcx>, - ) -> Result<(), Diag<'tcx>> { + ) -> Result<(), Diag<'a>> { self.at(cause, self.param_env) .eq(DefineOpaqueTypes::Yes, expected, actual) .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) @@ -247,13 +247,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// will be permitted if the diverges flag is currently "always". #[instrument(level = "debug", skip(self, expr, expected_ty_expr, allow_two_phase))] pub fn demand_coerce_diag( - &self, + &'a self, mut expr: &'tcx hir::Expr<'tcx>, checked_ty: Ty<'tcx>, expected: Ty<'tcx>, mut expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>, allow_two_phase: AllowTwoPhase, - ) -> Result, Diag<'tcx>> { + ) -> Result, Diag<'a>> { let expected = self.resolve_vars_with_obligations(expected); let e = match self.coerce(expr, checked_ty, expected, allow_two_phase, None) { diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index f4e1e46195345..2fbc8a3f146a1 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -638,7 +638,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Set expectation to error in that case and set tainted // by error (#114529) let coerce_to = opt_coerce_to.unwrap_or_else(|| { - let guar = tcx.dcx().span_delayed_bug( + let guar = self.dcx().span_delayed_bug( expr.span, "illegal break with value found but no error reported", ); @@ -1716,7 +1716,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { error_happened = true; let guar = if let Some(prev_span) = seen_fields.get(&ident) { - tcx.dcx().emit_err(FieldMultiplySpecifiedInInitializer { + self.dcx().emit_err(FieldMultiplySpecifiedInInitializer { span: field.ident.span, prev_span: *prev_span, ident, @@ -1757,7 +1757,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if adt_kind == AdtKind::Union { if hir_fields.len() != 1 { struct_span_code_err!( - tcx.dcx(), + self.dcx(), span, E0784, "union expressions should have exactly one field", diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 0ba4bd090f5e2..9a353bfe49d0e 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -170,7 +170,7 @@ impl<'tcx> TypeInformationCtxt<'tcx> for &FnCtxt<'_, 'tcx> { } fn report_error(&self, span: Span, msg: impl ToString) -> Self::Error { - self.tcx.dcx().span_delayed_bug(span, msg.to_string()) + self.dcx().span_delayed_bug(span, msg.to_string()) } fn error_reported_in_ty(&self, ty: Ty<'tcx>) -> Result<(), Self::Error> { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 061afd0306230..5450243417f7f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1182,7 +1182,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { name: self.tcx.item_name(def.did()).to_ident_string(), }); if ty.raw.has_param() { - let guar = self.tcx.dcx().emit_err(errors::SelfCtorFromOuterItem { + let guar = self.dcx().emit_err(errors::SelfCtorFromOuterItem { span: path_span, impl_span: tcx.def_span(impl_def_id), sugg, @@ -1207,7 +1207,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Check the visibility of the ctor. let vis = tcx.visibility(ctor_def_id); if !vis.is_accessible_from(tcx.parent_module(hir_id).to_def_id(), tcx) { - tcx.dcx() + self.dcx() .emit_err(CtorIsPrivate { span, def: tcx.def_path_str(adt_def.did()) }); } let new_res = Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id); @@ -1216,7 +1216,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (new_res, Some(user_args.args)) } _ => { - let mut err = tcx.dcx().struct_span_err( + let mut err = self.dcx().struct_span_err( span, "the `Self` constructor can only be used with tuple or unit structs", ); @@ -1304,7 +1304,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.fcx.ty_infer(Some(param), inf.span).into() } ( - &GenericParamDefKind::Const { has_default, is_host_effect }, + &GenericParamDefKind::Const { has_default, is_host_effect, .. }, GenericArg::Infer(inf), ) => { if has_default && is_host_effect { @@ -1346,7 +1346,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.fcx.var_for_def(self.span, param) } } - GenericParamDefKind::Const { has_default, is_host_effect } => { + GenericParamDefKind::Const { has_default, is_host_effect, .. } => { if has_default { // N.B. this is a bit of a hack. `infer_args` is passed depending on // whether the user has provided generic args. E.g. for `Vec::new` diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 1138642c56d61..c6d72700b3fce 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -238,7 +238,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Otherwise, there's a mismatch, so clear out what we're expecting, and set // our input types to err_args so we don't blow up the error messages let guar = struct_span_code_err!( - tcx.dcx(), + self.dcx(), call_span, E0059, "cannot use call notation; the first type parameter \ @@ -453,7 +453,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .map(|vars| self.resolve_vars_if_possible(vars)), ); - self.set_tainted_by_errors(self.report_arg_errors( + self.report_arg_errors( compatibility_diagonal, formal_and_expected_inputs, provided_args, @@ -462,7 +462,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn_def_id, call_span, call_expr, - )); + ); } } @@ -788,7 +788,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { format!("arguments to this {call_name} are incorrect"), ); } else { - err = tcx.dcx().struct_span_err( + err = self.dcx().struct_span_err( full_call_span, format!( "{call_name} takes {}{} but {} {} supplied", @@ -848,7 +848,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span_bug!(error_span, "expected errors from argument matrix"); } else { let mut err = - tcx.dcx().create_err(errors::ArgMismatchIndeterminate { span: error_span }); + self.dcx().create_err(errors::ArgMismatchIndeterminate { span: error_span }); suggest_confusable(&mut err); return err.emit(); } @@ -951,16 +951,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return err.emit(); } + // Special case, we found an extra argument is provided, which is very common in practice. + // but there is a obviously better removing suggestion compared to the current one, + // try to find the argument with Error type, if we removed it all the types will become good, + // then we will replace the current suggestion. + if let [Error::Extra(provided_idx)] = &errors[..] { + let remove_idx_is_perfect = |idx: usize| -> bool { + let removed_arg_tys = provided_arg_tys + .iter() + .enumerate() + .filter_map(|(j, arg)| if idx == j { None } else { Some(arg) }) + .collect::>(); + std::iter::zip(formal_and_expected_inputs.iter(), removed_arg_tys.iter()).all( + |((expected_ty, _), (provided_ty, _))| { + !provided_ty.references_error() + && self.can_coerce(*provided_ty, *expected_ty) + }, + ) + }; + + if !remove_idx_is_perfect(provided_idx.as_usize()) { + if let Some(i) = (0..provided_args.len()).find(|&i| remove_idx_is_perfect(i)) { + errors = vec![Error::Extra(ProvidedIdx::from_usize(i))]; + } + } + } + let mut err = if formal_and_expected_inputs.len() == provided_args.len() { struct_span_code_err!( - tcx.dcx(), + self.dcx(), full_call_span, E0308, "arguments to this {} are incorrect", call_name, ) } else { - tcx.dcx() + self.dcx() .struct_span_err( full_call_span, format!( @@ -1424,7 +1450,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected_ty: Ty<'tcx>, provided_ty: Ty<'tcx>, arg: &hir::Expr<'tcx>, - err: &mut Diag<'tcx>, + err: &mut Diag<'_>, ) { if let ty::RawPtr(_, hir::Mutability::Mut) = expected_ty.kind() && let ty::RawPtr(_, hir::Mutability::Not) = provided_ty.kind() @@ -2042,7 +2068,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if block_num > 1 && found_semi { err.span_suggestion_verbose( - span.shrink_to_lo(), + // use the span of the *whole* expr + self.tcx.hir().span(binding_hir_id).shrink_to_lo(), "you might have meant to return this to infer its type parameters", "return ", Applicability::MaybeIncorrect, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index c0d604779677b..da68da029b417 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -144,8 +144,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub(crate) fn dcx(&self) -> DiagCtxtHandle<'tcx> { - self.infcx.dcx() + pub(crate) fn dcx(&self) -> DiagCtxtHandle<'a> { + self.root_ctxt.infcx.dcx() } pub fn cause(&self, span: Span, code: ObligationCauseCode<'tcx>) -> ObligationCause<'tcx> { @@ -274,6 +274,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> { } }), ), + effects_min_tys: ty::List::empty(), } } diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs index 5eafc60a04eb8..0389c06c3123f 100644 --- a/compiler/rustc_hir_typeck/src/intrinsicck.rs +++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs @@ -52,7 +52,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Note: this path is currently not reached in any test, so any // example that triggers this would be worth minimizing and // converting into a test. - tcx.dcx().span_bug(span, "argument to transmute has inference variables"); + self.dcx().span_bug(span, "argument to transmute has inference variables"); } // Transmutes that are only changing lifetimes are always ok. if from == to { @@ -76,7 +76,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let (&ty::FnDef(..), SizeSkeleton::Known(size_to, _)) = (from.kind(), sk_to) && size_to == Pointer(dl.instruction_address_space).size(&tcx) { - struct_span_code_err!(tcx.dcx(), span, E0591, "can't transmute zero-sized type") + struct_span_code_err!(self.dcx(), span, E0591, "can't transmute zero-sized type") .with_note(format!("source type: {from}")) .with_note(format!("target type: {to}")) .with_help("cast with `as` to a pointer instead") @@ -116,7 +116,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let mut err = struct_span_code_err!( - tcx.dcx(), + self.dcx(), span, E0512, "cannot transmute between types of different sizes, \ diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index e1223307b53e3..ff8899ae0368d 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -21,7 +21,7 @@ use rustc_middle::ty::{self, GenericParamDefKind, Ty, TypeVisitableExt}; use rustc_middle::ty::{GenericArgs, GenericArgsRef}; use rustc_middle::{bug, span_bug}; use rustc_span::symbol::Ident; -use rustc_span::Span; +use rustc_span::{sym, Span}; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::{self, NormalizeExt}; @@ -356,6 +356,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Option>> { let (obligation, args) = self.obligation_for_method(cause, trait_def_id, self_ty, opt_input_types); + // FIXME(effects) find a better way to do this + // Operators don't have generic methods, but making them `#[const_trait]` gives them + // `const host: bool`. + let args = if self.tcx.has_attr(trait_def_id, sym::const_trait) { + self.tcx.mk_args_from_iter( + args.iter() + .chain([self.tcx.expected_host_effect_param_for_body(self.body_id).into()]), + ) + } else { + args + }; self.construct_obligation_for_trait(m_name, trait_def_id, obligation, args) } @@ -393,6 +404,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!("lookup_in_trait_adjusted: method_item={:?}", method_item); let mut obligations = vec![]; + // FIXME(effects): revisit when binops get `#[const_trait]` + // Instantiate late-bound regions and instantiate the trait // parameters into the method type to get the actual method type. // diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 9747a91ccbfad..63b30d79aba14 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1279,6 +1279,7 @@ impl<'tcx> Pick<'tcx> { trait_item_def_id: _, fn_has_self_parameter: _, opt_rpitit_info: _, + is_effects_desugaring: _, }, kind: _, import_ids: _, diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index a385bc70e359b..e310730bf9e91 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -705,7 +705,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut err = if is_write && let SelfSource::MethodCall(rcvr_expr) = source { self.suggest_missing_writer(rcvr_ty, rcvr_expr) } else { - let mut err = tcx.dcx().create_err(NoAssociatedItem { + let mut err = self.dcx().create_err(NoAssociatedItem { span, item_kind, item_name, @@ -1194,7 +1194,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: item_span, .. })) => { - tcx.dcx().span_delayed_bug( + self.dcx().span_delayed_bug( *item_span, "auto trait is invoked with no method error, but no error reported?", ); @@ -2361,7 +2361,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); if pick.is_ok() { let range_span = parent_expr.span.with_hi(expr.span.hi()); - return Err(tcx.dcx().emit_err(errors::MissingParenthesesInRange { + return Err(self.dcx().emit_err(errors::MissingParenthesesInRange { span, ty_str: ty_str.to_string(), method_name: item_name.as_str().to_string(), @@ -2420,7 +2420,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && let SelfSource::MethodCall(expr) = source { let mut err = struct_span_code_err!( - tcx.dcx(), + self.dcx(), span, E0689, "can't call {} `{}` on ambiguous numeric type `{}`", diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index aaf3d3ec34d01..f932a27e9a287 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -89,7 +89,7 @@ struct PatInfo<'tcx, 'a> { current_depth: u32, } -impl<'tcx> FnCtxt<'_, 'tcx> { +impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn pattern_cause(&self, ti: &TopInfo<'tcx>, cause_span: Span) -> ObligationCause<'tcx> { let code = ObligationCauseCode::Pattern { span: ti.span, @@ -100,12 +100,12 @@ impl<'tcx> FnCtxt<'_, 'tcx> { } fn demand_eqtype_pat_diag( - &self, + &'a self, cause_span: Span, expected: Ty<'tcx>, actual: Ty<'tcx>, ti: &TopInfo<'tcx>, - ) -> Result<(), Diag<'tcx>> { + ) -> Result<(), Diag<'a>> { self.demand_eqtype_with_origin(&self.pattern_cause(ti, cause_span), expected, actual) .map_err(|mut diag| { if let Some(expr) = ti.origin_expr { @@ -698,7 +698,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && let MutblCap::WeaklyNot(and_pat_span) = pat_info.max_ref_mutbl { let mut err = struct_span_code_err!( - self.tcx.dcx(), + self.dcx(), ident.span, E0596, "cannot borrow as mutable inside an `&` pattern" @@ -1010,7 +1010,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (res, opt_ty, segments) = path_resolution; match res { Res::Err => { - let e = tcx.dcx().span_delayed_bug(qpath.span(), "`Res::Err` but no error emitted"); + let e = + self.dcx().span_delayed_bug(qpath.span(), "`Res::Err` but no error emitted"); self.set_tainted_by_errors(e); return Ty::new_error(tcx, e); } @@ -1191,7 +1192,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (res, opt_ty, segments) = self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span); if res == Res::Err { - let e = tcx.dcx().span_delayed_bug(pat.span, "`Res::Err` but no error emitted"); + let e = self.dcx().span_delayed_bug(pat.span, "`Res::Err` but no error emitted"); self.set_tainted_by_errors(e); on_error(e); return Ty::new_error(tcx, e); @@ -1207,7 +1208,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let variant = match res { Res::Err => { - tcx.dcx().span_bug(pat.span, "`Res::Err` but no error emitted"); + self.dcx().span_bug(pat.span, "`Res::Err` but no error emitted"); } Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) => { let e = report_unexpected_res(res); @@ -1549,10 +1550,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Report an error if an incorrect number of fields was specified. if adt.is_union() { if fields.len() != 1 { - tcx.dcx().emit_err(errors::UnionPatMultipleFields { span: pat.span }); + self.dcx().emit_err(errors::UnionPatMultipleFields { span: pat.span }); } if has_rest_pat { - tcx.dcx().emit_err(errors::UnionPatDotDot { span: pat.span }); + self.dcx().emit_err(errors::UnionPatDotDot { span: pat.span }); } } else if !unmentioned_fields.is_empty() { let accessible_unmentioned_fields: Vec<_> = unmentioned_fields @@ -1690,7 +1691,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat: &'tcx Pat<'tcx>, variant: &ty::VariantDef, args: ty::GenericArgsRef<'tcx>, - ) -> Diag<'tcx> { + ) -> Diag<'a> { let tcx = self.tcx; let (field_names, t, plural) = if let [field] = inexistent_fields { (format!("a field named `{}`", field.ident), "this", "") @@ -1710,7 +1711,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let spans = inexistent_fields.iter().map(|field| field.ident.span).collect::>(); let mut err = struct_span_code_err!( - tcx.dcx(), + self.dcx(), spans, E0026, "{} `{}` does not have {}", @@ -1881,7 +1882,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, pat: &Pat<'_>, fields: &'tcx [hir::PatField<'tcx>], - ) -> Diag<'tcx> { + ) -> Diag<'a> { let mut err = self .dcx() .struct_span_err(pat.span, "pattern requires `..` due to inaccessible fields"); @@ -1973,7 +1974,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { unmentioned_fields: &[(&ty::FieldDef, Ident)], have_inaccessible_fields: bool, fields: &'tcx [hir::PatField<'tcx>], - ) -> Diag<'tcx> { + ) -> Diag<'a> { let inaccessible = if have_inaccessible_fields { " and inaccessible fields" } else { "" }; let field_names = if let [(_, field)] = unmentioned_fields { format!("field `{field}`{inaccessible}") diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 227691d099434..a8fd3ca8c59bd 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -139,7 +139,7 @@ pub struct TypeErrCtxt<'a, 'tcx> { } impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { - pub fn dcx(&self) -> DiagCtxtHandle<'tcx> { + pub fn dcx(&self) -> DiagCtxtHandle<'a> { self.infcx.dcx() } @@ -305,16 +305,17 @@ fn label_msg_span( } } -#[instrument(level = "trace", skip(tcx))] -pub fn unexpected_hidden_region_diagnostic<'tcx>( - tcx: TyCtxt<'tcx>, +#[instrument(level = "trace", skip(infcx))] +pub fn unexpected_hidden_region_diagnostic<'a, 'tcx>( + infcx: &'a InferCtxt<'tcx>, generic_param_scope: LocalDefId, span: Span, hidden_ty: Ty<'tcx>, hidden_region: ty::Region<'tcx>, opaque_ty_key: ty::OpaqueTypeKey<'tcx>, -) -> Diag<'tcx> { - let mut err = tcx.dcx().create_err(errors::OpaqueCapturesLifetime { +) -> Diag<'a> { + let tcx = infcx.tcx; + let mut err = infcx.dcx().create_err(errors::OpaqueCapturesLifetime { span, opaque_ty: Ty::new_opaque(tcx, opaque_ty_key.def_id.to_def_id(), opaque_ty_key.args), opaque_ty_span: tcx.def_span(opaque_ty_key.def_id), @@ -436,7 +437,7 @@ impl<'tcx> InferCtxt<'tcx> { } } -impl<'tcx> TypeErrCtxt<'_, 'tcx> { +impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { pub fn report_region_errors( &self, generic_param_scope: LocalDefId, @@ -2206,7 +2207,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { &self, trace: TypeTrace<'tcx>, terr: TypeError<'tcx>, - ) -> Diag<'tcx> { + ) -> Diag<'a> { debug!("report_and_explain_type_error(trace={:?}, terr={:?})", trace, terr); let span = trace.cause.span(); @@ -2215,7 +2216,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { span, self.type_error_additional_suggestions(&trace, terr), ); - let mut diag = self.tcx.dcx().create_err(failure_code); + let mut diag = self.dcx().create_err(failure_code); self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr, false, false); diag } @@ -2357,14 +2358,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { origin: Option>, bound_kind: GenericKind<'tcx>, sub: Region<'tcx>, - ) -> Diag<'tcx> { + ) -> Diag<'a> { if let Some(SubregionOrigin::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id, }) = origin { - return self.report_extra_impl_obligation( + return self.infcx.report_extra_impl_obligation( span, impl_item_def_id, trait_item_def_id, @@ -2790,7 +2791,7 @@ impl<'tcx> TypeRelation> for SameTypeModuloInfer<'_, 'tcx> { } impl<'tcx> InferCtxt<'tcx> { - fn report_inference_failure(&self, var_origin: RegionVariableOrigin) -> Diag<'tcx> { + fn report_inference_failure(&self, var_origin: RegionVariableOrigin) -> Diag<'_> { let br_string = |br: ty::BoundRegionKind| { let mut s = match br { ty::BrNamed(_, name) => name.to_string(), @@ -2829,7 +2830,7 @@ impl<'tcx> InferCtxt<'tcx> { }; struct_span_code_err!( - self.tcx.dcx(), + self.dcx(), var_origin.span(), E0495, "cannot infer an appropriate lifetime{} due to conflicting requirements", diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index d7349abc44c24..084aebc296f86 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -391,7 +391,7 @@ impl<'tcx> InferCtxt<'tcx> { span: Span, arg_data: InferenceDiagnosticsData, error_code: TypeAnnotationNeeded, - ) -> Diag<'tcx> { + ) -> Diag<'_> { let source_kind = "other"; let source_name = ""; let failure_span = None; @@ -436,7 +436,7 @@ impl<'tcx> InferCtxt<'tcx> { } } -impl<'tcx> TypeErrCtxt<'_, 'tcx> { +impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { #[instrument(level = "debug", skip(self, error_code))] pub fn emit_inference_failure_err( &self, @@ -445,7 +445,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { arg: GenericArg<'tcx>, error_code: TypeAnnotationNeeded, should_label_span: bool, - ) -> Diag<'tcx> { + ) -> Diag<'a> { let arg = self.resolve_vars_if_possible(arg); let arg_data = self.extract_inference_diagnostics_data(arg, None); @@ -453,7 +453,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { // If we don't have any typeck results we're outside // of a body, so we won't be able to get better info // here. - return self.bad_inference_failure_err(failure_span, arg_data, error_code); + return self.infcx.bad_inference_failure_err(failure_span, arg_data, error_code); }; let mut local_visitor = FindInferSourceVisitor::new(self, typeck_results, arg); @@ -465,7 +465,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } let Some(InferSource { span, kind }) = local_visitor.infer_source else { - return self.bad_inference_failure_err(failure_span, arg_data, error_code); + return self.infcx.bad_inference_failure_err(failure_span, arg_data, error_code); }; let (source_kind, name, path) = kind.ty_localized_msg(self); diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index 8fd19563c3057..d1fc9c9f140b1 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -14,7 +14,7 @@ use rustc_span::symbol::kw; use super::ObligationCauseAsDiagArg; -impl<'tcx> TypeErrCtxt<'_, 'tcx> { +impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { pub(super) fn note_region_origin(&self, err: &mut Diag<'_>, origin: &SubregionOrigin<'tcx>) { match *origin { infer::Subtype(ref trace) => RegionOriginNote::WithRequirement { @@ -79,7 +79,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { origin: SubregionOrigin<'tcx>, sub: Region<'tcx>, sup: Region<'tcx>, - ) -> Diag<'tcx> { + ) -> Diag<'a> { let mut err = match origin { infer::Subtype(box trace) => { let terr = TypeError::RegionsDoesNotOutlive(sup, sub); @@ -245,7 +245,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { }) } infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => { - let mut err = self.report_extra_impl_obligation( + let mut err = self.infcx.report_extra_impl_obligation( span, impl_item_def_id, trait_item_def_id, @@ -378,7 +378,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { placeholder_origin: SubregionOrigin<'tcx>, sub: Region<'tcx>, sup: Region<'tcx>, - ) -> Diag<'tcx> { + ) -> Diag<'a> { // I can't think how to do better than this right now. -nikomatsakis debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure"); match placeholder_origin { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index a3cf588da1c02..ff593d7ffb7df 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -684,8 +684,8 @@ impl<'tcx> InferOk<'tcx, ()> { } impl<'tcx> InferCtxt<'tcx> { - pub fn dcx(&self) -> DiagCtxtHandle<'tcx> { - self.tcx.dcx() + pub fn dcx(&self) -> DiagCtxtHandle<'_> { + self.tcx.dcx().taintable_handle(&self.tainted_by_errors) } pub fn defining_opaque_types(&self) -> &'tcx ty::List { @@ -1089,19 +1089,7 @@ impl<'tcx> InferCtxt<'tcx> { /// inference variables, regionck errors). #[must_use = "this method does not have any side effects"] pub fn tainted_by_errors(&self) -> Option { - if let Some(guar) = self.tainted_by_errors.get() { - Some(guar) - } else if self.dcx().err_count_excluding_lint_errs() > self.err_count_on_creation { - // Errors reported since this infcx was made. Lint errors are - // excluded to avoid some being swallowed in the presence of - // non-lint errors. (It's arguable whether or not this exclusion is - // important.) - let guar = self.dcx().has_errors().unwrap(); - self.set_tainted_by_errors(guar); - Some(guar) - } else { - None - } + self.tainted_by_errors.get() } /// Set the "tainted by errors" flag to true. We call this when we @@ -1328,8 +1316,7 @@ impl<'tcx> InferCtxt<'tcx> { bug!("`{value:?}` is not fully resolved"); } if value.has_infer_regions() { - let guar = - self.tcx.dcx().delayed_bug(format!("`{value:?}` is not fully resolved")); + let guar = self.dcx().delayed_bug(format!("`{value:?}` is not fully resolved")); Ok(self.tcx.fold_regions(value, |re, _| { if re.is_var() { ty::Region::new_error(self.tcx, guar) } else { re } })) @@ -1607,7 +1594,7 @@ impl<'tcx> InferCtxt<'tcx> { } } -impl<'tcx> TypeErrCtxt<'_, 'tcx> { +impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // [Note-Type-error-reporting] // An invariant is that anytime the expected or actual type is Error (the special // error type, meaning that an error occurred when typechecking this expression), @@ -1623,9 +1610,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { sp: Span, mk_diag: M, actual_ty: Ty<'tcx>, - ) -> Diag<'tcx> + ) -> Diag<'a> where - M: FnOnce(String) -> Diag<'tcx>, + M: FnOnce(String) -> Diag<'a>, { let actual_ty = self.resolve_vars_if_possible(actual_ty); debug!("type_error_struct_with_diag({:?}, {:?})", sp, actual_ty); @@ -1646,7 +1633,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { expected: Ty<'tcx>, actual: Ty<'tcx>, err: TypeError<'tcx>, - ) -> Diag<'tcx> { + ) -> Diag<'a> { self.report_and_explain_type_error(TypeTrace::types(cause, true, expected, actual), err) } @@ -1656,7 +1643,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { expected: ty::Const<'tcx>, actual: ty::Const<'tcx>, err: TypeError<'tcx>, - ) -> Diag<'tcx> { + ) -> Diag<'a> { self.report_and_explain_type_error(TypeTrace::consts(cause, true, expected, actual), err) } } diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index b8dd501a721b5..7c764cccc4772 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -156,7 +156,7 @@ impl<'tcx> InferCtxt<'tcx> { if self.can_define_opaque_ty(b_def_id) && self.tcx.is_type_alias_impl_trait(b_def_id) { - self.tcx.dcx().emit_err(OpaqueHiddenTypeDiag { + self.dcx().emit_err(OpaqueHiddenTypeDiag { span, hidden_type: self.tcx.def_span(b_def_id), opaque_type: self.tcx.def_span(def_id), diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs index 890e25368bc75..7730fe29e0933 100644 --- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs @@ -12,15 +12,15 @@ use std::fmt; use std::iter; impl<'tcx> InferCtxt<'tcx> { - pub fn report_extra_impl_obligation( - &self, + pub fn report_extra_impl_obligation<'a>( + &'a self, error_span: Span, impl_item_def_id: LocalDefId, trait_item_def_id: DefId, requirement: &dyn fmt::Display, - ) -> Diag<'tcx> { + ) -> Diag<'a> { let mut err = struct_span_code_err!( - self.tcx.dcx(), + self.dcx(), error_span, E0276, "impl has stricter requirements than trait" diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index ab4148faaab63..24cf9f03fcdb3 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -275,10 +275,10 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { } // Get predicates implied by the trait, or only super predicates if we only care about self predicates. let predicates = match self.mode { - Filter::All => tcx.implied_predicates_of(data.def_id()), - Filter::OnlySelf => tcx.super_predicates_of(data.def_id()), + Filter::All => tcx.explicit_implied_predicates_of(data.def_id()), + Filter::OnlySelf => tcx.explicit_super_predicates_of(data.def_id()), Filter::OnlySelfThatDefines(ident) => { - tcx.super_predicates_that_define_assoc_item((data.def_id(), ident)) + tcx.explicit_supertraits_containing_assoc_item((data.def_id(), ident)) } }; @@ -420,7 +420,7 @@ pub fn transitive_bounds<'tcx>( /// A specialized variant of `elaborate` that only elaborates trait references that may /// define the given associated item with the name `assoc_name`. It uses the -/// `super_predicates_that_define_assoc_item` query to avoid enumerating super-predicates that +/// `explicit_supertraits_containing_assoc_item` query to avoid enumerating super-predicates that /// aren't related to `assoc_item`. This is used when resolving types like `Self::Item` or /// `T::Item` and helps to avoid cycle errors (see e.g. #35237). pub fn transitive_bounds_that_define_assoc_item<'tcx>( diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 02322c9b2828f..9bd67a1154b7d 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -2,14 +2,22 @@ use crate::interface::{initialize_checked_jobserver, parse_cfg}; use rustc_data_structures::profiling::TimePassesFormat; use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig}; +use rustc_session::config::{build_configuration, build_session_options, rustc_optgroups}; use rustc_session::config::{ - build_configuration, build_session_options, rustc_optgroups, BranchProtection, CFGuard, Cfg, - CollapseMacroDebuginfo, CoverageLevel, CoverageOptions, DebugInfo, DumpMonoStatsFormat, - ErrorOutputType, ExternEntry, ExternLocation, Externs, FunctionReturn, InliningThreshold, - Input, InstrumentCoverage, InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail, - LtoCli, NextSolverConfig, OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, - PacRet, Passes, PatchableFunctionEntry, Polonius, ProcMacroExecutionStrategy, Strip, - SwitchWithOptPath, SymbolManglingVersion, WasiExecModel, + BranchProtection, CFGuard, Cfg, CollapseMacroDebuginfo, CoverageLevel, CoverageOptions, + DebugInfo, DumpMonoStatsFormat, ErrorOutputType, +}; +use rustc_session::config::{ + ExternEntry, ExternLocation, Externs, FunctionReturn, InliningThreshold, Input, + InstrumentCoverage, InstrumentXRay, LinkSelfContained, LinkerPluginLto, +}; +use rustc_session::config::{ + LocationDetail, LtoCli, NextSolverConfig, OomStrategy, Options, OutFileName, OutputType, + OutputTypes, PAuthKey, PacRet, Passes, PatchableFunctionEntry, +}; +use rustc_session::config::{ + Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion, + WasiExecModel, }; use rustc_session::lint::Level; use rustc_session::search_paths::SearchPath; diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 46cf87d1e3c17..3e952558d29d3 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -56,8 +56,6 @@ lint_builtin_asm_labels = avoid using named labels in inline assembly .help = only local labels of the form `:` should be used in inline asm .note = see the asm section of Rust By Example for more information -lint_builtin_box_pointers = type uses owned (Box type) pointers: {$ty} - lint_builtin_clashing_extern_diff_name = `{$this}` redeclares `{$orig}` with a different signature .previous_decl_label = `{$orig}` previously declared here .mismatch_label = this signature doesn't match the previous declaration diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 98318cd14d9dc..79c8046f9b741 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -24,9 +24,9 @@ use crate::fluent_generated as fluent; use crate::{ errors::BuiltinEllipsisInclusiveRangePatterns, lints::{ - BuiltinAnonymousParams, BuiltinBoxPointers, BuiltinConstNoMangle, - BuiltinDeprecatedAttrLink, BuiltinDeprecatedAttrLinkSuggestion, BuiltinDeprecatedAttrUsed, - BuiltinDerefNullptr, BuiltinEllipsisInclusiveRangePatternsLint, BuiltinExplicitOutlives, + BuiltinAnonymousParams, BuiltinConstNoMangle, BuiltinDeprecatedAttrLink, + BuiltinDeprecatedAttrLinkSuggestion, BuiltinDeprecatedAttrUsed, BuiltinDerefNullptr, + BuiltinEllipsisInclusiveRangePatternsLint, BuiltinExplicitOutlives, BuiltinExplicitOutlivesSuggestion, BuiltinFeatureIssueNote, BuiltinIncompleteFeatures, BuiltinIncompleteFeaturesHelp, BuiltinInternalFeatures, BuiltinKeywordIdents, BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc, @@ -56,7 +56,6 @@ use rustc_middle::bug; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::GenericArgKind; use rustc_middle::ty::TypeVisitableExt; use rustc_middle::ty::Upcast; use rustc_middle::ty::{self, Ty, TyCtxt, VariantDef}; @@ -134,80 +133,6 @@ impl EarlyLintPass for WhileTrue { } } -declare_lint! { - /// The `box_pointers` lints use of the Box type. - /// - /// ### Example - /// - /// ```rust,compile_fail - /// #![deny(box_pointers)] - /// struct Foo { - /// x: Box, - /// } - /// ``` - /// - /// {{produces}} - /// - /// ### Explanation - /// - /// This lint is mostly historical, and not particularly useful. `Box` - /// used to be built into the language, and the only way to do heap - /// allocation. Today's Rust can call into other allocators, etc. - BOX_POINTERS, - Allow, - "use of owned (Box type) heap memory" -} - -declare_lint_pass!(BoxPointers => [BOX_POINTERS]); - -impl BoxPointers { - fn check_heap_type(&self, cx: &LateContext<'_>, span: Span, ty: Ty<'_>) { - for leaf in ty.walk() { - if let GenericArgKind::Type(leaf_ty) = leaf.unpack() - && leaf_ty.is_box() - { - cx.emit_span_lint(BOX_POINTERS, span, BuiltinBoxPointers { ty }); - } - } - } -} - -impl<'tcx> LateLintPass<'tcx> for BoxPointers { - fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { - match it.kind { - hir::ItemKind::Fn(..) - | hir::ItemKind::TyAlias(..) - | hir::ItemKind::Enum(..) - | hir::ItemKind::Struct(..) - | hir::ItemKind::Union(..) => self.check_heap_type( - cx, - it.span, - cx.tcx.type_of(it.owner_id).instantiate_identity(), - ), - _ => (), - } - - // If it's a struct, we also have to check the fields' types - match it.kind { - hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => { - for field in struct_def.fields() { - self.check_heap_type( - cx, - field.span, - cx.tcx.type_of(field.def_id).instantiate_identity(), - ); - } - } - _ => (), - } - } - - fn check_expr(&mut self, cx: &LateContext<'_>, e: &hir::Expr<'_>) { - let ty = cx.typeck_results().node_type(e.hir_id); - self.check_heap_type(cx, e.span, ty); - } -} - declare_lint! { /// The `non_shorthand_field_patterns` lint detects using `Struct { x: x }` /// instead of `Struct { x }` in a pattern. @@ -1640,7 +1565,6 @@ declare_lint_pass!( /// which are used by other parts of the compiler. SoftLints => [ WHILE_TRUE, - BOX_POINTERS, NON_SHORTHAND_FIELD_PATTERNS, UNSAFE_CODE, MISSING_DOCS, diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 7dae2de7bfb58..17f9d4421aef2 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -187,7 +187,6 @@ late_lint_methods!( ImproperCTypesDefinitions: ImproperCTypesDefinitions, InvalidFromUtf8: InvalidFromUtf8, VariantSizeDifferences: VariantSizeDifferences, - BoxPointers: BoxPointers, PathStatements: PathStatements, LetUnderscore: LetUnderscore, InvalidReferenceCasting: InvalidReferenceCasting, @@ -551,6 +550,10 @@ fn register_builtins(store: &mut LintStore) { "converted into hard error, see RFC #3535 \ for more information", ); + store.register_removed( + "box_pointers", + "it does not detect other kinds of allocations, and existed only for historical reasons", + ); } fn register_internals(store: &mut LintStore) { diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 14084405d0ee1..7c5640f5959a0 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -66,12 +66,6 @@ pub struct BuiltinWhileTrue { pub replace: String, } -#[derive(LintDiagnostic)] -#[diag(lint_builtin_box_pointers)] -pub struct BuiltinBoxPointers<'a> { - pub ty: Ty<'a>, -} - #[derive(LintDiagnostic)] #[diag(lint_builtin_non_shorthand_field_patterns)] pub struct BuiltinNonShorthandFieldPatterns { diff --git a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs index aa1d94228ea22..445dcd41e5d52 100644 --- a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs +++ b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs @@ -45,7 +45,7 @@ impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable { { let direct_super_traits_iter = cx .tcx - .super_predicates_of(def_id) + .explicit_super_predicates_of(def_id) .predicates .into_iter() .filter_map(|(pred, _)| pred.as_trait_clause()); diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index 300dac442d564..17429ed061f25 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -50,7 +50,7 @@ declare_lint! { /// All nested bodies (functions, enum discriminant, array length, consts) (expect for /// `const _: Ty = { ... }` in top-level module, which is still undecided) are checked. pub NON_LOCAL_DEFINITIONS, - Warn, + Allow, "checks for non-local definitions", report_in_external_macro } diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 472e93d202d76..2ade6964ca89e 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -74,6 +74,7 @@ declare_lint_pass! { NON_CONTIGUOUS_RANGE_ENDPOINTS, NON_EXHAUSTIVE_OMITTED_PATTERNS, ORDER_DEPENDENT_TRAIT_OBJECTS, + OUT_OF_SCOPE_MACRO_CALLS, OVERLAPPING_RANGE_ENDPOINTS, PATTERNS_IN_FNS_WITHOUT_BODY, PRIVATE_BOUNDS, diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index ea7037740f17e..83b41e0540edf 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1348,7 +1348,9 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } fn get_associated_item(self, id: DefIndex, sess: &'a Session) -> ty::AssocItem { - let name = if self.root.tables.opt_rpitit_info.get(self, id).is_some() { + let name = if self.root.tables.opt_rpitit_info.get(self, id).is_some() + || self.root.tables.is_effects_desugaring.get(self, id) + { kw::Empty } else { self.item_name(id) @@ -1371,6 +1373,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { container, fn_has_self_parameter: has_self, opt_rpitit_info, + is_effects_desugaring: self.root.tables.is_effects_desugaring.get(self, id), } } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index c9450142cd3be..6b240f0f0b3de 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -211,8 +211,8 @@ provide! { tcx, def_id, other, cdata, explicit_predicates_of => { table } generics_of => { table } inferred_outlives_of => { table_defaulted_array } - super_predicates_of => { table } - implied_predicates_of => { table } + explicit_super_predicates_of => { table } + explicit_implied_predicates_of => { table } type_of => { table } type_alias_is_lazy => { cdata.root.tables.type_alias_is_lazy.get(cdata, def_id.index) } variances_of => { table } @@ -279,6 +279,9 @@ provide! { tcx, def_id, other, cdata, .process_decoded(tcx, || panic!("{def_id:?} does not have trait_impl_trait_tys"))) } + associated_type_for_effects => { + table + } associated_types_for_impl_traits_in_associated_fn => { table_defaulted_array } visibility => { cdata.get_visibility(def_id.index) } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 4bd2ec09a6e6f..209316ca20fdb 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1431,8 +1431,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } if let DefKind::Trait = def_kind { record!(self.tables.trait_def[def_id] <- self.tcx.trait_def(def_id)); - record!(self.tables.super_predicates_of[def_id] <- self.tcx.super_predicates_of(def_id)); - record!(self.tables.implied_predicates_of[def_id] <- self.tcx.implied_predicates_of(def_id)); + record!(self.tables.explicit_super_predicates_of[def_id] <- self.tcx.explicit_super_predicates_of(def_id)); + record!(self.tables.explicit_implied_predicates_of[def_id] <- self.tcx.explicit_implied_predicates_of(def_id)); let module_children = self.tcx.module_children_local(local_id); record_array!(self.tables.module_children_non_reexports[def_id] <- @@ -1440,8 +1440,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } if let DefKind::TraitAlias = def_kind { record!(self.tables.trait_def[def_id] <- self.tcx.trait_def(def_id)); - record!(self.tables.super_predicates_of[def_id] <- self.tcx.super_predicates_of(def_id)); - record!(self.tables.implied_predicates_of[def_id] <- self.tcx.implied_predicates_of(def_id)); + record!(self.tables.explicit_super_predicates_of[def_id] <- self.tcx.explicit_super_predicates_of(def_id)); + record!(self.tables.explicit_implied_predicates_of[def_id] <- self.tcx.explicit_implied_predicates_of(def_id)); } if let DefKind::Trait | DefKind::Impl { .. } = def_kind { let associated_item_def_ids = self.tcx.associated_item_def_ids(def_id); @@ -1454,6 +1454,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { for &def_id in associated_item_def_ids { self.encode_info_for_assoc_item(def_id); } + if let Some(assoc_def_id) = self.tcx.associated_type_for_effects(def_id) { + record!(self.tables.associated_type_for_effects[def_id] <- assoc_def_id); + } } if def_kind == DefKind::Closure && let Some(coroutine_kind) = self.tcx.coroutine_kind(def_id) @@ -1634,6 +1637,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { ); } } + if item.is_effects_desugaring { + self.tables.is_effects_desugaring.set(def_id.index, true); + } } fn encode_mir(&mut self) { diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 87900c23d8daf..2a44b3423ae2f 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -391,7 +391,9 @@ define_tables! { inferred_outlives_of: Table, Span)>>, inherent_impls: Table>, associated_types_for_impl_traits_in_associated_fn: Table>, + associated_type_for_effects: Table>>, opt_rpitit_info: Table>>, + is_effects_desugaring: Table, unused_generic_params: Table, // Reexported names are not associated with individual `DefId`s, // e.g. a glob import can introduce a lot of names, all with the same `DefId`. @@ -416,10 +418,10 @@ define_tables! { lookup_deprecation_entry: Table>, explicit_predicates_of: Table>>, generics_of: Table>, - super_predicates_of: Table>>, + explicit_super_predicates_of: Table>>, // As an optimization, we only store this for trait aliases, - // since it's identical to super_predicates_of for traits. - implied_predicates_of: Table>>, + // since it's identical to explicit_super_predicates_of for traits. + explicit_implied_predicates_of: Table>>, type_of: Table>>>, variances_of: Table>, fn_sig: Table>>>, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 230a44bcf2452..d40a783358959 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -368,6 +368,7 @@ rustc_queries! { desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } separate_provide_extern + feedable } /// The set of item bounds (see [`TyCtxt::explicit_item_bounds`]) that @@ -378,6 +379,7 @@ rustc_queries! { desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } separate_provide_extern + feedable } /// Elaborated version of the predicates from `explicit_item_bounds`. @@ -646,6 +648,9 @@ rustc_queries! { } /// Returns the predicates written explicitly by the user. + /// + /// You should probably use `predicates_of` unless you're looking for + /// predicates with explicit spans for diagnostics purposes. query explicit_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { desc { |tcx| "computing explicit predicates of `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } @@ -662,29 +667,32 @@ rustc_queries! { feedable } - /// Maps from the `DefId` of a trait to the list of - /// super-predicates. This is a subset of the full list of - /// predicates. We store these in a separate map because we must - /// evaluate them even during type conversion, often before the - /// full predicates are available (note that supertraits have - /// additional acyclicity requirements). - query super_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { + /// Maps from the `DefId` of a trait to the list of super-predicates of the trait, + /// *before* elaboration (so it doesn't contain transitive super-predicates). This + /// is a subset of the full list of predicates. We store these in a separate map + /// because we must evaluate them even during type conversion, often before the full + /// predicates are available (note that super-predicates must not be cyclic). + query explicit_super_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { desc { |tcx| "computing the super predicates of `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } separate_provide_extern } - query implied_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { + /// The predicates of the trait that are implied during elaboration. This is a + /// superset of the super-predicates of the trait, but a subset of the predicates + /// of the trait. For regular traits, this includes all super-predicates and their + /// associated type bounds. For trait aliases, currently, this includes all of the + /// predicates of the trait alias. + query explicit_implied_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { desc { |tcx| "computing the implied predicates of `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } separate_provide_extern } - /// The `Option` is the name of an associated type. If it is `None`, then this query - /// returns the full set of predicates. If `Some`, then the query returns only the - /// subset of super-predicates that reference traits that define the given associated type. - /// This is used to avoid cycles in resolving types like `T::Item`. - query super_predicates_that_define_assoc_item(key: (DefId, rustc_span::symbol::Ident)) -> ty::GenericPredicates<'tcx> { + /// The Ident is the name of an associated type.The query returns only the subset + /// of supertraits that define the given associated type. This is used to avoid + /// cycles in resolving type-dependent associated item paths like `T::Item`. + query explicit_supertraits_containing_assoc_item(key: (DefId, rustc_span::symbol::Ident)) -> ty::GenericPredicates<'tcx> { desc { |tcx| "computing the super traits of `{}` with associated type name `{}`", tcx.def_path_str(key.0), key.1 @@ -847,6 +855,12 @@ rustc_queries! { separate_provide_extern } + query associated_type_for_effects(def_id: DefId) -> Option { + desc { |tcx| "creating associated items for effects in `{}`", tcx.def_path_str(def_id) } + cache_on_disk_if { def_id.is_local() } + separate_provide_extern + } + /// Given an impl trait in trait `opaque_ty_def_id`, create and return the corresponding /// associated item. query associated_type_for_impl_trait_in_trait(opaque_ty_def_id: LocalDefId) -> LocalDefId { diff --git a/compiler/rustc_middle/src/traits/util.rs b/compiler/rustc_middle/src/traits/util.rs index adbb6cf2ddc94..7437be7a74c14 100644 --- a/compiler/rustc_middle/src/traits/util.rs +++ b/compiler/rustc_middle/src/traits/util.rs @@ -35,7 +35,7 @@ struct Elaborator<'tcx> { impl<'tcx> Elaborator<'tcx> { fn elaborate(&mut self, trait_ref: PolyTraitRef<'tcx>) { let super_predicates = - self.tcx.super_predicates_of(trait_ref.def_id()).predicates.iter().filter_map( + self.tcx.explicit_super_predicates_of(trait_ref.def_id()).predicates.iter().filter_map( |&(pred, _)| { let clause = pred.instantiate_supertrait(self.tcx, trait_ref); self.visited.insert(clause).then_some(clause) diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index 1cdde3f057c67..820f5e950a9d9 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -34,6 +34,8 @@ pub struct AssocItem { /// return-position `impl Trait` in trait desugaring. The `ImplTraitInTraitData` /// provides additional information about its source. pub opt_rpitit_info: Option, + + pub is_effects_desugaring: bool, } impl AssocItem { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 4bac9396e59a9..9225ae6300fc6 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -342,12 +342,15 @@ impl<'tcx> Interner for TyCtxt<'tcx> { ) } - fn super_predicates_of( + fn explicit_super_predicates_of( self, def_id: DefId, ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { ty::EarlyBinder::bind( - self.super_predicates_of(def_id).instantiate_identity(self).predicates.into_iter(), + self.explicit_super_predicates_of(def_id) + .instantiate_identity(self) + .predicates + .into_iter(), ) } @@ -598,6 +601,11 @@ fn trait_lang_item_to_lang_item(lang_item: TraitSolverLangItem) -> LangItem { TraitSolverLangItem::Destruct => LangItem::Destruct, TraitSolverLangItem::DiscriminantKind => LangItem::DiscriminantKind, TraitSolverLangItem::DynMetadata => LangItem::DynMetadata, + TraitSolverLangItem::EffectsMaybe => LangItem::EffectsMaybe, + TraitSolverLangItem::EffectsIntersection => LangItem::EffectsIntersection, + TraitSolverLangItem::EffectsIntersectionOutput => LangItem::EffectsIntersectionOutput, + TraitSolverLangItem::EffectsNoRuntime => LangItem::EffectsNoRuntime, + TraitSolverLangItem::EffectsRuntime => LangItem::EffectsRuntime, TraitSolverLangItem::FnPtrTrait => LangItem::FnPtrTrait, TraitSolverLangItem::FusedIterator => LangItem::FusedIterator, TraitSolverLangItem::Future => LangItem::Future, @@ -2440,7 +2448,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Given the def_id of a Trait `trait_def_id` and the name of an associated item `assoc_name` /// returns true if the `trait_def_id` defines an associated item of name `assoc_name`. pub fn trait_may_define_assoc_item(self, trait_def_id: DefId, assoc_name: Ident) -> bool { - self.super_traits_of(trait_def_id).any(|trait_did| { + self.supertrait_def_ids(trait_def_id).any(|trait_did| { self.associated_items(trait_did) .filter_by_name_unhygienic(assoc_name.name) .any(|item| self.hygienic_eq(assoc_name, item.ident(self), trait_did)) @@ -2463,9 +2471,9 @@ impl<'tcx> TyCtxt<'tcx> { /// Computes the def-ids of the transitive supertraits of `trait_def_id`. This (intentionally) /// does not compute the full elaborated super-predicates but just the set of def-ids. It is used - /// to identify which traits may define a given associated type to help avoid cycle errors. - /// Returns a `DefId` iterator. - fn super_traits_of(self, trait_def_id: DefId) -> impl Iterator + 'tcx { + /// to identify which traits may define a given associated type to help avoid cycle errors, + /// and to make size estimates for vtable layout computation. + pub fn supertrait_def_ids(self, trait_def_id: DefId) -> impl Iterator + 'tcx { let mut set = FxHashSet::default(); let mut stack = vec![trait_def_id]; @@ -2473,7 +2481,7 @@ impl<'tcx> TyCtxt<'tcx> { iter::from_fn(move || -> Option { let trait_did = stack.pop()?; - let generic_predicates = self.super_predicates_of(trait_did); + let generic_predicates = self.explicit_super_predicates_of(trait_did); for (predicate, _) in generic_predicates.predicates { if let ty::ClauseKind::Trait(data) = predicate.kind().skip_binder() { @@ -3095,9 +3103,9 @@ impl<'tcx> TyCtxt<'tcx> { matches!( node, hir::Node::Item(hir::Item { - kind: hir::ItemKind::Impl(hir::Impl { generics, .. }), + kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), .. - }) if generics.params.iter().any(|p| matches!(p.kind, hir::GenericParamKind::Const { is_host_effect: true, .. })) + }) if matches!(constness, hir::Constness::Const) ) } diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 6467689a8aa15..844023df1e315 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -14,7 +14,7 @@ use super::{Clause, InstantiatedPredicates, ParamConst, ParamTy, Ty, TyCtxt}; pub enum GenericParamDefKind { Lifetime, Type { has_default: bool, synthetic: bool }, - Const { has_default: bool, is_host_effect: bool }, + Const { has_default: bool, is_host_effect: bool, synthetic: bool }, } impl GenericParamDefKind { @@ -371,6 +371,7 @@ impl<'tcx> Generics { pub struct GenericPredicates<'tcx> { pub parent: Option, pub predicates: &'tcx [(Clause<'tcx>, Span)], + pub effects_min_tys: &'tcx ty::List>, } impl<'tcx> GenericPredicates<'tcx> { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 9c2bfc12a18a1..7d57d88f40f4a 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1608,7 +1608,7 @@ impl<'tcx> TyCtxt<'tcx> { } } - /// If the def-id is an associated type that was desugared from a + /// If the `def_id` is an associated type that was desugared from a /// return-position `impl Trait` from a trait, then provide the source info /// about where that RPITIT came from. pub fn opt_rpitit_info(self, def_id: DefId) -> Option { @@ -1619,6 +1619,16 @@ impl<'tcx> TyCtxt<'tcx> { } } + /// Whether the `def_id` is an associated type that was desugared from a + /// `#[const_trait]` or `impl_const`. + pub fn is_effects_desugared_assoc_ty(self, def_id: DefId) -> bool { + if let DefKind::AssocTy = self.def_kind(def_id) { + self.associated_item(def_id).is_effects_desugaring + } else { + false + } + } + pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option { variant.fields.iter_enumerated().find_map(|(i, field)| { self.hygienic_eq(ident, field.ident(self), variant.def_id).then_some(i) diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs index dc3c84f9e439a..466c3b93f8e5d 100644 --- a/compiler/rustc_middle/src/ty/vtable.rs +++ b/compiler/rustc_middle/src/ty/vtable.rs @@ -3,8 +3,6 @@ use std::fmt; use crate::mir::interpret::{alloc_range, AllocId, Allocation, Pointer, Scalar}; use crate::ty::{self, Instance, PolyTraitRef, Ty, TyCtxt}; use rustc_ast::Mutability; -use rustc_data_structures::fx::FxHashSet; -use rustc_hir::def_id::DefId; use rustc_macros::HashStable; #[derive(Clone, Copy, PartialEq, HashStable)] @@ -42,45 +40,12 @@ impl<'tcx> fmt::Debug for VtblEntry<'tcx> { impl<'tcx> TyCtxt<'tcx> { pub const COMMON_VTABLE_ENTRIES: &'tcx [VtblEntry<'tcx>] = &[VtblEntry::MetadataDropInPlace, VtblEntry::MetadataSize, VtblEntry::MetadataAlign]; - - pub fn supertrait_def_ids(self, trait_def_id: DefId) -> SupertraitDefIds<'tcx> { - SupertraitDefIds { - tcx: self, - stack: vec![trait_def_id], - visited: Some(trait_def_id).into_iter().collect(), - } - } } pub const COMMON_VTABLE_ENTRIES_DROPINPLACE: usize = 0; pub const COMMON_VTABLE_ENTRIES_SIZE: usize = 1; pub const COMMON_VTABLE_ENTRIES_ALIGN: usize = 2; -pub struct SupertraitDefIds<'tcx> { - tcx: TyCtxt<'tcx>, - stack: Vec, - visited: FxHashSet, -} - -impl Iterator for SupertraitDefIds<'_> { - type Item = DefId; - - fn next(&mut self) -> Option { - let def_id = self.stack.pop()?; - let predicates = self.tcx.super_predicates_of(def_id); - let visited = &mut self.visited; - self.stack.extend( - predicates - .predicates - .iter() - .filter_map(|(pred, _)| pred.as_trait_clause()) - .map(|trait_ref| trait_ref.def_id()) - .filter(|&super_def_id| visited.insert(super_def_id)), - ); - Some(def_id) - } -} - // Note that we don't have access to a self type here, this has to be purely based on the trait (and // supertrait) definitions. That means we can't call into the same vtable_entries code since that // returns a specific instantiation (e.g., with Vacant slots when bounds aren't satisfied). The goal diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index c1d645aa42cb8..5ccbd7c59cfba 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -1,3 +1,4 @@ +use crate::build::matches::{DeclareLetBindings, EmitStorageLive, ScheduleDrops}; use crate::build::ForGuard::OutsideGuard; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; use rustc_middle::middle::region::Scope; @@ -189,38 +190,43 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let initializer_span = this.thir[*initializer].span; let scope = (*init_scope, source_info); - let failure = unpack!( - block = this.in_scope(scope, *lint_level, |this| { - this.declare_bindings( - visibility_scope, - remainder_span, - pattern, - None, - Some((Some(&destination), initializer_span)), - ); - this.visit_primary_bindings( - pattern, - UserTypeProjections::none(), - &mut |this, _, _, node, span, _, _| { - this.storage_live_binding( - block, - node, - span, - OutsideGuard, - true, - ); - }, - ); - this.ast_let_else( - block, - *initializer, - initializer_span, - *else_block, - &last_remainder_scope, - pattern, - ) - }) - ); + let failure_and_block = this.in_scope(scope, *lint_level, |this| { + this.declare_bindings( + visibility_scope, + remainder_span, + pattern, + None, + Some((Some(&destination), initializer_span)), + ); + this.visit_primary_bindings( + pattern, + UserTypeProjections::none(), + &mut |this, _, _, node, span, _, _| { + this.storage_live_binding( + block, + node, + span, + OutsideGuard, + ScheduleDrops::Yes, + ); + }, + ); + let else_block_span = this.thir[*else_block].span; + let (matching, failure) = + this.in_if_then_scope(last_remainder_scope, else_block_span, |this| { + this.lower_let_expr( + block, + *initializer, + pattern, + None, + initializer_span, + DeclareLetBindings::No, + EmitStorageLive::No, + ) + }); + matching.and(failure) + }); + let failure = unpack!(block = failure_and_block); this.cfg.goto(failure, source_info, failure_entry); if let Some(source_scope) = visibility_scope { @@ -292,7 +298,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pattern, UserTypeProjections::none(), &mut |this, _, _, node, span, _, _| { - this.storage_live_binding(block, node, span, OutsideGuard, true); + this.storage_live_binding( + block, + node, + span, + OutsideGuard, + ScheduleDrops::Yes, + ); this.schedule_drop_for_binding(node, span, OutsideGuard); }, ) diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 76bdc26a501a6..942c69b5c0a75 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -1,6 +1,7 @@ //! See docs in build/expr/mod.rs use crate::build::expr::category::{Category, RvalueFunc}; +use crate::build::matches::DeclareLetBindings; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder, NeedsTemporary}; use rustc_ast::InlineAsmOptions; use rustc_data_structures::fx::FxHashMap; @@ -86,7 +87,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { cond, Some(condition_scope), // Temp scope source_info, - true, // Declare `let` bindings normally + DeclareLetBindings::Yes, // Declare `let` bindings normally )); // Lower the `then` arm into its block. @@ -163,7 +164,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { source_info, // This flag controls how inner `let` expressions are lowered, // but either way there shouldn't be any of those in here. - true, + DeclareLetBindings::LetNotPermitted, ) }); let (short_circuit, continuation, constant) = match op { diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 932406fd1aaf2..efed52231e3fa 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -21,12 +21,14 @@ use rustc_span::symbol::Symbol; use rustc_span::{BytePos, Pos, Span}; use rustc_target::abi::VariantIdx; use tracing::{debug, instrument}; +use util::visit_bindings; // helper functions, broken out by category: mod simplify; mod test; mod util; +use std::assert_matches::assert_matches; use std::borrow::Borrow; use std::mem; @@ -38,9 +40,50 @@ struct ThenElseArgs { /// `self.local_scope()` is used. temp_scope_override: Option, variable_source_info: SourceInfo, + /// Determines how bindings should be handled when lowering `let` expressions. + /// /// Forwarded to [`Builder::lower_let_expr`] when lowering [`ExprKind::Let`]. - /// When false (for match guards), `let` bindings won't be declared. - declare_let_bindings: bool, + declare_let_bindings: DeclareLetBindings, +} + +/// Should lowering a `let` expression also declare its bindings? +/// +/// Used by [`Builder::lower_let_expr`] when lowering [`ExprKind::Let`]. +#[derive(Clone, Copy)] +pub(crate) enum DeclareLetBindings { + /// Yes, declare `let` bindings as normal for `if` conditions. + Yes, + /// No, don't declare `let` bindings, because the caller declares them + /// separately due to special requirements. + /// + /// Used for match guards and let-else. + No, + /// Let expressions are not permitted in this context, so it is a bug to + /// try to lower one (e.g inside lazy-boolean-or or boolean-not). + LetNotPermitted, +} + +/// Used by [`Builder::bind_matched_candidate_for_arm_body`] to determine +/// whether or not to call [`Builder::storage_live_binding`] to emit +/// [`StatementKind::StorageLive`]. +#[derive(Clone, Copy)] +pub(crate) enum EmitStorageLive { + /// Yes, emit `StorageLive` as normal. + Yes, + /// No, don't emit `StorageLive`. The caller has taken responsibility for + /// emitting `StorageLive` as appropriate. + No, +} + +/// Used by [`Builder::storage_live_binding`] and [`Builder::bind_matched_candidate_for_arm_body`] +/// to decide whether to schedule drops. +#[derive(Clone, Copy, Debug)] +pub(crate) enum ScheduleDrops { + /// Yes, the relevant functions should also schedule drops as appropriate. + Yes, + /// No, don't schedule drops. The caller has taken responsibility for any + /// appropriate drops. + No, } impl<'a, 'tcx> Builder<'a, 'tcx> { @@ -56,7 +99,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { expr_id: ExprId, temp_scope_override: Option, variable_source_info: SourceInfo, - declare_let_bindings: bool, + declare_let_bindings: DeclareLetBindings, ) -> BlockAnd<()> { self.then_else_break_inner( block, @@ -90,13 +133,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.then_else_break_inner( block, lhs, - ThenElseArgs { declare_let_bindings: true, ..args }, + ThenElseArgs { + declare_let_bindings: DeclareLetBindings::LetNotPermitted, + ..args + }, ) }); let rhs_success_block = unpack!(this.then_else_break_inner( failure_block, rhs, - ThenElseArgs { declare_let_bindings: true, ..args }, + ThenElseArgs { + declare_let_bindings: DeclareLetBindings::LetNotPermitted, + ..args + }, )); // Make the LHS and RHS success arms converge to a common block. @@ -126,7 +175,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.then_else_break_inner( block, arg, - ThenElseArgs { declare_let_bindings: true, ..args }, + ThenElseArgs { + declare_let_bindings: DeclareLetBindings::LetNotPermitted, + ..args + }, ) }); this.break_for_else(success_block, args.variable_source_info); @@ -146,6 +198,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Some(args.variable_source_info.scope), args.variable_source_info.span, args.declare_let_bindings, + EmitStorageLive::Yes, ), _ => { let mut block = block; @@ -314,13 +367,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let match_start_span = span.shrink_to_lo().to(scrutinee_span); - let fake_borrow_temps = self.lower_match_tree( + // The set of places that we are creating fake borrows of. If there are no match guards then + // we don't need any fake borrows, so don't track them. + let fake_borrow_temps: Vec<(Place<'tcx>, Local, FakeBorrowKind)> = if match_has_guard { + util::collect_fake_borrows(self, &candidates, scrutinee_span, scrutinee_place.base()) + } else { + Vec::new() + }; + + self.lower_match_tree( block, scrutinee_span, &scrutinee_place, match_start_span, - match_has_guard, &mut candidates, + false, ); self.lower_match_arms( @@ -375,89 +436,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { .collect() } - /// Create the decision tree for the match expression, starting from `block`. - /// - /// Modifies `candidates` to store the bindings and type ascriptions for - /// that candidate. - /// - /// Returns the places that need fake borrows because we bind or test them. - fn lower_match_tree<'pat>( - &mut self, - block: BasicBlock, - scrutinee_span: Span, - scrutinee_place_builder: &PlaceBuilder<'tcx>, - match_start_span: Span, - match_has_guard: bool, - candidates: &mut [&mut Candidate<'pat, 'tcx>], - ) -> Vec<(Place<'tcx>, Local, FakeBorrowKind)> { - // The set of places that we are creating fake borrows of. If there are no match guards then - // we don't need any fake borrows, so don't track them. - let fake_borrows: Vec<(Place<'tcx>, Local, FakeBorrowKind)> = if match_has_guard { - util::collect_fake_borrows( - self, - candidates, - scrutinee_span, - scrutinee_place_builder.base(), - ) - } else { - Vec::new() - }; - - // See the doc comment on `match_candidates` for why we have an - // otherwise block. Match checking will ensure this is actually - // unreachable. - let otherwise_block = self.cfg.start_new_block(); - - // This will generate code to test scrutinee_place and - // branch to the appropriate arm block - self.match_candidates(match_start_span, scrutinee_span, block, otherwise_block, candidates); - - let source_info = self.source_info(scrutinee_span); - - // Matching on a `scrutinee_place` with an uninhabited type doesn't - // generate any memory reads by itself, and so if the place "expression" - // contains unsafe operations like raw pointer dereferences or union - // field projections, we wouldn't know to require an `unsafe` block - // around a `match` equivalent to `std::intrinsics::unreachable()`. - // See issue #47412 for this hole being discovered in the wild. - // - // HACK(eddyb) Work around the above issue by adding a dummy inspection - // of `scrutinee_place`, specifically by applying `ReadForMatch`. - // - // NOTE: ReadForMatch also checks that the scrutinee is initialized. - // This is currently needed to not allow matching on an uninitialized, - // uninhabited value. If we get never patterns, those will check that - // the place is initialized, and so this read would only be used to - // check safety. - let cause_matched_place = FakeReadCause::ForMatchedPlace(None); - - if let Some(scrutinee_place) = scrutinee_place_builder.try_to_place(self) { - self.cfg.push_fake_read( - otherwise_block, - source_info, - cause_matched_place, - scrutinee_place, - ); - } - - self.cfg.terminate(otherwise_block, source_info, TerminatorKind::Unreachable); - - // Link each leaf candidate to the `pre_binding_block` of the next one. - let mut previous_candidate: Option<&mut Candidate<'_, '_>> = None; - - for candidate in candidates { - candidate.visit_leaves(|leaf_candidate| { - if let Some(ref mut prev) = previous_candidate { - assert!(leaf_candidate.false_edge_start_block.is_some()); - prev.next_candidate_start_block = leaf_candidate.false_edge_start_block; - } - previous_candidate = Some(leaf_candidate); - }); - } - - fake_borrows - } - /// Lower the bindings, guards and arm bodies of a `match` expression. /// /// The decision tree should have already been created @@ -513,7 +491,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &fake_borrow_temps, scrutinee_span, Some((arm, match_scope)), - false, + EmitStorageLive::Yes, ); this.fixed_temps_scope = old_dedup_scope; @@ -558,7 +536,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fake_borrow_temps: &[(Place<'tcx>, Local, FakeBorrowKind)], scrutinee_span: Span, arm_match_scope: Option<(&Arm<'tcx>, region::Scope)>, - storages_alive: bool, + emit_storage_live: EmitStorageLive, ) -> BasicBlock { if candidate.subcandidates.is_empty() { // Avoid generating another `BasicBlock` when we only have one @@ -569,8 +547,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fake_borrow_temps, scrutinee_span, arm_match_scope, - true, - storages_alive, + ScheduleDrops::Yes, + emit_storage_live, ) } else { // It's helpful to avoid scheduling drops multiple times to save @@ -588,7 +566,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // To handle this we instead unschedule it's drop after each time // we lower the guard. let target_block = self.cfg.start_new_block(); - let mut schedule_drops = true; + let mut schedule_drops = ScheduleDrops::Yes; let arm = arm_match_scope.unzip().0; // We keep a stack of all of the bindings and type ascriptions // from the parent candidates that we visit, that also need to @@ -607,10 +585,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { scrutinee_span, arm_match_scope, schedule_drops, - storages_alive, + emit_storage_live, ); if arm.is_none() { - schedule_drops = false; + schedule_drops = ScheduleDrops::No; } self.cfg.goto(binding_end, outer_source_info, target_block); }, @@ -636,8 +614,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { match irrefutable_pat.kind { // Optimize the case of `let x = ...` to write directly into `x` PatKind::Binding { mode: BindingMode(ByRef::No, _), var, subpattern: None, .. } => { - let place = - self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard, true); + let place = self.storage_live_binding( + block, + var, + irrefutable_pat.span, + OutsideGuard, + ScheduleDrops::Yes, + ); unpack!(block = self.expr_into_dest(place, block, initializer_id)); // Inject a fake read, see comments on `FakeReadCause::ForLet`. @@ -670,8 +653,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }, ascription: thir::Ascription { ref annotation, variance: _ }, } => { - let place = - self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard, true); + let place = self.storage_live_binding( + block, + var, + irrefutable_pat.span, + OutsideGuard, + ScheduleDrops::Yes, + ); unpack!(block = self.expr_into_dest(place, block, initializer_id)); // Inject a fake read, see comments on `FakeReadCause::ForLet`. @@ -728,62 +716,56 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { set_match_place: bool, ) -> BlockAnd<()> { let mut candidate = Candidate::new(initializer.clone(), irrefutable_pat, false, self); - let fake_borrow_temps = self.lower_match_tree( - block, - irrefutable_pat.span, - &initializer, - irrefutable_pat.span, - false, - &mut [&mut candidate], - ); // For matches and function arguments, the place that is being matched // can be set when creating the variables. But the place for // let PATTERN = ... might not even exist until we do the assignment. // so we set it here instead. if set_match_place { - let mut next = Some(&candidate); - while let Some(candidate_ref) = next.take() { - for binding in &candidate_ref.extra_data.bindings { + // `try_to_place` may fail if it is unable to resolve the given `PlaceBuilder` inside a + // closure. In this case, we don't want to include a scrutinee place. + // `scrutinee_place_builder` will fail for destructured assignments. This is because a + // closure only captures the precise places that it will read and as a result a closure + // may not capture the entire tuple/struct and rather have individual places that will + // be read in the final MIR. + // Example: + // ``` + // let foo = (0, 1); + // let c = || { + // let (v1, v2) = foo; + // }; + // ``` + if let Some(place) = initializer.try_to_place(self) { + visit_bindings(&[&mut candidate], |binding: &Binding<'_>| { let local = self.var_local_id(binding.var_id, OutsideGuard); - // `try_to_place` may fail if it is unable to resolve the given - // `PlaceBuilder` inside a closure. In this case, we don't want to include - // a scrutinee place. `scrutinee_place_builder` will fail for destructured - // assignments. This is because a closure only captures the precise places - // that it will read and as a result a closure may not capture the entire - // tuple/struct and rather have individual places that will be read in the - // final MIR. - // Example: - // ``` - // let foo = (0, 1); - // let c = || { - // let (v1, v2) = foo; - // }; - // ``` - if let Some(place) = initializer.try_to_place(self) { - let LocalInfo::User(BindingForm::Var(VarBindingForm { - opt_match_place: Some((ref mut match_place, _)), - .. - })) = **self.local_decls[local].local_info.as_mut().assert_crate_local() - else { - bug!("Let binding to non-user variable.") - }; + if let LocalInfo::User(BindingForm::Var(VarBindingForm { + opt_match_place: Some((ref mut match_place, _)), + .. + })) = **self.local_decls[local].local_info.as_mut().assert_crate_local() + { *match_place = Some(place); - } - } - // All of the subcandidates should bind the same locals, so we - // only visit the first one. - next = candidate_ref.subcandidates.get(0) + } else { + bug!("Let binding to non-user variable.") + }; + }); } } + self.lower_match_tree( + block, + irrefutable_pat.span, + &initializer, + irrefutable_pat.span, + &mut [&mut candidate], + false, + ); self.bind_pattern( self.source_info(irrefutable_pat.span), candidate, - fake_borrow_temps.as_slice(), + &[], irrefutable_pat.span, None, - false, + EmitStorageLive::Yes, ) .unit() } @@ -859,13 +841,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } + /// Emits a [`StatementKind::StorageLive`] for the given var, and also + /// schedules a drop if requested (and possible). pub(crate) fn storage_live_binding( &mut self, block: BasicBlock, var: LocalVarId, span: Span, for_guard: ForGuard, - schedule_drop: bool, + schedule_drop: ScheduleDrops, ) -> Place<'tcx> { let local_id = self.var_local_id(var, for_guard); let source_info = self.source_info(span); @@ -873,7 +857,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Although there is almost always scope for given variable in corner cases // like #92893 we might get variable with no scope. if let Some(region_scope) = self.region_scope_tree.var_scope(var.0.local_id) - && schedule_drop + && matches!(schedule_drop, ScheduleDrops::Yes) { self.schedule_drop(span, region_scope, local_id, DropKind::Storage); } @@ -1306,6 +1290,79 @@ pub(crate) struct ArmHasGuard(pub(crate) bool); // Main matching algorithm impl<'a, 'tcx> Builder<'a, 'tcx> { + /// The entrypoint of the matching algorithm. Create the decision tree for the match expression, + /// starting from `block`. + /// + /// Modifies `candidates` to store the bindings and type ascriptions for + /// that candidate. + /// + /// `refutable` indicates whether the candidate list is refutable (for `if let` and `let else`) + /// or not (for `let` and `match`). In the refutable case we return the block to which we branch + /// on failure. + fn lower_match_tree<'pat>( + &mut self, + block: BasicBlock, + scrutinee_span: Span, + scrutinee_place_builder: &PlaceBuilder<'tcx>, + match_start_span: Span, + candidates: &mut [&mut Candidate<'pat, 'tcx>], + refutable: bool, + ) -> BasicBlock { + // See the doc comment on `match_candidates` for why we have an otherwise block. + let otherwise_block = self.cfg.start_new_block(); + + // This will generate code to test scrutinee_place and branch to the appropriate arm block + self.match_candidates(match_start_span, scrutinee_span, block, otherwise_block, candidates); + + // Link each leaf candidate to the `false_edge_start_block` of the next one. + let mut previous_candidate: Option<&mut Candidate<'_, '_>> = None; + for candidate in candidates { + candidate.visit_leaves(|leaf_candidate| { + if let Some(ref mut prev) = previous_candidate { + assert!(leaf_candidate.false_edge_start_block.is_some()); + prev.next_candidate_start_block = leaf_candidate.false_edge_start_block; + } + previous_candidate = Some(leaf_candidate); + }); + } + + if refutable { + // In refutable cases there's always at least one candidate, and we want a false edge to + // the failure block. + previous_candidate.as_mut().unwrap().next_candidate_start_block = Some(otherwise_block) + } else { + // Match checking ensures `otherwise_block` is actually unreachable in irrefutable + // cases. + let source_info = self.source_info(scrutinee_span); + + // Matching on a scrutinee place of an uninhabited type doesn't generate any memory + // reads by itself, and so if the place is uninitialized we wouldn't know. In order to + // disallow the following: + // ```rust + // let x: !; + // match x {} + // ``` + // we add a dummy read on the place. + // + // NOTE: If we require never patterns for empty matches, those will check that the place + // is initialized, and so this read would no longer be needed. + let cause_matched_place = FakeReadCause::ForMatchedPlace(None); + + if let Some(scrutinee_place) = scrutinee_place_builder.try_to_place(self) { + self.cfg.push_fake_read( + otherwise_block, + source_info, + cause_matched_place, + scrutinee_place, + ); + } + + self.cfg.terminate(otherwise_block, source_info, TerminatorKind::Unreachable); + } + + otherwise_block + } + /// The main match algorithm. It begins with a set of candidates /// `candidates` and has the job of generating code to determine /// which of these candidates, if any, is the correct one. The @@ -1997,53 +2054,69 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Pat binding - used for `let` and function parameters as well. impl<'a, 'tcx> Builder<'a, 'tcx> { - /// If the bindings have already been declared, set `declare_bindings` to - /// `false` to avoid duplicated bindings declaration. Used for if-let guards. + /// Lowers a `let` expression that appears in a suitable context + /// (e.g. an `if` condition or match guard). + /// + /// Also used for lowering let-else statements, since they have similar + /// needs despite not actually using `let` expressions. + /// + /// Use [`DeclareLetBindings`] to control whether the `let` bindings are + /// declared or not. pub(crate) fn lower_let_expr( &mut self, mut block: BasicBlock, expr_id: ExprId, pat: &Pat<'tcx>, source_scope: Option, - span: Span, - declare_bindings: bool, + scope_span: Span, + declare_let_bindings: DeclareLetBindings, + emit_storage_live: EmitStorageLive, ) -> BlockAnd<()> { let expr_span = self.thir[expr_id].span; - let expr_place_builder = unpack!(block = self.lower_scrutinee(block, expr_id, expr_span)); - let wildcard = Pat::wildcard_from_ty(pat.ty); - let mut guard_candidate = Candidate::new(expr_place_builder.clone(), pat, false, self); - let mut otherwise_candidate = - Candidate::new(expr_place_builder.clone(), &wildcard, false, self); - let fake_borrow_temps = self.lower_match_tree( + let scrutinee = unpack!(block = self.lower_scrutinee(block, expr_id, expr_span)); + let mut candidate = Candidate::new(scrutinee.clone(), pat, false, self); + let otherwise_block = self.lower_match_tree( block, + expr_span, + &scrutinee, pat.span, - &expr_place_builder, - pat.span, - false, - &mut [&mut guard_candidate, &mut otherwise_candidate], + &mut [&mut candidate], + true, ); - let expr_place = expr_place_builder.try_to_place(self); - let opt_expr_place = expr_place.as_ref().map(|place| (Some(place), expr_span)); - let otherwise_post_guard_block = otherwise_candidate.pre_binding_block.unwrap(); - self.break_for_else(otherwise_post_guard_block, self.source_info(expr_span)); - if declare_bindings { - self.declare_bindings(source_scope, pat.span.to(span), pat, None, opt_expr_place); + self.break_for_else(otherwise_block, self.source_info(expr_span)); + + match declare_let_bindings { + DeclareLetBindings::Yes => { + let expr_place = scrutinee.try_to_place(self); + let opt_expr_place = expr_place.as_ref().map(|place| (Some(place), expr_span)); + self.declare_bindings( + source_scope, + pat.span.to(scope_span), + pat, + None, + opt_expr_place, + ); + } + DeclareLetBindings::No => {} // Caller is responsible for bindings. + DeclareLetBindings::LetNotPermitted => { + self.tcx.dcx().span_bug(expr_span, "let expression not expected in this context") + } } - let post_guard_block = self.bind_pattern( + let success = self.bind_pattern( self.source_info(pat.span), - guard_candidate, - fake_borrow_temps.as_slice(), + candidate, + &[], expr_span, None, - false, + emit_storage_live, ); // If branch coverage is enabled, record this branch. - self.visit_coverage_conditional_let(pat, post_guard_block, otherwise_post_guard_block); + self.visit_coverage_conditional_let(pat, success, otherwise_block); - post_guard_block.unit() + success.unit() } /// Initializes each of the bindings from the candidate by @@ -2061,8 +2134,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fake_borrows: &[(Place<'tcx>, Local, FakeBorrowKind)], scrutinee_span: Span, arm_match_scope: Option<(&Arm<'tcx>, region::Scope)>, - schedule_drops: bool, - storages_alive: bool, + schedule_drops: ScheduleDrops, + emit_storage_live: EmitStorageLive, ) -> BasicBlock { debug!("bind_and_guard_matched_candidate(candidate={:?})", candidate); @@ -2091,14 +2164,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { return self.cfg.start_new_block(); } - self.ascribe_types( - block, - parent_data - .iter() - .flat_map(|d| &d.ascriptions) - .cloned() - .chain(candidate.extra_data.ascriptions), - ); + let ascriptions = parent_data + .iter() + .flat_map(|d| &d.ascriptions) + .cloned() + .chain(candidate.extra_data.ascriptions); + let bindings = + parent_data.iter().flat_map(|d| &d.bindings).chain(&candidate.extra_data.bindings); + + self.ascribe_types(block, ascriptions); // rust-lang/rust#27282: The `autoref` business deserves some // explanation here. @@ -2185,12 +2259,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { && let Some(guard) = arm.guard { let tcx = self.tcx; - let bindings = - parent_data.iter().flat_map(|d| &d.bindings).chain(&candidate.extra_data.bindings); self.bind_matched_candidate_for_guard(block, schedule_drops, bindings.clone()); - let guard_frame = - GuardFrame { locals: bindings.map(|b| GuardFrameLocal::new(b.var_id)).collect() }; + let guard_frame = GuardFrame { + locals: bindings.clone().map(|b| GuardFrameLocal::new(b.var_id)).collect(), + }; debug!("entering guard building context: {:?}", guard_frame); self.guard_context.push(guard_frame); @@ -2211,7 +2284,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { guard, None, // Use `self.local_scope()` as the temp scope this.source_info(arm.span), - false, // For guards, `let` bindings are declared separately + DeclareLetBindings::No, // For guards, `let` bindings are declared separately ) }); @@ -2263,11 +2336,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // ``` // // and that is clearly not correct. - let by_value_bindings = parent_data - .iter() - .flat_map(|d| &d.bindings) - .chain(&candidate.extra_data.bindings) - .filter(|binding| matches!(binding.binding_mode.0, ByRef::No)); + let by_value_bindings = + bindings.filter(|binding| matches!(binding.binding_mode.0, ByRef::No)); // Read all of the by reference bindings to ensure that the // place they refer to can't be modified by the guard. for binding in by_value_bindings.clone() { @@ -2275,12 +2345,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let cause = FakeReadCause::ForGuardBinding; self.cfg.push_fake_read(post_guard_block, guard_end, cause, Place::from(local_id)); } - assert!(schedule_drops, "patterns with guards must schedule drops"); + assert_matches!( + schedule_drops, + ScheduleDrops::Yes, + "patterns with guards must schedule drops" + ); self.bind_matched_candidate_for_arm_body( post_guard_block, - true, + ScheduleDrops::Yes, by_value_bindings, - storages_alive, + emit_storage_live, ); post_guard_block @@ -2291,8 +2365,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.bind_matched_candidate_for_arm_body( block, schedule_drops, - parent_data.iter().flat_map(|d| &d.bindings).chain(&candidate.extra_data.bindings), - storages_alive, + bindings, + emit_storage_live, ); block } @@ -2328,7 +2402,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn bind_matched_candidate_for_guard<'b>( &mut self, block: BasicBlock, - schedule_drops: bool, + schedule_drops: ScheduleDrops, bindings: impl IntoIterator>, ) where 'tcx: 'b, @@ -2381,9 +2455,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn bind_matched_candidate_for_arm_body<'b>( &mut self, block: BasicBlock, - schedule_drops: bool, + schedule_drops: ScheduleDrops, bindings: impl IntoIterator>, - storages_alive: bool, + emit_storage_live: EmitStorageLive, ) where 'tcx: 'b, { @@ -2393,21 +2467,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Assign each of the bindings. This may trigger moves out of the candidate. for binding in bindings { let source_info = self.source_info(binding.span); - let local = if storages_alive { + let local = match emit_storage_live { // Here storages are already alive, probably because this is a binding // from let-else. // We just need to schedule drop for the value. - self.var_local_id(binding.var_id, OutsideGuard).into() - } else { - self.storage_live_binding( + EmitStorageLive::No => self.var_local_id(binding.var_id, OutsideGuard).into(), + EmitStorageLive::Yes => self.storage_live_binding( block, binding.var_id, binding.span, OutsideGuard, schedule_drops, - ) + ), }; - if schedule_drops { + if matches!(schedule_drops, ScheduleDrops::Yes) { self.schedule_drop_for_binding(binding.var_id, binding.span, OutsideGuard); } let rvalue = match binding.binding_mode.0 { @@ -2493,55 +2566,4 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { debug!(?locals); self.var_indices.insert(var_id, locals); } - - pub(crate) fn ast_let_else( - &mut self, - mut block: BasicBlock, - init_id: ExprId, - initializer_span: Span, - else_block: BlockId, - let_else_scope: ®ion::Scope, - pattern: &Pat<'tcx>, - ) -> BlockAnd { - let else_block_span = self.thir[else_block].span; - let (matching, failure) = self.in_if_then_scope(*let_else_scope, else_block_span, |this| { - let scrutinee = unpack!(block = this.lower_scrutinee(block, init_id, initializer_span)); - let pat = Pat { ty: pattern.ty, span: else_block_span, kind: PatKind::Wild }; - let mut wildcard = Candidate::new(scrutinee.clone(), &pat, false, this); - let mut candidate = Candidate::new(scrutinee.clone(), pattern, false, this); - let fake_borrow_temps = this.lower_match_tree( - block, - initializer_span, - &scrutinee, - pattern.span, - false, - &mut [&mut candidate, &mut wildcard], - ); - // This block is for the matching case - let matching = this.bind_pattern( - this.source_info(pattern.span), - candidate, - fake_borrow_temps.as_slice(), - initializer_span, - None, - true, - ); - // This block is for the failure case - let failure = this.bind_pattern( - this.source_info(else_block_span), - wildcard, - fake_borrow_temps.as_slice(), - initializer_span, - None, - true, - ); - - // If branch coverage is enabled, record this branch. - this.visit_coverage_conditional_let(pattern, matching, failure); - - this.break_for_else(failure, this.source_info(initializer_span)); - matching.unit() - }); - matching.and(failure) - } } diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs index 630d0b9438dca..3bec154e1df5d 100644 --- a/compiler/rustc_mir_build/src/build/matches/util.rs +++ b/compiler/rustc_mir_build/src/build/matches/util.rs @@ -1,3 +1,5 @@ +use std::marker::PhantomData; + use crate::build::expr::as_place::{PlaceBase, PlaceBuilder}; use crate::build::matches::{Binding, Candidate, FlatPat, MatchPair, TestCase}; use crate::build::Builder; @@ -269,18 +271,6 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> { } } -pub(super) struct FakeBorrowCollector<'a, 'b, 'tcx> { - cx: &'a mut Builder<'b, 'tcx>, - /// Base of the scrutinee place. Used to distinguish bindings inside the scrutinee place from - /// bindings inside deref patterns. - scrutinee_base: PlaceBase, - /// Store for each place the kind of borrow to take. In case of conflicts, we take the strongest - /// borrow (i.e. Deep > Shallow). - /// Invariant: for any place in `fake_borrows`, all the prefixes of this place that are - /// dereferences are also borrowed with the same of stronger borrow kind. - fake_borrows: FxIndexMap, FakeBorrowKind>, -} - /// Determine the set of places that have to be stable across match guards. /// /// Returns a list of places that need a fake borrow along with a local to store it. @@ -344,6 +334,18 @@ pub(super) fn collect_fake_borrows<'tcx>( .collect() } +pub(super) struct FakeBorrowCollector<'a, 'b, 'tcx> { + cx: &'a mut Builder<'b, 'tcx>, + /// Base of the scrutinee place. Used to distinguish bindings inside the scrutinee place from + /// bindings inside deref patterns. + scrutinee_base: PlaceBase, + /// Store for each place the kind of borrow to take. In case of conflicts, we take the strongest + /// borrow (i.e. Deep > Shallow). + /// Invariant: for any place in `fake_borrows`, all the prefixes of this place that are + /// dereferences are also borrowed with the same of stronger borrow kind. + fake_borrows: FxIndexMap, FakeBorrowKind>, +} + impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> { // Fake borrow this place and its dereference prefixes. fn fake_borrow(&mut self, place: Place<'tcx>, kind: FakeBorrowKind) { @@ -457,6 +459,57 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> { } } +/// Visit all the bindings of these candidates. Because or-alternatives bind the same variables, we +/// only explore the first one of each or-pattern. +pub(super) fn visit_bindings<'tcx>( + candidates: &[&mut Candidate<'_, 'tcx>], + f: impl FnMut(&Binding<'tcx>), +) { + let mut visitor = BindingsVisitor { f, phantom: PhantomData }; + for candidate in candidates.iter() { + visitor.visit_candidate(candidate); + } +} + +pub(super) struct BindingsVisitor<'tcx, F> { + f: F, + phantom: PhantomData<&'tcx ()>, +} + +impl<'tcx, F> BindingsVisitor<'tcx, F> +where + F: FnMut(&Binding<'tcx>), +{ + fn visit_candidate(&mut self, candidate: &Candidate<'_, 'tcx>) { + for binding in &candidate.extra_data.bindings { + (self.f)(binding) + } + for match_pair in &candidate.match_pairs { + self.visit_match_pair(match_pair); + } + } + + fn visit_flat_pat(&mut self, flat_pat: &FlatPat<'_, 'tcx>) { + for binding in &flat_pat.extra_data.bindings { + (self.f)(binding) + } + for match_pair in &flat_pat.match_pairs { + self.visit_match_pair(match_pair); + } + } + + fn visit_match_pair(&mut self, match_pair: &MatchPair<'_, 'tcx>) { + if let TestCase::Or { pats, .. } = &match_pair.test_case { + // All the or-alternatives should bind the same locals, so we only visit the first one. + self.visit_flat_pat(&pats[0]) + } else { + for subpair in &match_pair.subpairs { + self.visit_match_pair(subpair); + } + } + } +} + #[must_use] pub(crate) fn ref_pat_borrow_kind(ref_mutability: Mutability) -> BorrowKind { match ref_mutability { diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs index f0b79dab0c974..ffcf630b653cd 100644 --- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs +++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs @@ -50,15 +50,19 @@ use crate::{lattice, AnalysisDomain, GenKill, GenKillAnalysis, MaybeReachable}; /// Similarly, at a given `drop` statement, the set-intersection /// between this data and `MaybeUninitializedPlaces` yields the set of /// places that would require a dynamic drop-flag at that statement. -pub struct MaybeInitializedPlaces<'a, 'tcx> { +pub struct MaybeInitializedPlaces<'a, 'mir, 'tcx> { tcx: TyCtxt<'tcx>, - body: &'a Body<'tcx>, + body: &'mir Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>, skip_unreachable_unwind: bool, } -impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self { +impl<'a, 'mir, 'tcx> MaybeInitializedPlaces<'a, 'mir, 'tcx> { + pub fn new( + tcx: TyCtxt<'tcx>, + body: &'mir Body<'tcx>, + mdpe: &'a MoveDataParamEnv<'tcx>, + ) -> Self { MaybeInitializedPlaces { tcx, body, mdpe, skip_unreachable_unwind: false } } @@ -84,7 +88,7 @@ impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> { } } -impl<'a, 'tcx> HasMoveData<'tcx> for MaybeInitializedPlaces<'a, 'tcx> { +impl<'a, 'mir, 'tcx> HasMoveData<'tcx> for MaybeInitializedPlaces<'a, 'mir, 'tcx> { fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data } @@ -125,17 +129,21 @@ impl<'a, 'tcx> HasMoveData<'tcx> for MaybeInitializedPlaces<'a, 'tcx> { /// Similarly, at a given `drop` statement, the set-intersection /// between this data and `MaybeInitializedPlaces` yields the set of /// places that would require a dynamic drop-flag at that statement. -pub struct MaybeUninitializedPlaces<'a, 'tcx> { +pub struct MaybeUninitializedPlaces<'a, 'mir, 'tcx> { tcx: TyCtxt<'tcx>, - body: &'a Body<'tcx>, + body: &'mir Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>, mark_inactive_variants_as_uninit: bool, skip_unreachable_unwind: BitSet, } -impl<'a, 'tcx> MaybeUninitializedPlaces<'a, 'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self { +impl<'a, 'mir, 'tcx> MaybeUninitializedPlaces<'a, 'mir, 'tcx> { + pub fn new( + tcx: TyCtxt<'tcx>, + body: &'mir Body<'tcx>, + mdpe: &'a MoveDataParamEnv<'tcx>, + ) -> Self { MaybeUninitializedPlaces { tcx, body, @@ -164,7 +172,7 @@ impl<'a, 'tcx> MaybeUninitializedPlaces<'a, 'tcx> { } } -impl<'a, 'tcx> HasMoveData<'tcx> for MaybeUninitializedPlaces<'a, 'tcx> { +impl<'a, 'tcx> HasMoveData<'tcx> for MaybeUninitializedPlaces<'a, '_, 'tcx> { fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data } @@ -250,24 +258,24 @@ impl<'a, 'tcx> HasMoveData<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> { /// c = S; // {a, b, c, d } /// } /// ``` -pub struct EverInitializedPlaces<'a, 'tcx> { - body: &'a Body<'tcx>, +pub struct EverInitializedPlaces<'a, 'mir, 'tcx> { + body: &'mir Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>, } -impl<'a, 'tcx> EverInitializedPlaces<'a, 'tcx> { - pub fn new(body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self { +impl<'a, 'mir, 'tcx> EverInitializedPlaces<'a, 'mir, 'tcx> { + pub fn new(body: &'mir Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self { EverInitializedPlaces { body, mdpe } } } -impl<'a, 'tcx> HasMoveData<'tcx> for EverInitializedPlaces<'a, 'tcx> { +impl<'a, 'tcx> HasMoveData<'tcx> for EverInitializedPlaces<'a, '_, 'tcx> { fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data } } -impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> { +impl<'a, 'mir, 'tcx> MaybeInitializedPlaces<'a, 'mir, 'tcx> { fn update_bits( trans: &mut impl GenKill, path: MovePathIndex, @@ -280,7 +288,7 @@ impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> { } } -impl<'a, 'tcx> MaybeUninitializedPlaces<'a, 'tcx> { +impl<'a, 'tcx> MaybeUninitializedPlaces<'a, '_, 'tcx> { fn update_bits( trans: &mut impl GenKill, path: MovePathIndex, @@ -306,7 +314,7 @@ impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> { } } -impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { +impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, '_, 'tcx> { /// There can be many more `MovePathIndex` than there are locals in a MIR body. /// We use a chunked bitset to avoid paying too high a memory footprint. type Domain = MaybeReachable>; @@ -328,7 +336,7 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { } } -impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { +impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, '_, 'tcx> { type Idx = MovePathIndex; fn domain_size(&self, _: &Body<'tcx>) -> usize { @@ -441,7 +449,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { } } -impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { +impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, '_, 'tcx> { /// There can be many more `MovePathIndex` than there are locals in a MIR body. /// We use a chunked bitset to avoid paying too high a memory footprint. type Domain = ChunkedBitSet; @@ -465,7 +473,7 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { } } -impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { +impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, '_, 'tcx> { type Idx = MovePathIndex; fn domain_size(&self, _: &Body<'tcx>) -> usize { @@ -642,7 +650,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> { } } -impl<'tcx> AnalysisDomain<'tcx> for EverInitializedPlaces<'_, 'tcx> { +impl<'tcx> AnalysisDomain<'tcx> for EverInitializedPlaces<'_, '_, 'tcx> { /// There can be many more `InitIndex` than there are locals in a MIR body. /// We use a chunked bitset to avoid paying too high a memory footprint. type Domain = ChunkedBitSet; @@ -661,7 +669,7 @@ impl<'tcx> AnalysisDomain<'tcx> for EverInitializedPlaces<'_, 'tcx> { } } -impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, 'tcx> { +impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, '_, 'tcx> { type Idx = InitIndex; fn domain_size(&self, _: &Body<'tcx>) -> usize { diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 5e2d88f94ca28..bfbfff7e25944 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -846,9 +846,10 @@ impl Map { if let ty::Ref(_, ref_ty, _) | ty::RawPtr(ref_ty, _) = ty.kind() && let ty::Slice(..) = ref_ty.kind() + // The user may have written a predicate like `[T]: Sized` in their where clauses, + // which makes slices scalars. + && self.places[place].value_index.is_none() { - assert!(self.places[place].value_index.is_none(), "slices are not scalars"); - // Prepend new child to the linked list. let len = self.places.push(PlaceInfo::new(Some(TrackElem::DerefLen))); self.places[len].next_sibling = self.places[place].first_child; diff --git a/compiler/rustc_mir_transform/src/cost_checker.rs b/compiler/rustc_mir_transform/src/cost_checker.rs index 7e401b5482f3d..3333bebff3a6e 100644 --- a/compiler/rustc_mir_transform/src/cost_checker.rs +++ b/compiler/rustc_mir_transform/src/cost_checker.rs @@ -31,6 +31,37 @@ impl<'b, 'tcx> CostChecker<'b, 'tcx> { CostChecker { tcx, param_env, callee_body, instance, penalty: 0, bonus: 0 } } + /// Add function-level costs not well-represented by the block-level costs. + /// + /// Needed because the `CostChecker` is used sometimes for just blocks, + /// and even the full `Inline` doesn't call `visit_body`, so there's nowhere + /// to put this logic in the visitor. + pub fn add_function_level_costs(&mut self) { + fn is_call_like(bbd: &BasicBlockData<'_>) -> bool { + use TerminatorKind::*; + match bbd.terminator().kind { + Call { .. } | Drop { .. } | Assert { .. } | InlineAsm { .. } => true, + + Goto { .. } + | SwitchInt { .. } + | UnwindResume + | UnwindTerminate(_) + | Return + | Unreachable => false, + + Yield { .. } | CoroutineDrop | FalseEdge { .. } | FalseUnwind { .. } => { + unreachable!() + } + } + } + + // If the only has one Call (or similar), inlining isn't increasing the total + // number of calls, so give extra encouragement to inlining that. + if self.callee_body.basic_blocks.iter().filter(|bbd| is_call_like(bbd)).count() == 1 { + self.bonus += CALL_PENALTY; + } + } + pub fn cost(&self) -> usize { usize::saturating_sub(self.penalty, self.bonus) } diff --git a/compiler/rustc_mir_transform/src/coverage/mappings.rs b/compiler/rustc_mir_transform/src/coverage/mappings.rs index 759bb7c1f9d96..235992ac5470d 100644 --- a/compiler/rustc_mir_transform/src/coverage/mappings.rs +++ b/compiler/rustc_mir_transform/src/coverage/mappings.rs @@ -9,9 +9,8 @@ use rustc_middle::ty::TyCtxt; use rustc_span::Span; use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph, START_BCB}; -use crate::coverage::spans::{ - extract_refined_covspans, unexpand_into_body_span_with_visible_macro, -}; +use crate::coverage::spans::extract_refined_covspans; +use crate::coverage::unexpand::unexpand_into_body_span; use crate::coverage::ExtractedHirInfo; /// Associates an ordinary executable code span with its corresponding BCB. @@ -202,8 +201,7 @@ pub(super) fn extract_branch_pairs( if !raw_span.ctxt().outer_expn_data().is_root() { return None; } - let (span, _) = - unexpand_into_body_span_with_visible_macro(raw_span, hir_info.body_span)?; + let span = unexpand_into_body_span(raw_span, hir_info.body_span)?; let bcb_from_marker = |marker: BlockMarkerId| basic_coverage_blocks.bcb_from_bb(block_markers[marker]?); @@ -238,7 +236,7 @@ pub(super) fn extract_mcdc_mappings( if !raw_span.ctxt().outer_expn_data().is_root() { return None; } - let (span, _) = unexpand_into_body_span_with_visible_macro(raw_span, body_span)?; + let span = unexpand_into_body_span(raw_span, body_span)?; let true_bcb = bcb_from_marker(true_marker)?; let false_bcb = bcb_from_marker(false_marker)?; @@ -261,7 +259,7 @@ pub(super) fn extract_mcdc_mappings( mcdc_decisions.extend(branch_info.mcdc_decision_spans.iter().filter_map( |decision: &mir::coverage::MCDCDecisionSpan| { - let (span, _) = unexpand_into_body_span_with_visible_macro(decision.span, body_span)?; + let span = unexpand_into_body_span(decision.span, body_span)?; let end_bcbs = decision .end_markers diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 4a64d21f3d17b..d55bde311c17e 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -6,6 +6,7 @@ mod mappings; mod spans; #[cfg(test)] mod tests; +mod unexpand; use rustc_middle::mir::coverage::{ CodeRegion, CoverageKind, DecisionInfo, FunctionCoverageInfo, Mapping, MappingKind, diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index 84a70d1f02d75..7612c01c52ec4 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -14,11 +14,6 @@ use crate::coverage::ExtractedHirInfo; mod from_mir; -// FIXME(#124545) It's awkward that we have to re-export this, because it's an -// internal detail of `from_mir` that is also needed when handling branch and -// MC/DC spans. Ideally we would find a more natural home for it. -pub(super) use from_mir::unexpand_into_body_span_with_visible_macro; - pub(super) fn extract_refined_covspans( mir_body: &mir::Body<'_>, hir_info: &ExtractedHirInfo, diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs index 09deb7534bfde..2ca166929eec8 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs @@ -4,12 +4,13 @@ use rustc_middle::mir::{ self, AggregateKind, FakeReadCause, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, }; -use rustc_span::{ExpnKind, MacroKind, Span, Symbol}; +use rustc_span::{Span, Symbol}; use crate::coverage::graph::{ BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph, START_BCB, }; use crate::coverage::spans::Covspan; +use crate::coverage::unexpand::unexpand_into_body_span_with_visible_macro; use crate::coverage::ExtractedHirInfo; pub(crate) struct ExtractedCovspans { @@ -215,59 +216,6 @@ fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option { } } -/// Returns an extrapolated span (pre-expansion[^1]) corresponding to a range -/// within the function's body source. This span is guaranteed to be contained -/// within, or equal to, the `body_span`. If the extrapolated span is not -/// contained within the `body_span`, `None` is returned. -/// -/// [^1]Expansions result from Rust syntax including macros, syntactic sugar, -/// etc.). -pub(crate) fn unexpand_into_body_span_with_visible_macro( - original_span: Span, - body_span: Span, -) -> Option<(Span, Option)> { - let (span, prev) = unexpand_into_body_span_with_prev(original_span, body_span)?; - - let visible_macro = prev - .map(|prev| match prev.ctxt().outer_expn_data().kind { - ExpnKind::Macro(MacroKind::Bang, name) => Some(name), - _ => None, - }) - .flatten(); - - Some((span, visible_macro)) -} - -/// Walks through the expansion ancestors of `original_span` to find a span that -/// is contained in `body_span` and has the same [`SyntaxContext`] as `body_span`. -/// The ancestor that was traversed just before the matching span (if any) is -/// also returned. -/// -/// For example, a return value of `Some((ancestor, Some(prev))` means that: -/// - `ancestor == original_span.find_ancestor_inside_same_ctxt(body_span)` -/// - `ancestor == prev.parent_callsite()` -/// -/// [`SyntaxContext`]: rustc_span::SyntaxContext -fn unexpand_into_body_span_with_prev( - original_span: Span, - body_span: Span, -) -> Option<(Span, Option)> { - let mut prev = None; - let mut curr = original_span; - - while !body_span.contains(curr) || !curr.eq_ctxt(body_span) { - prev = Some(curr); - curr = curr.parent_callsite()?; - } - - debug_assert_eq!(Some(curr), original_span.find_ancestor_in_same_ctxt(body_span)); - if let Some(prev) = prev { - debug_assert_eq!(Some(curr), prev.parent_callsite()); - } - - Some((curr, prev)) -} - #[derive(Debug)] pub(crate) struct Hole { pub(crate) span: Span, diff --git a/compiler/rustc_mir_transform/src/coverage/unexpand.rs b/compiler/rustc_mir_transform/src/coverage/unexpand.rs new file mode 100644 index 0000000000000..8cde291b9073e --- /dev/null +++ b/compiler/rustc_mir_transform/src/coverage/unexpand.rs @@ -0,0 +1,60 @@ +use rustc_span::{ExpnKind, MacroKind, Span, Symbol}; + +/// Walks through the expansion ancestors of `original_span` to find a span that +/// is contained in `body_span` and has the same [syntax context] as `body_span`. +pub(crate) fn unexpand_into_body_span(original_span: Span, body_span: Span) -> Option { + // Because we don't need to return any extra ancestor information, + // we can just delegate directly to `find_ancestor_inside_same_ctxt`. + original_span.find_ancestor_inside_same_ctxt(body_span) +} + +/// Walks through the expansion ancestors of `original_span` to find a span that +/// is contained in `body_span` and has the same [syntax context] as `body_span`. +/// +/// If the returned span represents a bang-macro invocation (e.g. `foo!(..)`), +/// the returned symbol will be the name of that macro (e.g. `foo`). +pub(crate) fn unexpand_into_body_span_with_visible_macro( + original_span: Span, + body_span: Span, +) -> Option<(Span, Option)> { + let (span, prev) = unexpand_into_body_span_with_prev(original_span, body_span)?; + + let visible_macro = prev + .map(|prev| match prev.ctxt().outer_expn_data().kind { + ExpnKind::Macro(MacroKind::Bang, name) => Some(name), + _ => None, + }) + .flatten(); + + Some((span, visible_macro)) +} + +/// Walks through the expansion ancestors of `original_span` to find a span that +/// is contained in `body_span` and has the same [syntax context] as `body_span`. +/// The ancestor that was traversed just before the matching span (if any) is +/// also returned. +/// +/// For example, a return value of `Some((ancestor, Some(prev)))` means that: +/// - `ancestor == original_span.find_ancestor_inside_same_ctxt(body_span)` +/// - `prev.parent_callsite() == ancestor` +/// +/// [syntax context]: rustc_span::SyntaxContext +fn unexpand_into_body_span_with_prev( + original_span: Span, + body_span: Span, +) -> Option<(Span, Option)> { + let mut prev = None; + let mut curr = original_span; + + while !body_span.contains(curr) || !curr.eq_ctxt(body_span) { + prev = Some(curr); + curr = curr.parent_callsite()?; + } + + debug_assert_eq!(Some(curr), original_span.find_ancestor_inside_same_ctxt(body_span)); + if let Some(prev) = prev { + debug_assert_eq!(Some(curr), prev.parent_callsite()); + } + + Some((curr, prev)) +} diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 0fd85eb345d0c..8b965f4d18e45 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -181,11 +181,6 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> { state.insert_value_idx(value_target, val, self.map()); } if let Some(overflow_target) = overflow_target { - let overflow = match overflow { - FlatSet::Top => FlatSet::Top, - FlatSet::Elem(overflow) => FlatSet::Elem(overflow), - FlatSet::Bottom => FlatSet::Bottom, - }; // We have flooded `target` earlier. state.insert_value_idx(overflow_target, overflow, self.map()); } diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index 665b2260294a3..fbbb8c5e47245 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -97,7 +97,7 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops { #[instrument(level = "trace", skip(body, flow_inits), ret)] fn compute_dead_unwinds<'mir, 'tcx>( body: &'mir Body<'tcx>, - flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>, + flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'_, 'mir, 'tcx>>, ) -> BitSet { // We only need to do this pass once, because unwind edges can only // reach cleanup blocks, which can't have unwind edges themselves. @@ -118,12 +118,12 @@ fn compute_dead_unwinds<'mir, 'tcx>( dead_unwinds } -struct InitializationData<'mir, 'tcx> { - inits: ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>, - uninits: ResultsCursor<'mir, 'tcx, MaybeUninitializedPlaces<'mir, 'tcx>>, +struct InitializationData<'a, 'mir, 'tcx> { + inits: ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'a, 'mir, 'tcx>>, + uninits: ResultsCursor<'mir, 'tcx, MaybeUninitializedPlaces<'a, 'mir, 'tcx>>, } -impl InitializationData<'_, '_> { +impl InitializationData<'_, '_, '_> { fn seek_before(&mut self, loc: Location) { self.inits.seek_before_primary_effect(loc); self.uninits.seek_before_primary_effect(loc); @@ -134,17 +134,17 @@ impl InitializationData<'_, '_> { } } -struct Elaborator<'a, 'b, 'tcx> { - ctxt: &'a mut ElaborateDropsCtxt<'b, 'tcx>, +struct Elaborator<'a, 'b, 'mir, 'tcx> { + ctxt: &'a mut ElaborateDropsCtxt<'b, 'mir, 'tcx>, } -impl fmt::Debug for Elaborator<'_, '_, '_> { +impl fmt::Debug for Elaborator<'_, '_, '_, '_> { fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { Ok(()) } } -impl<'a, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, '_, 'tcx> { +impl<'a, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, '_, '_, 'tcx> { type Path = MovePathIndex; fn patch(&mut self) -> &mut MirPatch<'tcx> { @@ -238,16 +238,16 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, '_, 'tcx> { } } -struct ElaborateDropsCtxt<'a, 'tcx> { +struct ElaborateDropsCtxt<'a, 'mir, 'tcx> { tcx: TyCtxt<'tcx>, - body: &'a Body<'tcx>, + body: &'mir Body<'tcx>, env: &'a MoveDataParamEnv<'tcx>, - init_data: InitializationData<'a, 'tcx>, + init_data: InitializationData<'a, 'mir, 'tcx>, drop_flags: IndexVec>, patch: MirPatch<'tcx>, } -impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { +impl<'b, 'mir, 'tcx> ElaborateDropsCtxt<'b, 'mir, 'tcx> { fn move_data(&self) -> &'b MoveData<'tcx> { &self.env.move_data } diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 936a7e2d9dedd..3dbdeb615cfe2 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -1074,11 +1074,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { { lhs = *lhs_value; rhs = *rhs_value; - if let Some(op) = self.try_as_operand(lhs, location) { - *lhs_operand = op; - } - if let Some(op) = self.try_as_operand(rhs, location) { - *rhs_operand = op; + if let Some(lhs_op) = self.try_as_operand(lhs, location) + && let Some(rhs_op) = self.try_as_operand(rhs, location) + { + *lhs_operand = lhs_op; + *rhs_operand = rhs_op; } } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 0a5fc697d0321..6fa31c1174d0b 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -11,7 +11,7 @@ use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs} use rustc_middle::mir::visit::*; use rustc_middle::mir::*; use rustc_middle::ty::TypeVisitableExt; -use rustc_middle::ty::{self, Instance, InstanceKind, ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::{self, Instance, InstanceKind, ParamEnv, Ty, TyCtxt, TypeFlags}; use rustc_session::config::{DebugInfo, OptLevel}; use rustc_span::source_map::Spanned; use rustc_span::sym; @@ -85,13 +85,18 @@ fn inline<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool { } let param_env = tcx.param_env_reveal_all_normalized(def_id); + let codegen_fn_attrs = tcx.codegen_fn_attrs(def_id); let mut this = Inliner { tcx, param_env, - codegen_fn_attrs: tcx.codegen_fn_attrs(def_id), + codegen_fn_attrs, history: Vec::new(), changed: false, + caller_is_inline_forwarder: matches!( + codegen_fn_attrs.inline, + InlineAttr::Hint | InlineAttr::Always + ) && body_is_forwarder(body), }; let blocks = START_BLOCK..body.basic_blocks.next_index(); this.process_blocks(body, blocks); @@ -111,6 +116,9 @@ struct Inliner<'tcx> { history: Vec, /// Indicates that the caller body has been modified. changed: bool, + /// Indicates that the caller is #[inline] and just calls another function, + /// and thus we can inline less into it as it'll be inlined itself. + caller_is_inline_forwarder: bool, } impl<'tcx> Inliner<'tcx> { @@ -306,6 +314,16 @@ impl<'tcx> Inliner<'tcx> { InstanceKind::Intrinsic(_) | InstanceKind::Virtual(..) => { return Err("instance without MIR (intrinsic / virtual)"); } + + // FIXME(#127030): `ConstParamHasTy` has bad interactions with + // the drop shim builder, which does not evaluate predicates in + // the correct param-env for types being dropped. Stall resolving + // the MIR for this instance until all of its const params are + // substituted. + InstanceKind::DropGlue(_, Some(ty)) if ty.has_type_flags(TypeFlags::HAS_CT_PARAM) => { + return Err("still needs substitution"); + } + // This cannot result in an immediate cycle since the callee MIR is a shim, which does // not get any optimizations run on it. Any subsequent inlining may cause cycles, but we // do not need to catch this here, we can wait until the inliner decides to continue @@ -475,7 +493,9 @@ impl<'tcx> Inliner<'tcx> { ) -> Result<(), &'static str> { let tcx = self.tcx; - let mut threshold = if cross_crate_inlinable { + let mut threshold = if self.caller_is_inline_forwarder { + self.tcx.sess.opts.unstable_opts.inline_mir_forwarder_threshold.unwrap_or(30) + } else if cross_crate_inlinable { self.tcx.sess.opts.unstable_opts.inline_mir_hint_threshold.unwrap_or(100) } else { self.tcx.sess.opts.unstable_opts.inline_mir_threshold.unwrap_or(50) @@ -494,6 +514,8 @@ impl<'tcx> Inliner<'tcx> { let mut checker = CostChecker::new(self.tcx, self.param_env, Some(callsite.callee), callee_body); + checker.add_function_level_costs(); + // Traverse the MIR manually so we can account for the effects of inlining on the CFG. let mut work_list = vec![START_BLOCK]; let mut visited = BitSet::new_empty(callee_body.basic_blocks.len()); @@ -1081,3 +1103,37 @@ fn try_instance_mir<'tcx>( } Ok(tcx.instance_mir(instance)) } + +fn body_is_forwarder(body: &Body<'_>) -> bool { + let TerminatorKind::Call { target, .. } = body.basic_blocks[START_BLOCK].terminator().kind + else { + return false; + }; + if let Some(target) = target { + let TerminatorKind::Return = body.basic_blocks[target].terminator().kind else { + return false; + }; + } + + let max_blocks = if !body.is_polymorphic { + 2 + } else if target.is_none() { + 3 + } else { + 4 + }; + if body.basic_blocks.len() > max_blocks { + return false; + } + + body.basic_blocks.iter_enumerated().all(|(bb, bb_data)| { + bb == START_BLOCK + || matches!( + bb_data.terminator().kind, + TerminatorKind::Return + | TerminatorKind::Drop { .. } + | TerminatorKind::UnwindResume + | TerminatorKind::UnwindTerminate(_) + ) + }) +} diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index 23cc0c46e7397..27e506a920bce 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -91,43 +91,8 @@ impl<'tcx> MirPass<'tcx> for JumpThreading { opportunities: Vec::new(), }; - for (bb, bbdata) in body.basic_blocks.iter_enumerated() { - debug!(?bb, term = ?bbdata.terminator()); - if bbdata.is_cleanup || loop_headers.contains(bb) { - continue; - } - let Some((discr, targets)) = bbdata.terminator().kind.as_switch() else { continue }; - let Some(discr) = discr.place() else { continue }; - debug!(?discr, ?bb); - - let discr_ty = discr.ty(body, tcx).ty; - let Ok(discr_layout) = finder.ecx.layout_of(discr_ty) else { continue }; - - let Some(discr) = finder.map.find(discr.as_ref()) else { continue }; - debug!(?discr); - - let cost = CostChecker::new(tcx, param_env, None, body); - - let mut state = State::new(ConditionSet::default(), finder.map); - - let conds = if let Some((value, then, else_)) = targets.as_static_if() { - let Some(value) = ScalarInt::try_from_uint(value, discr_layout.size) else { - continue; - }; - arena.alloc_from_iter([ - Condition { value, polarity: Polarity::Eq, target: then }, - Condition { value, polarity: Polarity::Ne, target: else_ }, - ]) - } else { - arena.alloc_from_iter(targets.iter().filter_map(|(value, target)| { - let value = ScalarInt::try_from_uint(value, discr_layout.size)?; - Some(Condition { value, polarity: Polarity::Eq, target }) - })) - }; - let conds = ConditionSet(conds); - state.insert_value_idx(discr, conds, finder.map); - - finder.find_opportunity(bb, state, cost, 0); + for bb in body.basic_blocks.indices() { + finder.start_from_switch(bb); } let opportunities = finder.opportunities; @@ -216,6 +181,46 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { } /// Recursion entry point to find threading opportunities. + #[instrument(level = "trace", skip(self))] + fn start_from_switch(&mut self, bb: BasicBlock) -> Option { + let bbdata = &self.body[bb]; + if bbdata.is_cleanup || self.loop_headers.contains(bb) { + return None; + } + let (discr, targets) = bbdata.terminator().kind.as_switch()?; + let discr = discr.place()?; + debug!(?discr, ?bb); + + let discr_ty = discr.ty(self.body, self.tcx).ty; + let discr_layout = self.ecx.layout_of(discr_ty).ok()?; + + let discr = self.map.find(discr.as_ref())?; + debug!(?discr); + + let cost = CostChecker::new(self.tcx, self.param_env, None, self.body); + let mut state = State::new(ConditionSet::default(), self.map); + + let conds = if let Some((value, then, else_)) = targets.as_static_if() { + let value = ScalarInt::try_from_uint(value, discr_layout.size)?; + self.arena.alloc_from_iter([ + Condition { value, polarity: Polarity::Eq, target: then }, + Condition { value, polarity: Polarity::Ne, target: else_ }, + ]) + } else { + self.arena.alloc_from_iter(targets.iter().filter_map(|(value, target)| { + let value = ScalarInt::try_from_uint(value, discr_layout.size)?; + Some(Condition { value, polarity: Polarity::Eq, target }) + })) + }; + let conds = ConditionSet(conds); + state.insert_value_idx(discr, conds, self.map); + + self.find_opportunity(bb, state, cost, 0); + None + } + + /// Recursively walk statements backwards from this bb's terminator to find threading + /// opportunities. #[instrument(level = "trace", skip(self, cost), ret)] fn find_opportunity( &mut self, @@ -270,12 +275,13 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { self.process_switch_int(discr, targets, bb, &mut state); self.find_opportunity(pred, state, cost, depth + 1); } - _ => self.recurse_through_terminator(pred, &state, &cost, depth), + _ => self.recurse_through_terminator(pred, || state, &cost, depth), } - } else { + } else if let &[ref predecessors @ .., last_pred] = &predecessors[..] { for &pred in predecessors { - self.recurse_through_terminator(pred, &state, &cost, depth); + self.recurse_through_terminator(pred, || state.clone(), &cost, depth); } + self.recurse_through_terminator(last_pred, || state, &cost, depth); } let new_tos = &mut self.opportunities[last_non_rec..]; @@ -566,11 +572,12 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { None } - #[instrument(level = "trace", skip(self, cost))] + #[instrument(level = "trace", skip(self, state, cost))] fn recurse_through_terminator( &mut self, bb: BasicBlock, - state: &State>, + // Pass a closure that may clone the state, as we don't want to do it each time. + state: impl FnOnce() -> State>, cost: &CostChecker<'_, 'tcx>, depth: usize, ) { @@ -600,7 +607,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { }; // We can recurse through this terminator. - let mut state = state.clone(); + let mut state = state(); if let Some(place_to_flood) = place_to_flood { state.flood_with(place_to_flood.as_ref(), self.map, ConditionSet::default()); } diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 21439530c08f6..6ee684605ac60 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -269,6 +269,11 @@ where ecx: &mut EvalCtxt<'_, D>, goal: Goal, ) -> Vec>; + + fn consider_builtin_effects_intersection_candidate( + ecx: &mut EvalCtxt<'_, D>, + goal: Goal, + ) -> Result, NoSolution>; } impl EvalCtxt<'_, D> @@ -420,6 +425,8 @@ where G::consider_builtin_destruct_candidate(self, goal) } else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::TransmuteTrait) { G::consider_builtin_transmute_candidate(self, goal) + } else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::EffectsIntersection) { + G::consider_builtin_effects_intersection_candidate(self, goal) } else { Err(NoSolution) }; diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index 0cef8d9f4bc34..3447b39fa5b40 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -668,8 +668,9 @@ where { let cx = ecx.cx(); let mut requirements = vec![]; - requirements - .extend(cx.super_predicates_of(trait_ref.def_id).iter_instantiated(cx, trait_ref.args)); + requirements.extend( + cx.explicit_super_predicates_of(trait_ref.def_id).iter_instantiated(cx, trait_ref.args), + ); // FIXME(associated_const_equality): Also add associated consts to // the requirements here. diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 4e8cb4384f462..9275bcc8e97c9 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -864,6 +864,68 @@ where ) -> Result, NoSolution> { panic!("`BikeshedIntrinsicFrom` does not have an associated type: {:?}", goal) } + + fn consider_builtin_effects_intersection_candidate( + ecx: &mut EvalCtxt<'_, D>, + goal: Goal, + ) -> Result, NoSolution> { + let ty::Tuple(types) = goal.predicate.self_ty().kind() else { + return Err(NoSolution); + }; + + let cx = ecx.cx(); + + let mut first_non_maybe = None; + let mut non_maybe_count = 0; + for ty in types.iter() { + if !matches!(ty::EffectKind::try_from_ty(cx, ty), Some(ty::EffectKind::Maybe)) { + first_non_maybe.get_or_insert(ty); + non_maybe_count += 1; + } + } + + match non_maybe_count { + 0 => { + let ty = ty::EffectKind::Maybe.to_ty(cx); + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { + ecx.instantiate_normalizes_to_term(goal, ty.into()); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }) + } + 1 => { + let ty = first_non_maybe.unwrap(); + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { + ecx.instantiate_normalizes_to_term(goal, ty.into()); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }) + } + _ => { + let mut min = ty::EffectKind::Maybe; + + for ty in types.iter() { + // We can't find the intersection if the types used are generic. + // + // FIXME(effects) do we want to look at where clauses to get some + // clue for the case where generic types are being used? + let Some(kind) = ty::EffectKind::try_from_ty(cx, ty) else { + return Err(NoSolution); + }; + + let Some(result) = ty::EffectKind::intersection(min, kind) else { + return Err(NoSolution); + }; + + min = result; + } + + let ty = min.to_ty(cx); + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { + ecx.instantiate_normalizes_to_term(goal, ty.into()); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }) + } + } + } } impl EvalCtxt<'_, D> diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 2bc9d35c2b020..f5832f7e5b4c9 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -702,6 +702,47 @@ where } }) } + + fn consider_builtin_effects_intersection_candidate( + ecx: &mut EvalCtxt<'_, D>, + goal: Goal, + ) -> Result, NoSolution> { + if goal.predicate.polarity != ty::PredicatePolarity::Positive { + return Err(NoSolution); + } + + let ty::Tuple(types) = goal.predicate.self_ty().kind() else { + return Err(NoSolution); + }; + + let cx = ecx.cx(); + let maybe_count = types + .iter() + .filter_map(|ty| ty::EffectKind::try_from_ty(cx, ty)) + .filter(|&ty| ty == ty::EffectKind::Maybe) + .count(); + + // Don't do concrete type check unless there are more than one type that will influence the result. + // This would allow `(Maybe, T): Min` pass even if we know nothing about `T`. + if types.len() - maybe_count > 1 { + let mut min = ty::EffectKind::Maybe; + + for ty in types.iter() { + let Some(kind) = ty::EffectKind::try_from_ty(ecx.cx(), ty) else { + return Err(NoSolution); + }; + + let Some(result) = ty::EffectKind::intersection(min, kind) else { + return Err(NoSolution); + }; + + min = result; + } + } + + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) + .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) + } } impl EvalCtxt<'_, D> diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 3cdc20b6c659f..b2df9a14eb01e 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2327,7 +2327,7 @@ impl<'a> Parser<'a> { let before = self.prev_token.clone(); let binder = if self.check_keyword(kw::For) { let lo = self.token.span; - let lifetime_defs = self.parse_late_bound_lifetime_defs()?; + let (lifetime_defs, _) = self.parse_late_bound_lifetime_defs()?; let span = lo.to(self.prev_token.span); self.psess.gated_spans.gate(sym::closure_lifetime_binder, span); diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index fde16ac957dfe..10c7715c7dcd5 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -457,7 +457,7 @@ impl<'a> Parser<'a> { // * `for<'a> Trait1<'a>: Trait2<'a /* ok */>` // * `(for<'a> Trait1<'a>): Trait2<'a /* not ok */>` // * `for<'a> for<'b> Trait1<'a, 'b>: Trait2<'a /* ok */, 'b /* not ok */>` - let lifetime_defs = self.parse_late_bound_lifetime_defs()?; + let (lifetime_defs, _) = self.parse_late_bound_lifetime_defs()?; // Parse type with mandatory colon and (possibly empty) bounds, // or with mandatory equality sign and the second type. diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index d2043c353fed9..1e5b227aaa9be 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -18,7 +18,7 @@ use rustc_ast::{ }; use rustc_errors::{Applicability, PResult}; use rustc_span::symbol::{kw, sym, Ident}; -use rustc_span::{Span, Symbol}; +use rustc_span::{ErrorGuaranteed, Span, Symbol}; use thin_vec::{thin_vec, ThinVec}; #[derive(Copy, Clone, PartialEq)] @@ -280,7 +280,7 @@ impl<'a> Parser<'a> { // Function pointer type or bound list (trait object type) starting with a poly-trait. // `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T` // `for<'lt> Trait1<'lt> + Trait2 + 'a` - let lifetime_defs = self.parse_late_bound_lifetime_defs()?; + let (lifetime_defs, _) = self.parse_late_bound_lifetime_defs()?; if self.check_fn_front_matter(false, Case::Sensitive) { self.parse_ty_bare_fn( lo, @@ -833,12 +833,9 @@ impl<'a> Parser<'a> { let lo = self.token.span; let leading_token = self.prev_token.clone(); let has_parens = self.eat(&token::OpenDelim(Delimiter::Parenthesis)); - let inner_lo = self.token.span; - let modifiers = self.parse_trait_bound_modifiers()?; let bound = if self.token.is_lifetime() { - self.error_lt_bound_with_modifiers(modifiers); - self.parse_generic_lt_bound(lo, inner_lo, has_parens)? + self.parse_generic_lt_bound(lo, has_parens)? } else if self.eat_keyword(kw::Use) { // parse precise captures, if any. This is `use<'lt, 'lt, P, P>`; a list of // lifetimes and ident params (including SelfUpper). These are validated later @@ -848,7 +845,7 @@ impl<'a> Parser<'a> { let (args, args_span) = self.parse_precise_capturing_args()?; GenericBound::Use(args, use_span.to(args_span)) } else { - self.parse_generic_ty_bound(lo, has_parens, modifiers, &leading_token)? + self.parse_generic_ty_bound(lo, has_parens, &leading_token)? }; Ok(bound) @@ -858,50 +855,64 @@ impl<'a> Parser<'a> { /// ```ebnf /// LT_BOUND = LIFETIME /// ``` - fn parse_generic_lt_bound( - &mut self, - lo: Span, - inner_lo: Span, - has_parens: bool, - ) -> PResult<'a, GenericBound> { - let bound = GenericBound::Outlives(self.expect_lifetime()); + fn parse_generic_lt_bound(&mut self, lo: Span, has_parens: bool) -> PResult<'a, GenericBound> { + let lt = self.expect_lifetime(); + let bound = GenericBound::Outlives(lt); if has_parens { // FIXME(Centril): Consider not erroring here and accepting `('lt)` instead, // possibly introducing `GenericBound::Paren(P)`? - self.recover_paren_lifetime(lo, inner_lo)?; + self.recover_paren_lifetime(lo, lt.ident.span)?; } Ok(bound) } /// Emits an error if any trait bound modifiers were present. - fn error_lt_bound_with_modifiers(&self, modifiers: TraitBoundModifiers) { - match modifiers.constness { + fn error_lt_bound_with_modifiers( + &self, + modifiers: TraitBoundModifiers, + binder_span: Option, + ) -> ErrorGuaranteed { + let TraitBoundModifiers { constness, asyncness, polarity } = modifiers; + + match constness { BoundConstness::Never => {} BoundConstness::Always(span) | BoundConstness::Maybe(span) => { - self.dcx().emit_err(errors::ModifierLifetime { - span, - modifier: modifiers.constness.as_str(), - }); + return self + .dcx() + .emit_err(errors::ModifierLifetime { span, modifier: constness.as_str() }); } } - match modifiers.polarity { + match polarity { BoundPolarity::Positive => {} BoundPolarity::Negative(span) | BoundPolarity::Maybe(span) => { - self.dcx().emit_err(errors::ModifierLifetime { - span, - modifier: modifiers.polarity.as_str(), - }); + return self + .dcx() + .emit_err(errors::ModifierLifetime { span, modifier: polarity.as_str() }); + } + } + + match asyncness { + BoundAsyncness::Normal => {} + BoundAsyncness::Async(span) => { + return self + .dcx() + .emit_err(errors::ModifierLifetime { span, modifier: asyncness.as_str() }); } } + + if let Some(span) = binder_span { + return self.dcx().emit_err(errors::ModifierLifetime { span, modifier: "for<...>" }); + } + + unreachable!("lifetime bound intercepted in `parse_generic_ty_bound` but no modifiers?") } /// Recover on `('lifetime)` with `(` already eaten. - fn recover_paren_lifetime(&mut self, lo: Span, inner_lo: Span) -> PResult<'a, ()> { - let inner_span = inner_lo.to(self.prev_token.span); + fn recover_paren_lifetime(&mut self, lo: Span, lt_span: Span) -> PResult<'a, ()> { self.expect(&token::CloseDelim(Delimiter::Parenthesis))?; let span = lo.to(self.prev_token.span); - let (sugg, snippet) = if let Ok(snippet) = self.span_to_snippet(inner_span) { + let (sugg, snippet) = if let Ok(snippet) = self.span_to_snippet(lt_span) { (Some(span), snippet) } else { (None, String::new()) @@ -916,7 +927,7 @@ impl<'a> Parser<'a> { /// If no modifiers are present, this does not consume any tokens. /// /// ```ebnf - /// TRAIT_BOUND_MODIFIERS = [["~"] "const"] ["?" | "!"] + /// TRAIT_BOUND_MODIFIERS = [["~"] "const"] ["async"] ["?" | "!"] /// ``` fn parse_trait_bound_modifiers(&mut self) -> PResult<'a, TraitBoundModifiers> { let constness = if self.eat(&token::Tilde) { @@ -970,15 +981,23 @@ impl<'a> Parser<'a> { /// TY_BOUND_NOPAREN = [TRAIT_BOUND_MODIFIERS] [for] SIMPLE_PATH /// ``` /// - /// For example, this grammar accepts `~const ?for<'a: 'b> m::Trait<'a>`. + /// For example, this grammar accepts `for<'a: 'b> ~const ?m::Trait<'a>`. fn parse_generic_ty_bound( &mut self, lo: Span, has_parens: bool, - modifiers: TraitBoundModifiers, leading_token: &Token, ) -> PResult<'a, GenericBound> { - let mut lifetime_defs = self.parse_late_bound_lifetime_defs()?; + let modifiers = self.parse_trait_bound_modifiers()?; + let (mut lifetime_defs, binder_span) = self.parse_late_bound_lifetime_defs()?; + + // Recover erroneous lifetime bound with modifiers or binder. + // e.g. `T: for<'a> 'a` or `T: ~const 'a`. + if self.token.is_lifetime() { + let _: ErrorGuaranteed = self.error_lt_bound_with_modifiers(modifiers, binder_span); + return self.parse_generic_lt_bound(lo, has_parens); + } + let mut path = if self.token.is_keyword(kw::Fn) && self.look_ahead(1, |tok| tok.kind == TokenKind::OpenDelim(Delimiter::Parenthesis)) && let Some(path) = self.recover_path_from_fn() @@ -1094,16 +1113,19 @@ impl<'a> Parser<'a> { } /// Optionally parses `for<$generic_params>`. - pub(super) fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, ThinVec> { + pub(super) fn parse_late_bound_lifetime_defs( + &mut self, + ) -> PResult<'a, (ThinVec, Option)> { if self.eat_keyword(kw::For) { + let lo = self.token.span; self.expect_lt()?; let params = self.parse_generic_params()?; self.expect_gt()?; - // We rely on AST validation to rule out invalid cases: There must not be type - // parameters, and the lifetime parameters must not have bounds. - Ok(params) + // We rely on AST validation to rule out invalid cases: There must not be + // type or const parameters, and parameters must not have bounds. + Ok((params, Some(lo.to(self.prev_token.span)))) } else { - Ok(ThinVec::new()) + Ok((ThinVec::new(), None)) } } diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 5a560325ab950..d7513fbad63c8 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -782,6 +782,7 @@ passes_used_compiler_linker = passes_used_static = attribute must be applied to a `static` variable + .label = but this is a {$target} passes_useless_assignment = useless assignment of {$is_field_assign -> diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 5f8e4a8b7a761..0eb9d1ce59f1d 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -274,7 +274,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } self.check_repr(attrs, span, target, item, hir_id); - self.check_used(attrs, target); + self.check_used(attrs, target, span); } fn inline_attr_str_error_with_macro_def(&self, hir_id: HirId, attr: &Attribute, sym: &str) { @@ -1930,12 +1930,16 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_used(&self, attrs: &[Attribute], target: Target) { + fn check_used(&self, attrs: &[Attribute], target: Target, target_span: Span) { let mut used_linker_span = None; let mut used_compiler_span = None; for attr in attrs.iter().filter(|attr| attr.has_name(sym::used)) { if target != Target::Static { - self.dcx().emit_err(errors::UsedStatic { span: attr.span }); + self.dcx().emit_err(errors::UsedStatic { + attr_span: attr.span, + span: target_span, + target: target.name(), + }); } let inner = attr.meta_item_list(); match inner.as_deref() { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 7734dba367046..a026ff3b13b57 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -551,7 +551,10 @@ pub struct ReprConflictingLint; #[diag(passes_used_static)] pub struct UsedStatic { #[primary_span] + pub attr_span: Span, + #[label] pub span: Span, + pub target: &'static str, } #[derive(Diagnostic)] diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 80f7ca544f3c5..2e4421d50e313 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1766,6 +1766,8 @@ options! { "enable LLVM inlining (default: yes)"), inline_mir: Option = (None, parse_opt_bool, [TRACKED], "enable MIR inlining (default: no)"), + inline_mir_forwarder_threshold: Option = (None, parse_opt_number, [TRACKED], + "inlining threshold when the caller is a simple forwarding function (default: 30)"), inline_mir_hint_threshold: Option = (None, parse_opt_number, [TRACKED], "inlining threshold for functions with inline hint (default: 100)"), inline_mir_preserve_debug: Option = (None, parse_opt_bool, [TRACKED], diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index e23f4289e981a..4eefd0eb17c40 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -160,7 +160,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> { fn predicates_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::GenericPredicates { let mut tables = self.0.borrow_mut(); let def_id = tables[def_id]; - let GenericPredicates { parent, predicates } = tables.tcx.predicates_of(def_id); + let GenericPredicates { parent, predicates, effects_min_tys: _ } = + tables.tcx.predicates_of(def_id); stable_mir::ty::GenericPredicates { parent: parent.map(|did| tables.trait_def(did)), predicates: predicates @@ -181,7 +182,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> { ) -> stable_mir::ty::GenericPredicates { let mut tables = self.0.borrow_mut(); let def_id = tables[def_id]; - let GenericPredicates { parent, predicates } = tables.tcx.explicit_predicates_of(def_id); + let GenericPredicates { parent, predicates, effects_min_tys: _ } = + tables.tcx.explicit_predicates_of(def_id); stable_mir::ty::GenericPredicates { parent: parent.map(|did| tables.trait_def(did)), predicates: predicates diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index 74c3fcc9b9ea9..9382460d6d403 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -600,7 +600,7 @@ impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDefKind { ty::GenericParamDefKind::Type { has_default, synthetic } => { GenericParamDefKind::Type { has_default: *has_default, synthetic: *synthetic } } - ty::GenericParamDefKind::Const { has_default, is_host_effect: _ } => { + ty::GenericParamDefKind::Const { has_default, is_host_effect: _, synthetic: _ } => { GenericParamDefKind::Const { has_default: *has_default } } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 3b6147c4c0f64..7da9211bcbf74 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -194,6 +194,14 @@ symbols! { Display, DoubleEndedIterator, Duration, + EffectsCompat, + EffectsIntersection, + EffectsIntersectionOutput, + EffectsMaybe, + EffectsNoRuntime, + EffectsRuntime, + EffectsTyCompat, + Effects__, Encodable, Encoder, Enumerate, @@ -1606,6 +1614,7 @@ symbols! { rustc_do_not_const_check, rustc_doc_primitive, rustc_dummy, + rustc_dump_def_parents, rustc_dump_item_bounds, rustc_dump_predicates, rustc_dump_user_args, @@ -1658,6 +1667,7 @@ symbols! { rustc_reallocator, rustc_regions, rustc_reservation_impl, + rustc_runtime, rustc_safe_intrinsic, rustc_serialize, rustc_skip_during_method_dispatch, diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml index 1f4fb57d996cc..f023a0eb53aeb 100644 --- a/compiler/rustc_trait_selection/Cargo.toml +++ b/compiler/rustc_trait_selection/Cargo.toml @@ -5,8 +5,6 @@ edition = "2021" [dependencies] # tidy-alphabetical-start -bitflags = "2.4.1" -derivative = "2.2.0" itertools = "0.12" rustc_ast = { path = "../rustc_ast" } rustc_ast_ir = { path = "../rustc_ast_ir" } @@ -15,7 +13,6 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } -rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } @@ -28,7 +25,6 @@ rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_transmute = { path = "../rustc_transmute", features = ["rustc"] } rustc_type_ir = { path = "../rustc_type_ir" } -rustc_type_ir_macros = { path = "../rustc_type_ir_macros" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs index 4b5b1d77b30da..34da8e576ce86 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs @@ -88,7 +88,7 @@ impl<'tcx> InferCtxt<'tcx> { found_args: Vec, is_closure: bool, closure_arg_span: Option, - ) -> Diag<'tcx> { + ) -> Diag<'_> { let kind = if is_closure { "closure" } else { "function" }; let args_str = |arguments: &[ArgKind], other: &[ArgKind]| { diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index f4a026c0367f4..ccf86dbb1d0b6 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -241,8 +241,8 @@ pub fn suggest_restriction<'tcx, G: EmissionGuarantee>( } } -#[extension(pub trait TypeErrCtxtExt<'tcx>)] -impl<'tcx> TypeErrCtxt<'_, 'tcx> { +#[extension(pub trait TypeErrCtxtExt<'a, 'tcx>)] +impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { fn suggest_restricting_param_bound( &self, err: &mut Diag<'_>, @@ -1845,7 +1845,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { fn point_at_returns_when_relevant( &self, - err: &mut Diag<'tcx>, + err: &mut Diag<'_>, obligation: &PredicateObligation<'tcx>, ) { match obligation.cause.code().peel_derives() { @@ -1884,7 +1884,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { cause: &ObligationCauseCode<'tcx>, found_node: Option>, param_env: ty::ParamEnv<'tcx>, - ) -> Diag<'tcx> { + ) -> Diag<'a> { pub(crate) fn build_fn_sig_ty<'tcx>( infcx: &InferCtxt<'tcx>, trait_ref: ty::TraitRef<'tcx>, @@ -2104,7 +2104,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { fn note_conflicting_closure_bounds( &self, cause: &ObligationCauseCode<'tcx>, - err: &mut Diag<'tcx>, + err: &mut Diag<'_>, ) { // First, look for an `WhereClauseInExpr`, which means we can get // the uninstantiated predicate list of the called function. And check @@ -4995,6 +4995,12 @@ fn point_at_assoc_type_restriction( let ty::ClauseKind::Projection(proj) = clause else { return; }; + // avoid ICEing since effects desugared associated types don't have names. + // this path should only be hit for `~const` on invalid places, so they + // will have an informative error already. + if tcx.is_effects_desugared_assoc_ty(proj.projection_term.def_id) { + return; + } let name = tcx.item_name(proj.projection_term.def_id); let mut predicates = generics.predicates.iter().peekable(); let mut prev: Option<&hir::WhereBoundPredicate<'_>> = None; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index d3096cf4b52ce..adf1076a7c90e 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -82,8 +82,8 @@ pub fn suggest_new_overflow_limit<'tcx, G: EmissionGuarantee>( )); } -#[extension(pub trait TypeErrCtxtExt<'tcx>)] -impl<'tcx> TypeErrCtxt<'_, 'tcx> { +#[extension(pub trait TypeErrCtxtExt<'a, 'tcx>)] +impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { fn report_fulfillment_errors( &self, mut errors: Vec>, @@ -228,7 +228,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { cause: OverflowCause<'tcx>, span: Span, suggest_increasing_limit: bool, - ) -> Diag<'tcx> { + ) -> Diag<'a> { fn with_short_path<'tcx, T>(tcx: TyCtxt<'tcx>, value: T) -> String where T: fmt::Display + Print<'tcx, FmtPrinter<'tcx, 'tcx>>, @@ -1101,7 +1101,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { && let ty::FnPtr(sig) = by_ref_captures.kind() && !sig.skip_binder().output().is_unit() { - let mut err = self.tcx.dcx().create_err(AsyncClosureNotFn { + let mut err = self.dcx().create_err(AsyncClosureNotFn { span: self.tcx.def_span(closure_def_id), kind: expected_kind.as_str(), }); @@ -1351,7 +1351,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { &self, ty: Ty<'tcx>, obligation: &PredicateObligation<'tcx>, - ) -> Diag<'tcx> { + ) -> Diag<'a> { let span = obligation.cause.span; let mut diag = match ty.kind() { @@ -1445,8 +1445,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } } -#[extension(pub(super) trait InferCtxtPrivExt<'tcx>)] -impl<'tcx> TypeErrCtxt<'_, 'tcx> { +#[extension(pub(super) trait InferCtxtPrivExt<'a, 'tcx>)] +impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { fn can_match_trait( &self, goal: ty::TraitPredicate<'tcx>, @@ -2884,7 +2884,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { self.suggest_unsized_bound_if_applicable(err, obligation); if let Some(span) = err.span.primary_span() && let Some(mut diag) = - self.tcx.dcx().steal_non_err(span, StashKey::AssociatedTypeSuggestion) + self.dcx().steal_non_err(span, StashKey::AssociatedTypeSuggestion) && let Ok(ref mut s1) = err.suggestions && let Ok(ref mut s2) = diag.suggestions { @@ -3379,7 +3379,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { found_kind: ty::ClosureKind, kind: ty::ClosureKind, trait_prefix: &'static str, - ) -> Diag<'tcx> { + ) -> Diag<'a> { let closure_span = self.tcx.def_span(closure_def_id); let mut err = ClosureKindMismatch { @@ -3422,7 +3422,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { found_trait_ref: ty::TraitRef<'tcx>, expected_trait_ref: ty::TraitRef<'tcx>, terr: TypeError<'tcx>, - ) -> Diag<'tcx> { + ) -> Diag<'a> { let self_ty = found_trait_ref.self_ty(); let (cause, terr) = if let ty::Closure(def_id, _) = self_ty.kind() { ( @@ -3473,7 +3473,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { span: Span, found_trait_ref: ty::TraitRef<'tcx>, expected_trait_ref: ty::TraitRef<'tcx>, - ) -> Result, ErrorGuaranteed> { + ) -> Result, ErrorGuaranteed> { let found_trait_ref = self.resolve_vars_if_possible(found_trait_ref); let expected_trait_ref = self.resolve_vars_if_possible(expected_trait_ref); @@ -3553,7 +3553,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { }) .unwrap_or((found_span, None, found)); - self.report_arg_count_mismatch( + self.infcx.report_arg_count_mismatch( span, closure_span, expected, @@ -3569,7 +3569,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { &self, obligation: &PredicateObligation<'tcx>, span: Span, - ) -> Result, ErrorGuaranteed> { + ) -> Result, ErrorGuaranteed> { if !self.tcx.features().generic_const_exprs { let guar = self .dcx() diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 4d10d33fa6ef5..f1611bd049de9 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -187,7 +187,7 @@ fn predicates_reference_self( ) -> SmallVec<[Span; 1]> { let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_def_id)); let predicates = if supertraits_only { - tcx.super_predicates_of(trait_def_id) + tcx.explicit_super_predicates_of(trait_def_id) } else { tcx.predicates_of(trait_def_id) }; @@ -256,7 +256,7 @@ fn super_predicates_have_non_lifetime_binders( if !tcx.features().non_lifetime_binders { return SmallVec::new(); } - tcx.super_predicates_of(trait_def_id) + tcx.explicit_super_predicates_of(trait_def_id) .predicates .iter() .filter_map(|(pred, span)| pred.has_non_region_bound_vars().then_some(*span)) diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 8c5dc88184cda..9508a3e8e1509 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -574,7 +574,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Check supertraits hold. This is so that their associated type bounds // will be checked in the code below. for super_trait in tcx - .super_predicates_of(trait_predicate.def_id()) + .explicit_super_predicates_of(trait_predicate.def_id()) .instantiate(tcx, trait_predicate.trait_ref.args) .predicates .into_iter() diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index f132e36468ac2..951af4b0920cb 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -128,7 +128,7 @@ impl<'tcx> TraitAliasExpander<'tcx> { } // Get components of trait alias. - let predicates = tcx.super_predicates_of(trait_ref.def_id()); + let predicates = tcx.explicit_super_predicates_of(trait_ref.def_id()); debug!(?predicates); let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| { diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index 017b0a45d1f41..e54ced85deeb7 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -117,7 +117,7 @@ fn prepare_vtable_segments_inner<'tcx, T>( let &(inner_most_trait_ref, _, _) = stack.last().unwrap(); let mut direct_super_traits_iter = tcx - .super_predicates_of(inner_most_trait_ref.def_id()) + .explicit_super_predicates_of(inner_most_trait_ref.def_id()) .predicates .into_iter() .filter_map(move |(pred, _)| { diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 4395eb57cd6d2..6726db8bb54df 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -4,8 +4,9 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, ImplTraitInTraitData, TyCtxt}; +use rustc_middle::ty::{self, ImplTraitInTraitData, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; +use rustc_span::sym; use rustc_span::symbol::kw; pub(crate) fn provide(providers: &mut Providers) { @@ -14,6 +15,7 @@ pub(crate) fn provide(providers: &mut Providers) { associated_item_def_ids, associated_items, associated_types_for_impl_traits_in_associated_fn, + associated_type_for_effects, associated_type_for_impl_trait_in_trait, impl_item_implementor_ids, ..*providers @@ -44,7 +46,8 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[DefId] { ) }) .copied(), - ), + ) + .chain(tcx.associated_type_for_effects(def_id)), ) } hir::ItemKind::Impl(impl_) => { @@ -70,7 +73,8 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[DefId] { ) }) .copied() - })), + })) + .chain(tcx.associated_type_for_effects(def_id)), ) } _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"), @@ -143,6 +147,7 @@ fn associated_item_from_trait_item_ref(trait_item_ref: &hir::TraitItemRef) -> ty container: ty::TraitContainer, fn_has_self_parameter: has_self, opt_rpitit_info: None, + is_effects_desugaring: false, } } @@ -162,9 +167,138 @@ fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::A container: ty::ImplContainer, fn_has_self_parameter: has_self, opt_rpitit_info: None, + is_effects_desugaring: false, } } +/// Given an `def_id` of a trait or a trait impl: +/// +/// If `def_id` is a trait that has `#[const_trait]`, then it synthesizes +/// a new def id corresponding to a new associated type for the effects. +/// +/// If `def_id` is an impl, then synthesize the associated type according +/// to the constness of the impl. +fn associated_type_for_effects(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option { + // don't synthesize the associated type even if the user has written `const_trait` + // if the effects feature is disabled. + if !tcx.features().effects { + return None; + } + let (feed, parent_did) = match tcx.def_kind(def_id) { + DefKind::Trait => { + let trait_def_id = def_id; + let attr = tcx.get_attr(def_id, sym::const_trait)?; + + let span = attr.span; + let trait_assoc_ty = tcx.at(span).create_def(trait_def_id, kw::Empty, DefKind::AssocTy); + + let local_def_id = trait_assoc_ty.def_id(); + let def_id = local_def_id.to_def_id(); + + // Copy span of the attribute. + trait_assoc_ty.def_ident_span(Some(span)); + + trait_assoc_ty.associated_item(ty::AssocItem { + name: kw::Empty, + kind: ty::AssocKind::Type, + def_id, + trait_item_def_id: None, + container: ty::TraitContainer, + fn_has_self_parameter: false, + opt_rpitit_info: None, + is_effects_desugaring: true, + }); + + // No default type + trait_assoc_ty.defaultness(hir::Defaultness::Default { has_value: false }); + + trait_assoc_ty.is_type_alias_impl_trait(false); + + (trait_assoc_ty, trait_def_id) + } + DefKind::Impl { .. } => { + let impl_def_id = def_id; + let trait_id = tcx.trait_id_of_impl(def_id.to_def_id())?; + + // first get the DefId of the assoc type on the trait, if there is not, + // then we don't need to generate it on the impl. + let trait_assoc_id = tcx.associated_type_for_effects(trait_id)?; + + // FIXME(effects): span + let span = tcx.def_ident_span(def_id).unwrap(); + + let impl_assoc_ty = tcx.at(span).create_def(def_id, kw::Empty, DefKind::AssocTy); + + let local_def_id = impl_assoc_ty.def_id(); + let def_id = local_def_id.to_def_id(); + + impl_assoc_ty.def_ident_span(Some(span)); + + impl_assoc_ty.associated_item(ty::AssocItem { + name: kw::Empty, + kind: ty::AssocKind::Type, + def_id, + trait_item_def_id: Some(trait_assoc_id), + container: ty::ImplContainer, + fn_has_self_parameter: false, + opt_rpitit_info: None, + is_effects_desugaring: true, + }); + + // no default value. + impl_assoc_ty.defaultness(hir::Defaultness::Final); + + // set the type of the associated type! If this is a const impl, + // we set to Maybe, otherwise we set to `Runtime`. + let type_def_id = if tcx.is_const_trait_impl_raw(impl_def_id.to_def_id()) { + tcx.require_lang_item(hir::LangItem::EffectsMaybe, Some(span)) + } else { + tcx.require_lang_item(hir::LangItem::EffectsRuntime, Some(span)) + }; + // FIXME(effects): make impls use `Min` for their effect types + impl_assoc_ty.type_of(ty::EarlyBinder::bind(Ty::new_adt( + tcx, + tcx.adt_def(type_def_id), + ty::GenericArgs::empty(), + ))); + + (impl_assoc_ty, impl_def_id) + } + def_kind => bug!( + "associated_type_for_effects: {:?} should be Trait or Impl but is {:?}", + def_id, + def_kind + ), + }; + + feed.feed_hir(); + + // visibility is public. + feed.visibility(ty::Visibility::Public); + + // Copy generics_of of the trait/impl, making the trait/impl as parent. + feed.generics_of({ + let parent_generics = tcx.generics_of(parent_did); + let parent_count = parent_generics.parent_count + parent_generics.own_params.len(); + + ty::Generics { + parent: Some(parent_did.to_def_id()), + parent_count, + own_params: vec![], + param_def_id_to_index: parent_generics.param_def_id_to_index.clone(), + has_self: false, + has_late_bound_regions: None, + host_effect_index: parent_generics.host_effect_index, + } + }); + feed.explicit_item_super_predicates(ty::EarlyBinder::bind(&[])); + + // There are no inferred outlives for the synthesized associated type. + feed.inferred_outlives_of(&[]); + + Some(feed.def_id().to_def_id()) +} + /// Given an `fn_def_id` of a trait or a trait implementation: /// /// if `fn_def_id` is a function defined inside a trait, then it synthesizes @@ -275,6 +409,7 @@ fn associated_type_for_impl_trait_in_trait( fn_def_id: fn_def_id.to_def_id(), opaque_def_id: opaque_ty_def_id.to_def_id(), }), + is_effects_desugaring: false, }); // Copy visility of the containing function. @@ -326,6 +461,7 @@ fn associated_type_for_impl_trait_in_impl( container: ty::ImplContainer, fn_has_self_parameter: false, opt_rpitit_info: Some(ImplTraitInTraitData::Impl { fn_def_id: impl_fn_def_id.to_def_id() }), + is_effects_desugaring: false, }); // Copy visility of the containing function. diff --git a/compiler/rustc_type_ir/src/effects.rs b/compiler/rustc_type_ir/src/effects.rs new file mode 100644 index 0000000000000..f7942f2f982f5 --- /dev/null +++ b/compiler/rustc_type_ir/src/effects.rs @@ -0,0 +1,59 @@ +use crate::inherent::{AdtDef, IntoKind, Ty}; +use crate::lang_items::TraitSolverLangItem::{EffectsMaybe, EffectsNoRuntime, EffectsRuntime}; +use crate::Interner; + +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum EffectKind { + Maybe, + Runtime, + NoRuntime, +} + +impl EffectKind { + pub fn try_from_def_id(tcx: I, def_id: I::DefId) -> Option { + if tcx.is_lang_item(def_id, EffectsMaybe) { + Some(EffectKind::Maybe) + } else if tcx.is_lang_item(def_id, EffectsRuntime) { + Some(EffectKind::Runtime) + } else if tcx.is_lang_item(def_id, EffectsNoRuntime) { + Some(EffectKind::NoRuntime) + } else { + None + } + } + + pub fn to_def_id(self, tcx: I) -> I::DefId { + let lang_item = match self { + EffectKind::Maybe => EffectsMaybe, + EffectKind::NoRuntime => EffectsNoRuntime, + EffectKind::Runtime => EffectsRuntime, + }; + + tcx.require_lang_item(lang_item) + } + + pub fn try_from_ty(tcx: I, ty: I::Ty) -> Option { + if let crate::Adt(def, _) = ty.kind() { + Self::try_from_def_id(tcx, def.def_id()) + } else { + None + } + } + + pub fn to_ty(self, tcx: I) -> I::Ty { + I::Ty::new_adt(tcx, tcx.adt_def(self.to_def_id(tcx)), Default::default()) + } + + /// Returns an intersection between two effect kinds. If one effect kind + /// is more permissive than the other (e.g. `Maybe` vs `Runtime`), this + /// returns the less permissive effect kind (`Runtime`). + pub fn intersection(a: Self, b: Self) -> Option { + use EffectKind::*; + match (a, b) { + (Maybe, x) | (x, Maybe) => Some(x), + (Runtime, Runtime) => Some(Runtime), + (NoRuntime, NoRuntime) => Some(NoRuntime), + (Runtime, NoRuntime) | (NoRuntime, Runtime) => None, + } + } +} diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index b89ea30fc3435..6665158c7cd34 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -209,8 +209,7 @@ pub trait Interner: def_id: Self::DefId, ) -> ty::EarlyBinder>; - // FIXME: Rename this so it's obvious it's only *immediate* super predicates. - fn super_predicates_of( + fn explicit_super_predicates_of( self, def_id: Self::DefId, ) -> ty::EarlyBinder>; diff --git a/compiler/rustc_type_ir/src/lang_items.rs b/compiler/rustc_type_ir/src/lang_items.rs index cf5ec1ab3febc..cf00c37caa287 100644 --- a/compiler/rustc_type_ir/src/lang_items.rs +++ b/compiler/rustc_type_ir/src/lang_items.rs @@ -17,6 +17,11 @@ pub enum TraitSolverLangItem { Destruct, DiscriminantKind, DynMetadata, + EffectsIntersection, + EffectsIntersectionOutput, + EffectsMaybe, + EffectsNoRuntime, + EffectsRuntime, FnPtrTrait, FusedIterator, Future, diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 9b8ca5efdda82..d7442e7c89c4a 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -35,6 +35,7 @@ mod macros; mod binder; mod canonical; mod const_kind; +mod effects; mod flags; mod generic_arg; mod interner; @@ -51,6 +52,7 @@ pub use canonical::*; #[cfg(feature = "nightly")] pub use codec::*; pub use const_kind::*; +pub use effects::*; pub use flags::*; pub use generic_arg::*; pub use interner::*; diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index 024b92790e970..612452a960a37 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -47,8 +47,6 @@ optimize_for_size = ["core/optimize_for_size"] [lints.rust.unexpected_cfgs] level = "warn" -# x.py uses beta cargo, so `check-cfg` entries do not yet take effect -# for rust-lang/rust. But for users of `-Zbuild-std` it does. check-cfg = [ 'cfg(bootstrap)', 'cfg(no_global_oom_handling)', diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 1134c7f833e2b..7b7dae5a057f0 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -429,6 +429,7 @@ impl RawVec { /// /// Aborts on OOM. #[cfg(not(no_global_oom_handling))] + #[inline] pub fn shrink_to_fit(&mut self, cap: usize) { if let Err(err) = self.shrink(cap) { handle_error(err); @@ -511,9 +512,25 @@ impl RawVec { } #[cfg(not(no_global_oom_handling))] + #[inline] fn shrink(&mut self, cap: usize) -> Result<(), TryReserveError> { assert!(cap <= self.capacity(), "Tried to shrink to a larger capacity"); + // SAFETY: Just checked this isn't trying to grow + unsafe { self.shrink_unchecked(cap) } + } + /// `shrink`, but without the capacity check. + /// + /// This is split out so that `shrink` can inline the check, since it + /// optimizes out in things like `shrink_to_fit`, without needing to + /// also inline all this code, as doing that ends up failing the + /// `vec-shrink-panic` codegen test when `shrink_to_fit` ends up being too + /// big for LLVM to be willing to inline. + /// + /// # Safety + /// `cap <= self.capacity()` + #[cfg(not(no_global_oom_handling))] + unsafe fn shrink_unchecked(&mut self, cap: usize) -> Result<(), TryReserveError> { let (ptr, layout) = if let Some(mem) = self.current_memory() { mem } else { return Ok(()) }; // See current_memory() why this assert is here const { assert!(mem::size_of::() % mem::align_of::() == 0) }; diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 743429d26dbfb..f1706e31bb80a 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1101,6 +1101,7 @@ impl Vec { /// ``` #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] + #[inline] pub fn shrink_to_fit(&mut self) { // The capacity is never less than the length, and there's nothing to do when // they are equal, so we can avoid the panic case in `RawVec::shrink_to_fit` diff --git a/library/core/Cargo.toml b/library/core/Cargo.toml index cf9fddd269aa4..cace4582b489a 100644 --- a/library/core/Cargo.toml +++ b/library/core/Cargo.toml @@ -39,8 +39,6 @@ debug_refcell = [] [lints.rust.unexpected_cfgs] level = "warn" -# x.py uses beta cargo, so `check-cfg` entries do not yet take effect -# for rust-lang/rust. But for users of `-Zbuild-std` it does. check-cfg = [ 'cfg(bootstrap)', 'cfg(no_fp_fmt_parse)', diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 37cb8e7d303af..eab11ae288a95 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -602,7 +602,7 @@ impl dyn Any + Send + Sync { /// While `TypeId` implements `Hash`, `PartialOrd`, and `Ord`, it is worth /// noting that the hashes and ordering will vary between Rust releases. Beware /// of relying on them inside of your code! -#[derive(Clone, Copy, Debug, Eq, PartialOrd, Ord)] +#[derive(Clone, Copy, Eq, PartialOrd, Ord)] #[stable(feature = "rust1", since = "1.0.0")] pub struct TypeId { // We avoid using `u128` because that imposes higher alignment requirements on many platforms. @@ -644,6 +644,10 @@ impl TypeId { let t2 = t as u64; TypeId { t: (t1, t2) } } + + fn as_u128(self) -> u128 { + u128::from(self.t.0) << 64 | u128::from(self.t.1) + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -666,6 +670,13 @@ impl hash::Hash for TypeId { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for TypeId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + f.debug_tuple("TypeId").field(&self.as_u128()).finish() + } +} + /// Returns the name of a type as a string slice. /// /// # Note diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 3bcd4be183465..d0e188dfcd1d8 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -2484,8 +2484,7 @@ impl Display for char { #[stable(feature = "rust1", since = "1.0.0")] impl Pointer for *const T { fn fmt(&self, f: &mut Formatter<'_>) -> Result { - // Cast is needed here because `.expose_provenance()` requires `T: Sized`. - pointer_fmt_inner((*self as *const ()).expose_provenance(), f) + pointer_fmt_inner(self.expose_provenance(), f) } } diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index 1c93a7b28fd35..da734466263ab 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -334,6 +334,7 @@ pub trait Hasher { /// /// [`write`]: Hasher::write #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] fn finish(&self) -> u64; /// Writes some data into this `Hasher`. diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd.rs index 4be5e62ea5bc6..b892e11158822 100644 --- a/library/core/src/intrinsics/simd.rs +++ b/library/core/src/intrinsics/simd.rs @@ -263,9 +263,6 @@ extern "rust-intrinsic" { /// /// `V` must be a vector of integers with the same length as `T` (but any element size). /// - /// `idx` must be a constant: either naming a constant item, or an inline - /// `const {}` expression. - /// /// For each pointer in `ptr`, if the corresponding value in `mask` is `!0`, read the pointer. /// Otherwise if the corresponding value in `mask` is `0`, return the corresponding value from /// `val`. diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index d1692729a31b4..128f1c818272b 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -34,12 +34,9 @@ //! Rust user code is to call the functions provided by this library instead (such as //! `ptr::copy`). //! -//! * `rust_begin_panic` - This function takes four arguments, a -//! `fmt::Arguments`, a `&'static str`, and two `u32`'s. These four arguments -//! dictate the panic message, the file at which panic was invoked, and the -//! line and column inside the file. It is up to consumers of this core +//! * Panic handler - This function takes one argument, a `&panic::PanicInfo`. It is up to consumers of this core //! library to define this panic function; it is only required to never -//! return. This requires a `lang` attribute named `panic_impl`. +//! return. You should mark your implementation using `#[panic_handler]`. //! //! * `rust_eh_personality` - is used by the failure mechanisms of the //! compiler. This is often mapped to GCC's personality function, but crates @@ -231,6 +228,7 @@ #![feature(let_chains)] #![feature(link_llvm_intrinsics)] #![feature(macro_metavar_expr)] +#![feature(marker_trait_attr)] #![feature(min_exhaustive_patterns)] #![feature(min_specialization)] #![feature(multiple_supertrait_upcastable)] diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 0fedb8835d1ae..21abd7c036ba7 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -996,15 +996,12 @@ marker_impls! { bool, char, str /* Technically requires `[u8]: ConstParamTy` */, + (), {T: ConstParamTy, const N: usize} [T; N], {T: ConstParamTy} [T], {T: ?Sized + ConstParamTy} &T, } -// FIXME(adt_const_params): Add to marker_impls call above once not in bootstrap -#[unstable(feature = "adt_const_params", issue = "95174")] -impl ConstParamTy for () {} - /// A common trait implemented by all function pointers. #[unstable( feature = "fn_ptr_trait", @@ -1027,3 +1024,49 @@ pub trait FnPtr: Copy + Clone { pub macro SmartPointer($item:item) { /* compiler built-in */ } + +// Support traits and types for the desugaring of const traits and +// `~const` bounds. Not supposed to be used by anything other than +// the compiler. +#[doc(hidden)] +#[unstable( + feature = "effect_types", + issue = "none", + reason = "internal module for implementing effects" +)] +#[allow(missing_debug_implementations)] // these unit structs don't need `Debug` impls. +#[cfg(not(bootstrap))] +pub mod effects { + #[lang = "EffectsNoRuntime"] + pub struct NoRuntime; + #[lang = "EffectsMaybe"] + pub struct Maybe; + #[lang = "EffectsRuntime"] + pub struct Runtime; + + #[lang = "EffectsCompat"] + pub trait Compat<#[rustc_runtime] const RUNTIME: bool> {} + + impl Compat for NoRuntime {} + impl Compat for Runtime {} + impl<#[rustc_runtime] const RUNTIME: bool> Compat for Maybe {} + + #[lang = "EffectsTyCompat"] + #[marker] + pub trait TyCompat {} + + impl TyCompat for T {} + impl TyCompat for Maybe {} + impl TyCompat for T {} + + #[lang = "EffectsIntersection"] + pub trait Intersection { + #[lang = "EffectsIntersectionOutput"] + type Output: ?Sized; + } + + // FIXME(effects): remove this after next trait solver lands + impl Intersection for () { + type Output = Maybe; + } +} diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs index b578756e46a66..c11a508a135b3 100644 --- a/library/core/src/net/ip_addr.rs +++ b/library/core/src/net/ip_addr.rs @@ -406,7 +406,7 @@ impl IpAddr { matches!(self, IpAddr::V6(_)) } - /// Converts this address to an `IpAddr::V4` if it is an IPv4-mapped IPv6 addresses, otherwise it + /// Converts this address to an `IpAddr::V4` if it is an IPv4-mapped IPv6 address, otherwise it /// returns `self` as-is. /// /// # Examples @@ -1879,7 +1879,7 @@ impl Ipv6Addr { } } - /// Converts this address to an `IpAddr::V4` if it is an IPv4-mapped addresses, otherwise it + /// Converts this address to an `IpAddr::V4` if it is an IPv4-mapped address, otherwise it /// returns self wrapped in an `IpAddr::V6`. /// /// # Examples diff --git a/library/core/src/num/dec2flt/common.rs b/library/core/src/num/dec2flt/common.rs index 11a626485191c..c85727b493816 100644 --- a/library/core/src/num/dec2flt/common.rs +++ b/library/core/src/num/dec2flt/common.rs @@ -39,9 +39,7 @@ impl ByteSlice for [u8] { fn parse_digits(&self, mut func: impl FnMut(u8)) -> &Self { let mut s = self; - // FIXME: Can't use s.split_first() here yet, - // see https://github.com/rust-lang/rust/issues/109328 - while let [c, s_next @ ..] = s { + while let Some((c, s_next)) = s.split_first() { let c = c.wrapping_sub(b'0'); if c < 10 { func(c); diff --git a/library/core/src/num/dec2flt/parse.rs b/library/core/src/num/dec2flt/parse.rs index b0a23835c5bd4..975bb8ad6bc1f 100644 --- a/library/core/src/num/dec2flt/parse.rs +++ b/library/core/src/num/dec2flt/parse.rs @@ -51,9 +51,7 @@ fn try_parse_19digits(s_ref: &mut &[u8], x: &mut u64) { let mut s = *s_ref; while *x < MIN_19DIGIT_INT { - // FIXME: Can't use s.split_first() here yet, - // see https://github.com/rust-lang/rust/issues/109328 - if let [c, s_next @ ..] = s { + if let Some((c, s_next)) = s.split_first() { let digit = c.wrapping_sub(b'0'); if digit < 10 { diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index cd74cece0d12e..ad72c29758bd7 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -2726,7 +2726,7 @@ macro_rules! uint_impl { pub const fn div_ceil(self, rhs: Self) -> Self { let d = self / rhs; let r = self % rhs; - if r > 0 && rhs > 0 { + if r > 0 { d + 1 } else { d diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs index 56ede02673c03..37c338dd9b778 100644 --- a/library/core/src/panic.rs +++ b/library/core/src/panic.rs @@ -12,7 +12,7 @@ use crate::any::Any; pub use self::location::Location; #[stable(feature = "panic_hooks", since = "1.10.0")] pub use self::panic_info::PanicInfo; -#[unstable(feature = "panic_info_message", issue = "66745")] +#[stable(feature = "panic_info_message", since = "CURRENT_RUSTC_VERSION")] pub use self::panic_info::PanicMessage; #[stable(feature = "catch_unwind", since = "1.9.0")] pub use self::unwind_safe::{AssertUnwindSafe, RefUnwindSafe, UnwindSafe}; diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs index 91953fd656b6a..6bbb9c3017110 100644 --- a/library/core/src/panic/panic_info.rs +++ b/library/core/src/panic/panic_info.rs @@ -24,7 +24,7 @@ pub struct PanicInfo<'a> { /// that were given to the `panic!()` macro. /// /// See [`PanicInfo::message`]. -#[unstable(feature = "panic_info_message", issue = "66745")] +#[stable(feature = "panic_info_message", since = "CURRENT_RUSTC_VERSION")] pub struct PanicMessage<'a> { message: fmt::Arguments<'a>, } @@ -57,7 +57,7 @@ impl<'a> PanicInfo<'a> { /// } /// ``` #[must_use] - #[unstable(feature = "panic_info_message", issue = "66745")] + #[stable(feature = "panic_info_message", since = "CURRENT_RUSTC_VERSION")] pub fn message(&self) -> PanicMessage<'_> { PanicMessage { message: self.message } } @@ -164,7 +164,7 @@ impl<'a> PanicMessage<'a> { /// For most cases with placeholders, this function will return `None`. /// /// See [`fmt::Arguments::as_str`] for details. - #[unstable(feature = "panic_info_message", issue = "66745")] + #[stable(feature = "panic_info_message", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_arguments_as_str", issue = "103900")] #[must_use] #[inline] @@ -173,7 +173,7 @@ impl<'a> PanicMessage<'a> { } } -#[unstable(feature = "panic_info_message", issue = "66745")] +#[stable(feature = "panic_info_message", since = "CURRENT_RUSTC_VERSION")] impl Display for PanicMessage<'_> { #[inline] fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -181,7 +181,7 @@ impl Display for PanicMessage<'_> { } } -#[unstable(feature = "panic_info_message", issue = "66745")] +#[stable(feature = "panic_info_message", since = "CURRENT_RUSTC_VERSION")] impl fmt::Debug for PanicMessage<'_> { #[inline] fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index b1f94caed3513..5537d26669a23 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -112,71 +112,6 @@ impl *const T { self as _ } - /// Casts a pointer to its raw bits. - /// - /// This is equivalent to `as usize`, but is more specific to enhance readability. - /// The inverse method is [`from_bits`](#method.from_bits). - /// - /// In particular, `*p as usize` and `p as usize` will both compile for - /// pointers to numeric types but do very different things, so using this - /// helps emphasize that reading the bits was intentional. - /// - /// # Examples - /// - /// ``` - /// #![feature(ptr_to_from_bits)] - /// # #[cfg(not(miri))] { // doctest does not work with strict provenance - /// let array = [13, 42]; - /// let p0: *const i32 = &array[0]; - /// assert_eq!(<*const _>::from_bits(p0.to_bits()), p0); - /// let p1: *const i32 = &array[1]; - /// assert_eq!(p1.to_bits() - p0.to_bits(), 4); - /// # } - /// ``` - #[unstable(feature = "ptr_to_from_bits", issue = "91126")] - #[deprecated( - since = "1.67.0", - note = "replaced by the `expose_provenance` method, or update your code \ - to follow the strict provenance rules using its APIs" - )] - #[inline(always)] - pub fn to_bits(self) -> usize - where - T: Sized, - { - self as usize - } - - /// Creates a pointer from its raw bits. - /// - /// This is equivalent to `as *const T`, but is more specific to enhance readability. - /// The inverse method is [`to_bits`](#method.to_bits). - /// - /// # Examples - /// - /// ``` - /// #![feature(ptr_to_from_bits)] - /// # #[cfg(not(miri))] { // doctest does not work with strict provenance - /// use std::ptr::NonNull; - /// let dangling: *const u8 = NonNull::dangling().as_ptr(); - /// assert_eq!(<*const u8>::from_bits(1), dangling); - /// # } - /// ``` - #[unstable(feature = "ptr_to_from_bits", issue = "91126")] - #[deprecated( - since = "1.67.0", - note = "replaced by the `ptr::with_exposed_provenance` function, or update \ - your code to follow the strict provenance rules using its APIs" - )] - #[allow(fuzzy_provenance_casts)] // this is an unstable and semi-deprecated cast function - #[inline(always)] - pub fn from_bits(bits: usize) -> Self - where - T: Sized, - { - bits as Self - } - /// Gets the "address" portion of the pointer. /// /// This is similar to `self as usize`, which semantically discards *provenance* and diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 7c685156cbb07..30d5b2cfc5a8b 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -117,72 +117,6 @@ impl *mut T { self as _ } - /// Casts a pointer to its raw bits. - /// - /// This is equivalent to `as usize`, but is more specific to enhance readability. - /// The inverse method is [`from_bits`](pointer#method.from_bits-1). - /// - /// In particular, `*p as usize` and `p as usize` will both compile for - /// pointers to numeric types but do very different things, so using this - /// helps emphasize that reading the bits was intentional. - /// - /// # Examples - /// - /// ``` - /// #![feature(ptr_to_from_bits)] - /// # #[cfg(not(miri))] { // doctest does not work with strict provenance - /// let mut array = [13, 42]; - /// let mut it = array.iter_mut(); - /// let p0: *mut i32 = it.next().unwrap(); - /// assert_eq!(<*mut _>::from_bits(p0.to_bits()), p0); - /// let p1: *mut i32 = it.next().unwrap(); - /// assert_eq!(p1.to_bits() - p0.to_bits(), 4); - /// } - /// ``` - #[unstable(feature = "ptr_to_from_bits", issue = "91126")] - #[deprecated( - since = "1.67.0", - note = "replaced by the `expose_provenance` method, or update your code \ - to follow the strict provenance rules using its APIs" - )] - #[inline(always)] - pub fn to_bits(self) -> usize - where - T: Sized, - { - self as usize - } - - /// Creates a pointer from its raw bits. - /// - /// This is equivalent to `as *mut T`, but is more specific to enhance readability. - /// The inverse method is [`to_bits`](pointer#method.to_bits-1). - /// - /// # Examples - /// - /// ``` - /// #![feature(ptr_to_from_bits)] - /// # #[cfg(not(miri))] { // doctest does not work with strict provenance - /// use std::ptr::NonNull; - /// let dangling: *mut u8 = NonNull::dangling().as_ptr(); - /// assert_eq!(<*mut u8>::from_bits(1), dangling); - /// } - /// ``` - #[unstable(feature = "ptr_to_from_bits", issue = "91126")] - #[deprecated( - since = "1.67.0", - note = "replaced by the `ptr::with_exposed_provenance_mut` function, or \ - update your code to follow the strict provenance rules using its APIs" - )] - #[allow(fuzzy_provenance_casts)] // this is an unstable and semi-deprecated cast function - #[inline(always)] - pub fn from_bits(bits: usize) -> Self - where - T: Sized, - { - bits as Self - } - /// Gets the "address" portion of the pointer. /// /// This is similar to `self as usize`, which semantically discards *provenance* and diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 1d19c985f232b..df108f5e0e4e5 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -3766,7 +3766,7 @@ impl fmt::Debug for AtomicPtr { #[stable(feature = "atomic_pointer", since = "1.24.0")] impl fmt::Pointer for AtomicPtr { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Pointer::fmt(&self.load(Ordering::SeqCst), f) + fmt::Pointer::fmt(&self.load(Ordering::Relaxed), f) } } diff --git a/library/core/src/time.rs b/library/core/src/time.rs index bc0fa3f0968d8..d66f558078ea8 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -620,13 +620,14 @@ impl Duration { /// Basic usage: /// /// ``` - /// #![feature(duration_abs_diff)] /// use std::time::Duration; /// /// assert_eq!(Duration::new(100, 0).abs_diff(Duration::new(80, 0)), Duration::new(20, 0)); /// assert_eq!(Duration::new(100, 400_000_000).abs_diff(Duration::new(110, 0)), Duration::new(9, 600_000_000)); /// ``` - #[unstable(feature = "duration_abs_diff", issue = "117618")] + #[stable(feature = "duration_abs_diff", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "duration_abs_diff", since = "CURRENT_RUSTC_VERSION")] + #[rustc_allow_const_fn_unstable(const_option)] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -842,7 +843,7 @@ impl Duration { /// Returns the number of seconds contained by this `Duration` as `f64`. /// - /// The returned value does include the fractional (nanosecond) part of the duration. + /// The returned value includes the fractional (nanosecond) part of the duration. /// /// # Examples /// ``` @@ -861,7 +862,7 @@ impl Duration { /// Returns the number of seconds contained by this `Duration` as `f32`. /// - /// The returned value does include the fractional (nanosecond) part of the duration. + /// The returned value includes the fractional (nanosecond) part of the duration. /// /// # Examples /// ``` @@ -880,7 +881,7 @@ impl Duration { /// Returns the number of milliseconds contained by this `Duration` as `f64`. /// - /// The returned value does include the fractional (nanosecond) part of the duration. + /// The returned value includes the fractional (nanosecond) part of the duration. /// /// # Examples /// ``` @@ -901,7 +902,7 @@ impl Duration { /// Returns the number of milliseconds contained by this `Duration` as `f32`. /// - /// The returned value does include the fractional (nanosecond) part of the duration. + /// The returned value includes the fractional (nanosecond) part of the duration. /// /// # Examples /// ``` diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 57127df51ebdd..83a615fcd8be3 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -30,7 +30,6 @@ #![feature(core_private_bignum)] #![feature(core_private_diy_float)] #![feature(dec2flt)] -#![feature(duration_abs_diff)] #![feature(duration_consts_float)] #![feature(duration_constants)] #![feature(duration_constructors)] diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 32479cd2836fa..358510b8f77d8 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -100,8 +100,6 @@ test = true [lints.rust.unexpected_cfgs] level = "warn" -# x.py uses beta cargo, so `check-cfg` entries do not yet take effect -# for rust-lang/rust. But for users of `-Zbuild-std` it does. check-cfg = [ 'cfg(bootstrap)', 'cfg(target_arch, values("xtensa"))', diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 27ed2e4137c7e..c8691a9a60922 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -339,7 +339,6 @@ #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_write_slice)] #![feature(panic_can_unwind)] -#![feature(panic_info_message)] #![feature(panic_internals)] #![feature(pointer_is_aligned_to)] #![feature(portable_simd)] diff --git a/library/std/src/sys/thread_local/guard/key.rs b/library/std/src/sys/thread_local/guard/key.rs index ee9d55ddd5e8e..67c3ca8862767 100644 --- a/library/std/src/sys/thread_local/guard/key.rs +++ b/library/std/src/sys/thread_local/guard/key.rs @@ -4,15 +4,15 @@ use crate::ptr; use crate::sys::thread_local::destructors; -use crate::sys::thread_local::key::StaticKey; +use crate::sys::thread_local::key::{set, LazyKey}; pub fn enable() { - static DTORS: StaticKey = StaticKey::new(Some(run)); + static DTORS: LazyKey = LazyKey::new(Some(run)); // Setting the key value to something other than NULL will result in the // destructor being run at thread exit. unsafe { - DTORS.set(ptr::without_provenance_mut(1)); + set(DTORS.force(), ptr::without_provenance_mut(1)); } unsafe extern "C" fn run(_: *mut u8) { diff --git a/library/std/src/sys/thread_local/key/racy.rs b/library/std/src/sys/thread_local/key/racy.rs index eda8b83bc7f03..69f11458c3289 100644 --- a/library/std/src/sys/thread_local/key/racy.rs +++ b/library/std/src/sys/thread_local/key/racy.rs @@ -1,4 +1,4 @@ -//! A `StaticKey` implementation using racy initialization. +//! A `LazyKey` implementation using racy initialization. //! //! Unfortunately, none of the platforms currently supported by `std` allows //! creating TLS keys at compile-time. Thus we need a way to lazily create keys. @@ -10,34 +10,12 @@ use crate::sync::atomic::{self, AtomicUsize, Ordering}; /// A type for TLS keys that are statically allocated. /// -/// This type is entirely `unsafe` to use as it does not protect against -/// use-after-deallocation or use-during-deallocation. -/// -/// The actual OS-TLS key is lazily allocated when this is used for the first -/// time. The key is also deallocated when the Rust runtime exits or `destroy` -/// is called, whichever comes first. -/// -/// # Examples -/// -/// ```ignore (cannot-doctest-private-modules) -/// use tls::os::{StaticKey, INIT}; -/// -/// // Use a regular global static to store the key. -/// static KEY: StaticKey = INIT; -/// -/// // The state provided via `get` and `set` is thread-local. -/// unsafe { -/// assert!(KEY.get().is_null()); -/// KEY.set(1 as *mut u8); -/// } -/// ``` -pub struct StaticKey { +/// This is basically a `LazyLock`, but avoids blocking and circular +/// dependencies with the rest of `std`. +pub struct LazyKey { /// Inner static TLS key (internals). key: AtomicUsize, /// Destructor for the TLS value. - /// - /// See `Key::new` for information about when the destructor runs and how - /// it runs. dtor: Option, } @@ -51,32 +29,14 @@ const KEY_SENTVAL: usize = 0; #[cfg(target_os = "nto")] const KEY_SENTVAL: usize = libc::PTHREAD_KEYS_MAX + 1; -impl StaticKey { +impl LazyKey { #[rustc_const_unstable(feature = "thread_local_internals", issue = "none")] - pub const fn new(dtor: Option) -> StaticKey { - StaticKey { key: atomic::AtomicUsize::new(KEY_SENTVAL), dtor } - } - - /// Gets the value associated with this TLS key - /// - /// This will lazily allocate a TLS key from the OS if one has not already - /// been allocated. - #[inline] - pub unsafe fn get(&self) -> *mut u8 { - unsafe { super::get(self.key()) } - } - - /// Sets this TLS key to a new value. - /// - /// This will lazily allocate a TLS key from the OS if one has not already - /// been allocated. - #[inline] - pub unsafe fn set(&self, val: *mut u8) { - unsafe { super::set(self.key(), val) } + pub const fn new(dtor: Option) -> LazyKey { + LazyKey { key: atomic::AtomicUsize::new(KEY_SENTVAL), dtor } } #[inline] - fn key(&self) -> super::Key { + pub fn force(&self) -> super::Key { match self.key.load(Ordering::Acquire) { KEY_SENTVAL => self.lazy_init() as super::Key, n => n as super::Key, diff --git a/library/std/src/sys/thread_local/key/tests.rs b/library/std/src/sys/thread_local/key/tests.rs index 24cad396da269..d82b34e71f0e4 100644 --- a/library/std/src/sys/thread_local/key/tests.rs +++ b/library/std/src/sys/thread_local/key/tests.rs @@ -1,18 +1,25 @@ -use super::StaticKey; +use super::{get, set, LazyKey}; use crate::ptr; #[test] fn smoke() { - static K1: StaticKey = StaticKey::new(None); - static K2: StaticKey = StaticKey::new(None); + static K1: LazyKey = LazyKey::new(None); + static K2: LazyKey = LazyKey::new(None); + + let k1 = K1.force(); + let k2 = K2.force(); + assert_ne!(k1, k2); + + assert_eq!(K1.force(), k1); + assert_eq!(K2.force(), k2); unsafe { - assert!(K1.get().is_null()); - assert!(K2.get().is_null()); - K1.set(ptr::without_provenance_mut(1)); - K2.set(ptr::without_provenance_mut(2)); - assert_eq!(K1.get() as usize, 1); - assert_eq!(K2.get() as usize, 2); + assert!(get(k1).is_null()); + assert!(get(k2).is_null()); + set(k1, ptr::without_provenance_mut(1)); + set(k2, ptr::without_provenance_mut(2)); + assert_eq!(get(k1) as usize, 1); + assert_eq!(get(k2) as usize, 2); } } @@ -26,25 +33,27 @@ fn destructors() { drop(unsafe { Arc::from_raw(ptr as *const ()) }); } - static KEY: StaticKey = StaticKey::new(Some(destruct)); + static KEY: LazyKey = LazyKey::new(Some(destruct)); let shared1 = Arc::new(()); let shared2 = Arc::clone(&shared1); + let key = KEY.force(); unsafe { - assert!(KEY.get().is_null()); - KEY.set(Arc::into_raw(shared1) as *mut u8); + assert!(get(key).is_null()); + set(key, Arc::into_raw(shared1) as *mut u8); } thread::spawn(move || unsafe { - assert!(KEY.get().is_null()); - KEY.set(Arc::into_raw(shared2) as *mut u8); + let key = KEY.force(); + assert!(get(key).is_null()); + set(key, Arc::into_raw(shared2) as *mut u8); }) .join() .unwrap(); // Leak the Arc, let the TLS destructor clean it up. - let shared1 = unsafe { ManuallyDrop::new(Arc::from_raw(KEY.get() as *const ())) }; + let shared1 = unsafe { ManuallyDrop::new(Arc::from_raw(get(key) as *const ())) }; assert_eq!( Arc::strong_count(&shared1), 1, diff --git a/library/std/src/sys/thread_local/key/unix.rs b/library/std/src/sys/thread_local/key/unix.rs index 13522d44b35dc..28e48a750b9bf 100644 --- a/library/std/src/sys/thread_local/key/unix.rs +++ b/library/std/src/sys/thread_local/key/unix.rs @@ -16,6 +16,7 @@ pub unsafe fn set(key: Key, value: *mut u8) { } #[inline] +#[cfg(any(not(target_thread_local), test))] pub unsafe fn get(key: Key) -> *mut u8 { unsafe { libc::pthread_getspecific(key) as *mut u8 } } diff --git a/library/std/src/sys/thread_local/key/windows.rs b/library/std/src/sys/thread_local/key/windows.rs index ad0e72c29edaf..baf23979c7c61 100644 --- a/library/std/src/sys/thread_local/key/windows.rs +++ b/library/std/src/sys/thread_local/key/windows.rs @@ -1,4 +1,4 @@ -//! Implementation of `StaticKey` for Windows. +//! Implementation of `LazyKey` for Windows. //! //! Windows has no native support for running destructors so we manage our own //! list of destructors to keep track of how to destroy keys. We then install a @@ -13,9 +13,9 @@ //! don't reach a fixed point after a short while then we just inevitably leak //! something. //! -//! The list is implemented as an atomic single-linked list of `StaticKey`s and +//! The list is implemented as an atomic single-linked list of `LazyKey`s and //! does not support unregistration. Unfortunately, this means that we cannot -//! use racy initialization for creating the keys in `StaticKey`, as that could +//! use racy initialization for creating the keys in `LazyKey`, as that could //! result in destructors being missed. Hence, we synchronize the creation of //! keys with destructors through [`INIT_ONCE`](c::INIT_ONCE) (`std`'s //! [`Once`](crate::sync::Once) cannot be used since it might use TLS itself). @@ -33,26 +33,26 @@ use crate::sync::atomic::{ use crate::sys::c; use crate::sys::thread_local::guard; -type Key = c::DWORD; +pub type Key = c::DWORD; type Dtor = unsafe extern "C" fn(*mut u8); -pub struct StaticKey { +pub struct LazyKey { /// The key value shifted up by one. Since TLS_OUT_OF_INDEXES == DWORD::MAX /// is not a valid key value, this allows us to use zero as sentinel value /// without risking overflow. key: AtomicU32, dtor: Option, - next: AtomicPtr, + next: AtomicPtr, /// Currently, destructors cannot be unregistered, so we cannot use racy /// initialization for keys. Instead, we need synchronize initialization. /// Use the Windows-provided `Once` since it does not require TLS. once: UnsafeCell, } -impl StaticKey { +impl LazyKey { #[inline] - pub const fn new(dtor: Option) -> StaticKey { - StaticKey { + pub const fn new(dtor: Option) -> LazyKey { + LazyKey { key: AtomicU32::new(0), dtor, next: AtomicPtr::new(ptr::null_mut()), @@ -61,18 +61,7 @@ impl StaticKey { } #[inline] - pub unsafe fn set(&'static self, val: *mut u8) { - let r = unsafe { c::TlsSetValue(self.key(), val.cast()) }; - debug_assert_eq!(r, c::TRUE); - } - - #[inline] - pub unsafe fn get(&'static self) -> *mut u8 { - unsafe { c::TlsGetValue(self.key()).cast() } - } - - #[inline] - fn key(&'static self) -> Key { + pub fn force(&'static self) -> Key { match self.key.load(Acquire) { 0 => unsafe { self.init() }, key => key - 1, @@ -141,17 +130,28 @@ impl StaticKey { } } -unsafe impl Send for StaticKey {} -unsafe impl Sync for StaticKey {} +unsafe impl Send for LazyKey {} +unsafe impl Sync for LazyKey {} + +#[inline] +pub unsafe fn set(key: Key, val: *mut u8) { + let r = unsafe { c::TlsSetValue(key, val.cast()) }; + debug_assert_eq!(r, c::TRUE); +} + +#[inline] +pub unsafe fn get(key: Key) -> *mut u8 { + unsafe { c::TlsGetValue(key).cast() } +} -static DTORS: AtomicPtr = AtomicPtr::new(ptr::null_mut()); +static DTORS: AtomicPtr = AtomicPtr::new(ptr::null_mut()); /// Should only be called once per key, otherwise loops or breaks may occur in /// the linked list. -unsafe fn register_dtor(key: &'static StaticKey) { +unsafe fn register_dtor(key: &'static LazyKey) { guard::enable(); - let this = <*const StaticKey>::cast_mut(key); + let this = <*const LazyKey>::cast_mut(key); // Use acquire ordering to pass along the changes done by the previously // registered keys when we store the new head with release ordering. let mut head = DTORS.load(Acquire); @@ -176,9 +176,9 @@ pub unsafe fn run_dtors() { let dtor = unsafe { (*cur).dtor.unwrap() }; cur = unsafe { (*cur).next.load(Relaxed) }; - // In StaticKey::init, we register the dtor before setting `key`. + // In LazyKey::init, we register the dtor before setting `key`. // So if one thread's `run_dtors` races with another thread executing `init` on the same - // `StaticKey`, we can encounter a key of 0 here. That means this key was never + // `LazyKey`, we can encounter a key of 0 here. That means this key was never // initialized in this thread so we can safely skip it. if pre_key == 0 { continue; diff --git a/library/std/src/sys/thread_local/key/xous.rs b/library/std/src/sys/thread_local/key/xous.rs index a23f6de95f7b5..5a837a33e190e 100644 --- a/library/std/src/sys/thread_local/key/xous.rs +++ b/library/std/src/sys/thread_local/key/xous.rs @@ -30,7 +30,7 @@ //! really. //! //! Perhaps one day we can fold the `Box` here into a static allocation, -//! expanding the `StaticKey` structure to contain not only a slot for the TLS +//! expanding the `LazyKey` structure to contain not only a slot for the TLS //! key but also a slot for the destructor queue on windows. An optimization for //! another day! diff --git a/library/std/src/sys/thread_local/mod.rs b/library/std/src/sys/thread_local/mod.rs index f74fd828cbe50..3d1b91a7ea095 100644 --- a/library/std/src/sys/thread_local/mod.rs +++ b/library/std/src/sys/thread_local/mod.rs @@ -36,7 +36,7 @@ cfg_if::cfg_if! { pub use native::{EagerStorage, LazyStorage, thread_local_inner}; } else { mod os; - pub use os::{Key, thread_local_inner}; + pub use os::{Storage, thread_local_inner}; } } @@ -126,28 +126,33 @@ pub(crate) mod key { mod unix; #[cfg(test)] mod tests; - pub(super) use racy::StaticKey; - use unix::{Key, create, destroy, get, set}; + pub(super) use racy::LazyKey; + pub(super) use unix::{Key, set}; + #[cfg(any(not(target_thread_local), test))] + pub(super) use unix::get; + use unix::{create, destroy}; } else if #[cfg(all(not(target_thread_local), target_os = "windows"))] { #[cfg(test)] mod tests; mod windows; - pub(super) use windows::{StaticKey, run_dtors}; + pub(super) use windows::{Key, LazyKey, get, run_dtors, set}; } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] { mod racy; mod sgx; #[cfg(test)] mod tests; - pub(super) use racy::StaticKey; - use sgx::{Key, create, destroy, get, set}; + pub(super) use racy::LazyKey; + pub(super) use sgx::{Key, get, set}; + use sgx::{create, destroy}; } else if #[cfg(target_os = "xous")] { mod racy; #[cfg(test)] mod tests; mod xous; - pub(super) use racy::StaticKey; + pub(super) use racy::LazyKey; pub(crate) use xous::destroy_tls; - use xous::{Key, create, destroy, get, set}; + pub(super) use xous::{Key, get, set}; + use xous::{create, destroy}; } } } diff --git a/library/std/src/sys/thread_local/os.rs b/library/std/src/sys/thread_local/os.rs index 6980c897fdb53..e06185f00690b 100644 --- a/library/std/src/sys/thread_local/os.rs +++ b/library/std/src/sys/thread_local/os.rs @@ -2,7 +2,7 @@ use super::abort_on_dtor_unwind; use crate::cell::Cell; use crate::marker::PhantomData; use crate::ptr; -use crate::sys::thread_local::key::StaticKey as OsKey; +use crate::sys::thread_local::key::{get, set, Key, LazyKey}; #[doc(hidden)] #[allow_internal_unstable(thread_local_internals)] @@ -22,12 +22,12 @@ pub macro thread_local_inner { unsafe { use $crate::thread::LocalKey; - use $crate::thread::local_impl::Key; + use $crate::thread::local_impl::Storage; // Inlining does not work on windows-gnu due to linking errors around // dllimports. See https://github.com/rust-lang/rust/issues/109797. LocalKey::new(#[cfg_attr(windows, inline(never))] |init| { - static VAL: Key<$t> = Key::new(); + static VAL: Storage<$t> = Storage::new(); VAL.get(init, __init) }) } @@ -41,22 +41,23 @@ pub macro thread_local_inner { /// Use a regular global static to store this key; the state provided will then be /// thread-local. #[allow(missing_debug_implementations)] -pub struct Key { - os: OsKey, +pub struct Storage { + key: LazyKey, marker: PhantomData>, } -unsafe impl Sync for Key {} +unsafe impl Sync for Storage {} struct Value { value: T, - key: &'static Key, + // INVARIANT: if this value is stored under a TLS key, `key` must be that `key`. + key: Key, } -impl Key { +impl Storage { #[rustc_const_unstable(feature = "thread_local_internals", issue = "none")] - pub const fn new() -> Key { - Key { os: OsKey::new(Some(destroy_value::)), marker: PhantomData } + pub const fn new() -> Storage { + Storage { key: LazyKey::new(Some(destroy_value::)), marker: PhantomData } } /// Get a pointer to the TLS value, potentially initializing it with the @@ -66,19 +67,23 @@ impl Key { /// The resulting pointer may not be used after reentrant inialialization /// or thread destruction has occurred. pub fn get(&'static self, i: Option<&mut Option>, f: impl FnOnce() -> T) -> *const T { - // SAFETY: (FIXME: get should actually be safe) - let ptr = unsafe { self.os.get() as *mut Value }; + let key = self.key.force(); + let ptr = unsafe { get(key) as *mut Value }; if ptr.addr() > 1 { // SAFETY: the check ensured the pointer is safe (its destructor // is not running) + it is coming from a trusted source (self). unsafe { &(*ptr).value } } else { - self.try_initialize(ptr, i, f) + // SAFETY: trivially correct. + unsafe { Self::try_initialize(key, ptr, i, f) } } } - fn try_initialize( - &'static self, + /// # Safety + /// * `key` must be the result of calling `self.key.force()` + /// * `ptr` must be the current value associated with `key`. + unsafe fn try_initialize( + key: Key, ptr: *mut Value, i: Option<&mut Option>, f: impl FnOnce() -> T, @@ -88,14 +93,19 @@ impl Key { return ptr::null(); } - let value = i.and_then(Option::take).unwrap_or_else(f); - let ptr = Box::into_raw(Box::new(Value { value, key: self })); - // SAFETY: (FIXME: get should actually be safe) - let old = unsafe { self.os.get() as *mut Value }; - // SAFETY: `ptr` is a correct pointer that can be destroyed by the key destructor. - unsafe { - self.os.set(ptr as *mut u8); - } + let value = Box::new(Value { value: i.and_then(Option::take).unwrap_or_else(f), key }); + let ptr = Box::into_raw(value); + + // SAFETY: + // * key came from a `LazyKey` and is thus correct. + // * `ptr` is a correct pointer that can be destroyed by the key destructor. + // * the value is stored under the key that it contains. + let old = unsafe { + let old = get(key) as *mut Value; + set(key, ptr as *mut u8); + old + }; + if !old.is_null() { // If the variable was recursively initialized, drop the old value. // SAFETY: We cannot be inside a `LocalKey::with` scope, as the @@ -123,8 +133,10 @@ unsafe extern "C" fn destroy_value(ptr: *mut u8) { abort_on_dtor_unwind(|| { let ptr = unsafe { Box::from_raw(ptr as *mut Value) }; let key = ptr.key; - unsafe { key.os.set(ptr::without_provenance_mut(1)) }; + // SAFETY: `key` is the TLS key `ptr` was stored under. + unsafe { set(key, ptr::without_provenance_mut(1)) }; drop(ptr); - unsafe { key.os.set(ptr::null_mut()) }; + // SAFETY: `key` is the TLS key `ptr` was stored under. + unsafe { set(key, ptr::null_mut()) }; }); } diff --git a/src/bootstrap/src/bin/rustc.rs b/src/bootstrap/src/bin/rustc.rs index d227419917767..009e62469b4d1 100644 --- a/src/bootstrap/src/bin/rustc.rs +++ b/src/bootstrap/src/bin/rustc.rs @@ -20,26 +20,24 @@ use std::path::{Path, PathBuf}; use std::process::{Child, Command}; use std::time::Instant; -use dylib_util::{dylib_path, dylib_path_var, exe}; +use shared_helpers::{ + dylib_path, dylib_path_var, exe, maybe_dump, parse_rustc_stage, parse_rustc_verbose, + parse_value_from_args, +}; -#[path = "../utils/bin_helpers.rs"] -mod bin_helpers; - -#[path = "../utils/dylib.rs"] -mod dylib_util; +#[path = "../utils/shared_helpers.rs"] +mod shared_helpers; fn main() { let orig_args = env::args_os().skip(1).collect::>(); let mut args = orig_args.clone(); - let arg = - |name| orig_args.windows(2).find(|args| args[0] == name).and_then(|args| args[1].to_str()); - let stage = bin_helpers::parse_rustc_stage(); - let verbose = bin_helpers::parse_rustc_verbose(); + let stage = parse_rustc_stage(); + let verbose = parse_rustc_verbose(); // Detect whether or not we're a build script depending on whether --target // is passed (a bit janky...) - let target = arg("--target"); + let target = parse_value_from_args(&orig_args, "--target"); let version = args.iter().find(|w| &**w == "-vV"); // Use a different compiler for build scripts, since there may not yet be a @@ -102,7 +100,7 @@ fn main() { cmd.args(&args).env(dylib_path_var(), env::join_paths(&dylib_path).unwrap()); // Get the name of the crate we're compiling, if any. - let crate_name = arg("--crate-name"); + let crate_name = parse_value_from_args(&orig_args, "--crate-name"); if let Some(crate_name) = crate_name { if let Some(target) = env::var_os("RUSTC_TIME") { @@ -143,10 +141,11 @@ fn main() { cmd.arg("-C").arg("panic=abort"); } + let crate_type = parse_value_from_args(&orig_args, "--crate-type"); // `-Ztls-model=initial-exec` must not be applied to proc-macros, see // issue https://github.com/rust-lang/rust/issues/100530 if env::var("RUSTC_TLS_MODEL_INITIAL_EXEC").is_ok() - && arg("--crate-type") != Some("proc-macro") + && crate_type != Some("proc-macro") && !matches!(crate_name, Some("proc_macro2" | "quote" | "syn" | "synstructure")) { cmd.arg("-Ztls-model=initial-exec"); @@ -251,7 +250,7 @@ fn main() { eprintln!("{prefix} libdir: {libdir:?}"); } - bin_helpers::maybe_dump(format!("stage{stage}-rustc"), &cmd); + maybe_dump(format!("stage{stage}-rustc"), &cmd); let start = Instant::now(); let (child, status) = { diff --git a/src/bootstrap/src/bin/rustdoc.rs b/src/bootstrap/src/bin/rustdoc.rs index b4d1415189cfa..ba6b0c2dbdad7 100644 --- a/src/bootstrap/src/bin/rustdoc.rs +++ b/src/bootstrap/src/bin/rustdoc.rs @@ -6,19 +6,19 @@ use std::env; use std::path::PathBuf; use std::process::Command; -use dylib_util::{dylib_path, dylib_path_var}; +use shared_helpers::{ + dylib_path, dylib_path_var, maybe_dump, parse_rustc_stage, parse_rustc_verbose, + parse_value_from_args, +}; -#[path = "../utils/bin_helpers.rs"] -mod bin_helpers; - -#[path = "../utils/dylib.rs"] -mod dylib_util; +#[path = "../utils/shared_helpers.rs"] +mod shared_helpers; fn main() { let args = env::args_os().skip(1).collect::>(); - let stage = bin_helpers::parse_rustc_stage(); - let verbose = bin_helpers::parse_rustc_verbose(); + let stage = parse_rustc_stage(); + let verbose = parse_rustc_verbose(); let rustdoc = env::var_os("RUSTDOC_REAL").expect("RUSTDOC_REAL was not set"); let libdir = env::var_os("RUSTDOC_LIBDIR").expect("RUSTDOC_LIBDIR was not set"); @@ -26,7 +26,7 @@ fn main() { // Detect whether or not we're a build script depending on whether --target // is passed (a bit janky...) - let target = args.windows(2).find(|w| &*w[0] == "--target").and_then(|w| w[1].to_str()); + let target = parse_value_from_args(&args, "--target"); let mut dylib_path = dylib_path(); dylib_path.insert(0, PathBuf::from(libdir.clone())); @@ -62,7 +62,7 @@ fn main() { cmd.arg("-Zunstable-options"); cmd.arg("--check-cfg=cfg(bootstrap)"); - bin_helpers::maybe_dump(format!("stage{stage}-rustdoc"), &cmd); + maybe_dump(format!("stage{stage}-rustdoc"), &cmd); if verbose > 1 { eprintln!( diff --git a/src/bootstrap/src/core/build_steps/clean.rs b/src/bootstrap/src/core/build_steps/clean.rs index a81d640301363..479af4af66665 100644 --- a/src/bootstrap/src/core/build_steps/clean.rs +++ b/src/bootstrap/src/core/build_steps/clean.rs @@ -85,7 +85,7 @@ macro_rules! clean_crate_tree { // NOTE: doesn't use `run_cargo` because we don't want to save a stamp file, // and doesn't use `stream_cargo` to avoid passing `--message-format` which `clean` doesn't accept. - builder.run(&mut cargo); + builder.run(cargo); } } )+ } diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 5b18cb3f7e1e6..de3b938e42731 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -27,6 +27,7 @@ use crate::core::builder::crate_description; use crate::core::builder::Cargo; use crate::core::builder::{Builder, Kind, PathSet, RunConfig, ShouldRun, Step, TaskPath}; use crate::core::config::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection}; +use crate::utils::exec::BootstrapCommand; use crate::utils::helpers::{ exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, output, symlink_dir, t, up_to_date, }; @@ -160,9 +161,10 @@ impl Step for Std { // This check is specific to testing std itself; see `test::Std` for more details. && !self.force_recompile { + let sysroot = builder.ensure(Sysroot { compiler, force_recompile: false }); cp_rustc_component_to_ci_sysroot( builder, - compiler, + &sysroot, builder.config.ci_rust_std_contents(), ); return; @@ -771,7 +773,7 @@ impl Step for StartupObjects { let src_file = &src_dir.join(file.to_string() + ".rs"); let dst_file = &dst_dir.join(file.to_string() + ".o"); if !up_to_date(src_file, dst_file) { - let mut cmd = Command::new(&builder.initial_rustc); + let mut cmd = BootstrapCommand::new(&builder.initial_rustc); cmd.env("RUSTC_BOOTSTRAP", "1"); if !builder.local_rebuild { // a local_rebuild compiler already has stage1 features @@ -796,12 +798,7 @@ impl Step for StartupObjects { } } -fn cp_rustc_component_to_ci_sysroot( - builder: &Builder<'_>, - compiler: Compiler, - contents: Vec, -) { - let sysroot = builder.ensure(Sysroot { compiler, force_recompile: false }); +fn cp_rustc_component_to_ci_sysroot(builder: &Builder<'_>, sysroot: &Path, contents: Vec) { let ci_rustc_dir = builder.config.ci_rustc_dir(); for file in contents { @@ -880,13 +877,7 @@ impl Step for Rustc { // NOTE: the ABI of the beta compiler is different from the ABI of the downloaded compiler, // so its artifacts can't be reused. if builder.download_rustc() && compiler.stage != 0 { - // Copy the existing artifacts instead of rebuilding them. - // NOTE: this path is only taken for tools linking to rustc-dev (including ui-fulldeps tests). - cp_rustc_component_to_ci_sysroot( - builder, - compiler, - builder.config.ci_rustc_dev_contents(), - ); + builder.ensure(Sysroot { compiler, force_recompile: false }); return compiler.stage; } @@ -1633,31 +1624,44 @@ impl Step for Sysroot { let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust"); if let Err(e) = symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust) { eprintln!( - "WARNING: creating symbolic link `{}` to `{}` failed with {}", + "ERROR: creating symbolic link `{}` to `{}` failed with {}", sysroot_lib_rustlib_src_rust.display(), builder.src.display(), e, ); if builder.config.rust_remap_debuginfo { eprintln!( - "WARNING: some `tests/ui` tests will fail when lacking `{}`", + "ERROR: some `tests/ui` tests will fail when lacking `{}`", sysroot_lib_rustlib_src_rust.display(), ); } + build_helper::exit!(1); } - // Same for the rustc-src component. - let sysroot_lib_rustlib_rustcsrc = sysroot.join("lib/rustlib/rustc-src"); - t!(fs::create_dir_all(&sysroot_lib_rustlib_rustcsrc)); - let sysroot_lib_rustlib_rustcsrc_rust = sysroot_lib_rustlib_rustcsrc.join("rust"); - if let Err(e) = - symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_rustcsrc_rust) - { - eprintln!( - "WARNING: creating symbolic link `{}` to `{}` failed with {}", - sysroot_lib_rustlib_rustcsrc_rust.display(), - builder.src.display(), - e, + + // Unlike rust-src component, we have to handle rustc-src a bit differently. + // When using CI rustc, we copy rustc-src component from its sysroot, + // otherwise we handle it in a similar way what we do for rust-src above. + if builder.download_rustc() { + cp_rustc_component_to_ci_sysroot( + builder, + &sysroot, + builder.config.ci_rustc_dev_contents(), ); + } else { + let sysroot_lib_rustlib_rustcsrc = sysroot.join("lib/rustlib/rustc-src"); + t!(fs::create_dir_all(&sysroot_lib_rustlib_rustcsrc)); + let sysroot_lib_rustlib_rustcsrc_rust = sysroot_lib_rustlib_rustcsrc.join("rust"); + if let Err(e) = + symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_rustcsrc_rust) + { + eprintln!( + "ERROR: creating symbolic link `{}` to `{}` failed with {}", + sysroot_lib_rustlib_rustcsrc_rust.display(), + builder.src.display(), + e, + ); + build_helper::exit!(1); + } } sysroot @@ -2076,7 +2080,7 @@ pub fn stream_cargo( tail_args: Vec, cb: &mut dyn FnMut(CargoMessage<'_>), ) -> bool { - let mut cargo = Command::from(cargo); + let mut cargo = BootstrapCommand::from(cargo).command; // Instruct Cargo to give us json messages on stdout, critically leaving // stderr as piped so we can get those pretty colors. let mut message_format = if builder.config.json_output { diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 0f24e91d81d60..08795efe5bb4c 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -26,6 +26,7 @@ use crate::core::build_steps::tool::{self, Tool}; use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step}; use crate::core::config::TargetSelection; use crate::utils::channel::{self, Info}; +use crate::utils::exec::BootstrapCommand; use crate::utils::helpers::{ exe, is_dylib, move_file, output, t, target_supports_cranelift_backend, timeit, }; @@ -1599,14 +1600,14 @@ impl Step for Extended { let _ = fs::remove_dir_all(&pkg); let pkgbuild = |component: &str| { - let mut cmd = Command::new("pkgbuild"); + let mut cmd = BootstrapCommand::new("pkgbuild"); cmd.arg("--identifier") .arg(format!("org.rust-lang.{}", component)) .arg("--scripts") .arg(pkg.join(component)) .arg("--nopayload") .arg(pkg.join(component).with_extension("pkg")); - builder.run(&mut cmd); + builder.run(cmd); }; let prepare = |name: &str| { @@ -1636,7 +1637,7 @@ impl Step for Extended { builder.create_dir(&pkg.join("res")); builder.create(&pkg.join("res/LICENSE.txt"), &license); builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), 0o644); - let mut cmd = Command::new("productbuild"); + let mut cmd = BootstrapCommand::new("productbuild"); cmd.arg("--distribution") .arg(xform(&etc.join("pkg/Distribution.xml"))) .arg("--resources") @@ -1649,7 +1650,7 @@ impl Step for Extended { .arg("--package-path") .arg(&pkg); let _time = timeit(builder); - builder.run(&mut cmd); + builder.run(cmd); } if target.is_windows() { @@ -1704,7 +1705,7 @@ impl Step for Extended { let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"]; builder.run( - Command::new(&heat) + BootstrapCommand::new(&heat) .current_dir(&exe) .arg("dir") .arg("rustc") @@ -1720,7 +1721,7 @@ impl Step for Extended { ); if built_tools.contains("rust-docs") { builder.run( - Command::new(&heat) + BootstrapCommand::new(&heat) .current_dir(&exe) .arg("dir") .arg("rust-docs") @@ -1738,7 +1739,7 @@ impl Step for Extended { ); } builder.run( - Command::new(&heat) + BootstrapCommand::new(&heat) .current_dir(&exe) .arg("dir") .arg("cargo") @@ -1755,7 +1756,7 @@ impl Step for Extended { .arg(etc.join("msi/remove-duplicates.xsl")), ); builder.run( - Command::new(&heat) + BootstrapCommand::new(&heat) .current_dir(&exe) .arg("dir") .arg("rust-std") @@ -1771,7 +1772,7 @@ impl Step for Extended { ); if built_tools.contains("rust-analyzer") { builder.run( - Command::new(&heat) + BootstrapCommand::new(&heat) .current_dir(&exe) .arg("dir") .arg("rust-analyzer") @@ -1790,7 +1791,7 @@ impl Step for Extended { } if built_tools.contains("clippy") { builder.run( - Command::new(&heat) + BootstrapCommand::new(&heat) .current_dir(&exe) .arg("dir") .arg("clippy") @@ -1809,7 +1810,7 @@ impl Step for Extended { } if built_tools.contains("miri") { builder.run( - Command::new(&heat) + BootstrapCommand::new(&heat) .current_dir(&exe) .arg("dir") .arg("miri") @@ -1827,7 +1828,7 @@ impl Step for Extended { ); } builder.run( - Command::new(&heat) + BootstrapCommand::new(&heat) .current_dir(&exe) .arg("dir") .arg("rust-analysis") @@ -1845,7 +1846,7 @@ impl Step for Extended { ); if target.ends_with("windows-gnu") { builder.run( - Command::new(&heat) + BootstrapCommand::new(&heat) .current_dir(&exe) .arg("dir") .arg("rust-mingw") @@ -1864,7 +1865,7 @@ impl Step for Extended { let candle = |input: &Path| { let output = exe.join(input.file_stem().unwrap()).with_extension("wixobj"); let arch = if target.contains("x86_64") { "x64" } else { "x86" }; - let mut cmd = Command::new(&candle); + let mut cmd = BootstrapCommand::new(&candle); cmd.current_dir(&exe) .arg("-nologo") .arg("-dRustcDir=rustc") @@ -1893,7 +1894,7 @@ impl Step for Extended { if target.ends_with("windows-gnu") { cmd.arg("-dGccDir=rust-mingw"); } - builder.run(&mut cmd); + builder.run(cmd); }; candle(&xform(&etc.join("msi/rust.wxs"))); candle(&etc.join("msi/ui.wxs")); @@ -1925,7 +1926,7 @@ impl Step for Extended { builder.info(&format!("building `msi` installer with {light:?}")); let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple); - let mut cmd = Command::new(&light); + let mut cmd = BootstrapCommand::new(&light); cmd.arg("-nologo") .arg("-ext") .arg("WixUIExtension") @@ -1962,7 +1963,7 @@ impl Step for Extended { cmd.arg("-sice:ICE57"); let _time = timeit(builder); - builder.run(&mut cmd); + builder.run(cmd); if !builder.config.dry_run() { t!(move_file(exe.join(&filename), distdir(builder).join(&filename))); @@ -1971,7 +1972,7 @@ impl Step for Extended { } } -fn add_env(builder: &Builder<'_>, cmd: &mut Command, target: TargetSelection) { +fn add_env(builder: &Builder<'_>, cmd: &mut BootstrapCommand, target: TargetSelection) { let mut parts = builder.version.split('.'); cmd.env("CFG_RELEASE_INFO", builder.rust_version()) .env("CFG_RELEASE_NUM", &builder.version) diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 87c700dad063d..4a5af25b3b2f8 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -249,6 +249,7 @@ impl Step for TheBook { let shared_assets = builder.ensure(SharedAssets { target }); // build the command first so we don't nest GHA groups + // FIXME: this doesn't do anything! builder.rustdoc_cmd(compiler); // build the redirect pages @@ -300,7 +301,7 @@ fn invoke_rustdoc( cmd.arg("-Z").arg("unstable-options").arg("--disable-minification"); } - builder.run(&mut cmd); + builder.run(cmd); } #[derive(Debug, Clone, Hash, PartialEq, Eq)] @@ -394,7 +395,7 @@ impl Step for Standalone { } else { cmd.arg("--markdown-css").arg("rust.css"); } - builder.run(&mut cmd); + builder.run(cmd); } // We open doc/index.html as the default if invoked as `x.py doc --open` @@ -493,7 +494,7 @@ impl Step for Releases { cmd.arg("--disable-minification"); } - builder.run(&mut cmd); + builder.run(cmd); } // We open doc/RELEASES.html as the default if invoked as `x.py doc --open RELEASES.md` @@ -737,7 +738,7 @@ fn doc_std( format!("library{} in {} format", crate_description(requested_crates), format.as_str()); let _guard = builder.msg_doc(compiler, description, target); - builder.run(&mut cargo.into()); + builder.run(cargo); builder.cp_link_r(&out_dir, out); } @@ -862,7 +863,7 @@ impl Step for Rustc { let proc_macro_out_dir = builder.stage_out(compiler, Mode::Rustc).join("doc"); symlink_dir_force(&builder.config, &out, &proc_macro_out_dir); - builder.run(&mut cargo.into()); + builder.run(cargo); if !builder.config.dry_run() { // Sanity check on linked compiler crates @@ -995,7 +996,7 @@ macro_rules! tool_doc { symlink_dir_force(&builder.config, &out, &proc_macro_out_dir); let _guard = builder.msg_doc(compiler, stringify!($tool).to_lowercase(), target); - builder.run(&mut cargo.into()); + builder.run(cargo); if !builder.config.dry_run() { // Sanity check on linked doc directories @@ -1079,7 +1080,7 @@ impl Step for ErrorIndex { index.arg(out); index.arg(&builder.version); - builder.run(&mut index); + builder.run(index); } } @@ -1115,7 +1116,7 @@ impl Step for UnstableBookGen { cmd.arg(builder.src.join("src")); cmd.arg(out); - builder.run(&mut cmd); + builder.run(cmd); } } @@ -1210,7 +1211,7 @@ impl Step for RustcBook { self.compiler.host, self.target, ); - builder.run(&mut cmd); + builder.run(cmd); drop(doc_generator_guard); // Run rustbook/mdbook to generate the HTML pages. diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs index c47233ca42abe..7ee1aca2abcd4 100644 --- a/src/bootstrap/src/core/build_steps/install.rs +++ b/src/bootstrap/src/core/build_steps/install.rs @@ -6,11 +6,11 @@ use std::env; use std::fs; use std::path::{Component, Path, PathBuf}; -use std::process::Command; use crate::core::build_steps::dist; use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::core::config::{Config, TargetSelection}; +use crate::utils::exec::BootstrapCommand; use crate::utils::helpers::t; use crate::utils::tarball::GeneratedTarball; use crate::{Compiler, Kind}; @@ -102,7 +102,7 @@ fn install_sh( let empty_dir = builder.out.join("tmp/empty_dir"); t!(fs::create_dir_all(&empty_dir)); - let mut cmd = Command::new(SHELL); + let mut cmd = BootstrapCommand::new(SHELL); cmd.current_dir(&empty_dir) .arg(sanitize_sh(&tarball.decompressed_output().join("install.sh"))) .arg(format!("--prefix={}", prepare_dir(&destdir_env, prefix))) @@ -113,7 +113,7 @@ fn install_sh( .arg(format!("--libdir={}", prepare_dir(&destdir_env, libdir))) .arg(format!("--mandir={}", prepare_dir(&destdir_env, mandir))) .arg("--disable-ldconfig"); - builder.run(&mut cmd); + builder.run(cmd); t!(fs::remove_dir_all(&empty_dir)); } diff --git a/src/bootstrap/src/core/build_steps/perf.rs b/src/bootstrap/src/core/build_steps/perf.rs index 9d70ca6bd71fd..f41b5fe10f1d9 100644 --- a/src/bootstrap/src/core/build_steps/perf.rs +++ b/src/bootstrap/src/core/build_steps/perf.rs @@ -1,7 +1,5 @@ -use std::process::Command; - use crate::core::build_steps::compile::{Std, Sysroot}; -use crate::core::build_steps::tool::RustcPerf; +use crate::core::build_steps::tool::{RustcPerf, Tool}; use crate::core::builder::Builder; use crate::core::config::DebuginfoLevel; @@ -22,24 +20,16 @@ Consider setting `rust.debuginfo-level = 1` in `config.toml`."#); let sysroot = builder.ensure(Sysroot::new(compiler)); let rustc = sysroot.join("bin/rustc"); - let results_dir = builder.build.tempdir().join("rustc-perf"); - - let mut cmd = Command::new(collector); - let cmd = cmd - .arg("profile_local") - .arg("eprintln") - .arg("--out-dir") - .arg(&results_dir) - .arg("--include") - .arg("helloworld") - .arg(&rustc); - - builder.info(&format!("Running `rustc-perf` using `{}`", rustc.display())); + let rustc_perf_dir = builder.build.tempdir().join("rustc-perf"); + let profile_results_dir = rustc_perf_dir.join("results"); - // We need to set the working directory to `src/tools/perf`, so that it can find the directory - // with compile-time benchmarks. - let cmd = cmd.current_dir(builder.src.join("src/tools/rustc-perf")); - builder.build.run(cmd); + // We need to take args passed after `--` and pass them to `rustc-perf-wrapper` + let args = std::env::args().skip_while(|a| a != "--").skip(1); - builder.info(&format!("You can find the results at `{}`", results_dir.display())); + let mut cmd = builder.tool_cmd(Tool::RustcPerfWrapper); + cmd.env("RUSTC_REAL", rustc) + .env("PERF_COLLECTOR", collector) + .env("PERF_RESULT_DIR", profile_results_dir) + .args(args); + builder.run(&mut cmd); } diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs index 9268b335db7c2..22d5efa5d95dd 100644 --- a/src/bootstrap/src/core/build_steps/run.rs +++ b/src/bootstrap/src/core/build_steps/run.rs @@ -50,7 +50,7 @@ impl Step for BuildManifest { cmd.arg(&builder.config.channel); builder.create_dir(&distdir(builder)); - builder.run(&mut cmd); + builder.run(cmd); } } @@ -72,7 +72,7 @@ impl Step for BumpStage0 { fn run(self, builder: &Builder<'_>) -> Self::Output { let mut cmd = builder.tool_cmd(Tool::BumpStage0); cmd.args(builder.config.args()); - builder.run(&mut cmd); + builder.run(cmd); } } @@ -94,7 +94,7 @@ impl Step for ReplaceVersionPlaceholder { fn run(self, builder: &Builder<'_>) -> Self::Output { let mut cmd = builder.tool_cmd(Tool::ReplaceVersionPlaceholder); cmd.arg(&builder.src); - builder.run(&mut cmd); + builder.run(cmd); } } @@ -158,8 +158,7 @@ impl Step for Miri { // after another --, so this must be at the end. miri.args(builder.config.args()); - let mut miri = Command::from(miri); - builder.run(&mut miri); + builder.run(miri); } } @@ -189,7 +188,7 @@ impl Step for CollectLicenseMetadata { let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata); cmd.env("REUSE_EXE", reuse); cmd.env("DEST", &dest); - builder.run(&mut cmd); + builder.run(cmd); dest } @@ -219,7 +218,7 @@ impl Step for GenerateCopyright { let mut cmd = builder.tool_cmd(Tool::GenerateCopyright); cmd.env("LICENSE_METADATA", &license_metadata); cmd.env("DEST", &dest); - builder.run(&mut cmd); + builder.run(cmd); dest } @@ -243,7 +242,7 @@ impl Step for GenerateWindowsSys { fn run(self, builder: &Builder<'_>) { let mut cmd = builder.tool_cmd(Tool::GenerateWindowsSys); cmd.arg(&builder.src); - builder.run(&mut cmd); + builder.run(cmd); } } diff --git a/src/bootstrap/src/core/build_steps/suggest.rs b/src/bootstrap/src/core/build_steps/suggest.rs index 754d1e61da8c6..7c5e0d4e13ebb 100644 --- a/src/bootstrap/src/core/build_steps/suggest.rs +++ b/src/bootstrap/src/core/build_steps/suggest.rs @@ -16,6 +16,7 @@ pub fn suggest(builder: &Builder<'_>, run: bool) { .tool_cmd(Tool::SuggestTests) .env("SUGGEST_TESTS_GIT_REPOSITORY", git_config.git_repository) .env("SUGGEST_TESTS_NIGHTLY_BRANCH", git_config.nightly_branch) + .command .output() .expect("failed to run `suggest-tests` tool"); diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 1ef5af7cc2daf..1460a2290197b 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -156,7 +156,7 @@ You can skip linkcheck with --skip src/tools/linkchecker" let _guard = builder.msg(Kind::Test, compiler.stage, "Linkcheck", bootstrap_host, bootstrap_host); let _time = helpers::timeit(builder); - builder.run_tracked( + builder.run( BootstrapCommand::from(linkchecker.arg(builder.out.join(host.triple).join("doc"))) .delay_failure(), ); @@ -216,7 +216,7 @@ impl Step for HtmlCheck { builder, )); - builder.run_tracked( + builder.run( BootstrapCommand::from( builder.tool_cmd(Tool::HtmlChecker).arg(builder.doc_out(self.target)), ) @@ -267,7 +267,7 @@ impl Step for Cargotest { .env("RUSTC", builder.rustc(compiler)) .env("RUSTDOC", builder.rustdoc(compiler)); add_rustdoc_cargo_linker_args(cmd, builder, compiler.host, LldThreads::No); - builder.run_tracked(BootstrapCommand::from(cmd).delay_failure()); + builder.run(BootstrapCommand::from(cmd).delay_failure()); } } @@ -465,7 +465,7 @@ impl Miri { // Tell it where to put the sysroot. cargo.env("MIRI_SYSROOT", &miri_sysroot); - let mut cargo = Command::from(cargo); + let mut cargo = BootstrapCommand::from(cargo); let _guard = builder.msg(Kind::Build, compiler.stage, "miri sysroot", compiler.host, target); builder.run(&mut cargo); @@ -482,8 +482,10 @@ impl Miri { String::new() } else { builder.verbose(|| println!("running: {cargo:?}")); - let out = - cargo.output().expect("We already ran `cargo miri setup` before and that worked"); + let out = cargo + .command + .output() + .expect("We already ran `cargo miri setup` before and that worked"); assert!(out.status.success(), "`cargo miri setup` returned with non-0 exit code"); // Output is "\n". let stdout = String::from_utf8(out.stdout) @@ -596,7 +598,7 @@ impl Step for Miri { target, ); let _time = helpers::timeit(builder); - builder.run(&mut cargo); + builder.run(cargo); } } } @@ -661,11 +663,11 @@ impl Step for CargoMiri { // Finally, pass test-args and run everything. cargo.arg("--").args(builder.config.test_args()); - let mut cargo = Command::from(cargo); + let cargo = BootstrapCommand::from(cargo); { let _guard = builder.msg_sysroot_tool(Kind::Test, stage, "cargo-miri", host, target); let _time = helpers::timeit(builder); - builder.run(&mut cargo); + builder.run(cargo); } } } @@ -766,7 +768,7 @@ impl Step for Clippy { let _guard = builder.msg_sysroot_tool(Kind::Test, compiler.stage, "clippy", host, host); // Clippy reports errors if it blessed the outputs - if builder.run_cmd(BootstrapCommand::from(&mut cargo).allow_failure()) { + if builder.run(BootstrapCommand::from(&mut cargo).allow_failure()).is_success() { // The tests succeeded; nothing to do. return; } @@ -819,7 +821,7 @@ impl Step for RustdocTheme { .env("RUSTC_BOOTSTRAP", "1"); cmd.args(linker_args(builder, self.compiler.host, LldThreads::No)); - builder.run_tracked(BootstrapCommand::from(&mut cmd).delay_failure()); + builder.run(BootstrapCommand::from(&mut cmd).delay_failure()); } } @@ -845,7 +847,7 @@ impl Step for RustdocJSStd { fn run(self, builder: &Builder<'_>) { let nodejs = builder.config.nodejs.as_ref().expect("need nodejs to run rustdoc-js-std tests"); - let mut command = Command::new(nodejs); + let mut command = BootstrapCommand::new(nodejs); command .arg(builder.src.join("src/tools/rustdoc-js/tester.js")) .arg("--crate-name") @@ -879,7 +881,7 @@ impl Step for RustdocJSStd { builder.config.build, self.target, ); - builder.run(&mut command); + builder.run(command); } } @@ -1097,7 +1099,7 @@ HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to } builder.info("tidy check"); - builder.run_tracked(BootstrapCommand::from(&mut cmd).delay_failure()); + builder.run(BootstrapCommand::from(&mut cmd).delay_failure()); builder.info("x.py completions check"); let [bash, zsh, fish, powershell] = ["x.py.sh", "x.py.zsh", "x.py.fish", "x.py.ps1"] @@ -1304,8 +1306,7 @@ impl Step for RunMakeSupport { &[], ); - let mut cargo = Command::from(cargo); - builder.run(&mut cargo); + builder.run(cargo); let lib_name = "librun_make_support.rlib"; let lib = builder.tools_dir(self.compiler).join(lib_name); @@ -1816,23 +1817,25 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the cmd.arg("--gdb").arg(gdb); } - let run = |cmd: &mut Command| { - cmd.output().map(|output| { - String::from_utf8_lossy(&output.stdout) - .lines() - .next() - .unwrap_or_else(|| panic!("{:?} failed {:?}", cmd, output)) - .to_string() - }) - }; - let lldb_exe = builder.config.lldb.clone().unwrap_or_else(|| PathBuf::from("lldb")); let lldb_version = Command::new(&lldb_exe) .arg("--version") .output() - .map(|output| String::from_utf8_lossy(&output.stdout).to_string()) - .ok(); + .map(|output| { + (String::from_utf8_lossy(&output.stdout).to_string(), output.status.success()) + }) + .ok() + .and_then(|(output, success)| if success { Some(output) } else { None }); if let Some(ref vers) = lldb_version { + let run = |cmd: &mut Command| { + cmd.output().map(|output| { + String::from_utf8_lossy(&output.stdout) + .lines() + .next() + .unwrap_or_else(|| panic!("{:?} failed {:?}", cmd, output)) + .to_string() + }) + }; cmd.arg("--lldb-version").arg(vers); let lldb_python_dir = run(Command::new(&lldb_exe).arg("-P")).ok(); if let Some(ref dir) = lldb_python_dir { @@ -2066,7 +2069,8 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the cmd.arg("--git-repository").arg(git_config.git_repository); cmd.arg("--nightly-branch").arg(git_config.nightly_branch); - builder.ci_env.force_coloring_in_ci(&mut cmd); + // FIXME: Move CiEnv back to bootstrap, it is only used here anyway + builder.ci_env.force_coloring_in_ci(&mut cmd.command); #[cfg(feature = "build-metrics")] builder.metrics.begin_test_suite( @@ -2184,11 +2188,8 @@ impl BookTest { ); let _time = helpers::timeit(builder); let cmd = BootstrapCommand::from(&mut rustbook_cmd).delay_failure(); - let toolstate = if builder.run_tracked(cmd).is_success() { - ToolState::TestPass - } else { - ToolState::TestFail - }; + let toolstate = + if builder.run(cmd).is_success() { ToolState::TestPass } else { ToolState::TestFail }; builder.save_toolstate(self.name, toolstate); } @@ -2317,8 +2318,7 @@ impl Step for ErrorIndex { let guard = builder.msg(Kind::Test, compiler.stage, "error-index", compiler.host, compiler.host); let _time = helpers::timeit(builder); - builder - .run_tracked(BootstrapCommand::from(&mut tool).output_mode(OutputMode::OnlyOnFailure)); + builder.run(BootstrapCommand::from(&mut tool).output_mode(OutputMode::OnlyOnFailure)); drop(guard); // The tests themselves need to link to std, so make sure it is // available. @@ -2347,11 +2347,11 @@ fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> let test_args = builder.config.test_args().join(" "); cmd.arg("--test-args").arg(test_args); - let mut cmd = BootstrapCommand::from(&mut cmd).delay_failure(); + cmd = cmd.delay_failure(); if !builder.config.verbose_tests { cmd = cmd.quiet(); } - builder.run_tracked(cmd).is_success() + builder.run(cmd).is_success() } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -2377,11 +2377,8 @@ impl Step for RustcGuide { let src = builder.src.join(relative_path); let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook); let cmd = BootstrapCommand::from(rustbook_cmd.arg("linkcheck").arg(&src)).delay_failure(); - let toolstate = if builder.run_tracked(cmd).is_success() { - ToolState::TestPass - } else { - ToolState::TestFail - }; + let toolstate = + if builder.run(cmd).is_success() { ToolState::TestPass } else { ToolState::TestFail }; builder.save_toolstate("rustc-dev-guide", toolstate); } } @@ -2432,7 +2429,7 @@ impl Step for CrateLibrustc { /// Returns whether the test succeeded. #[allow(clippy::too_many_arguments)] // FIXME: reduce the number of args and remove this. fn run_cargo_test<'a>( - cargo: impl Into, + cargo: impl Into, libtest_args: &[&str], crates: &[String], primary_crate: &str, @@ -2463,14 +2460,14 @@ fn run_cargo_test<'a>( /// Given a `cargo test` subcommand, pass it the appropriate test flags given a `builder`. fn prepare_cargo_test( - cargo: impl Into, + cargo: impl Into, libtest_args: &[&str], crates: &[String], primary_crate: &str, compiler: Compiler, target: TargetSelection, builder: &Builder<'_>, -) -> Command { +) -> BootstrapCommand { let mut cargo = cargo.into(); // Propegate `--bless` if it has not already been set/unset @@ -2881,19 +2878,19 @@ impl Step for RemoteCopyLibs { // Spawn the emulator and wait for it to come online let tool = builder.tool_exe(Tool::RemoteTestClient); - let mut cmd = Command::new(&tool); + let mut cmd = BootstrapCommand::new(&tool); cmd.arg("spawn-emulator").arg(target.triple).arg(&server).arg(builder.tempdir()); if let Some(rootfs) = builder.qemu_rootfs(target) { cmd.arg(rootfs); } - builder.run(&mut cmd); + builder.run(cmd); // Push all our dylibs to the emulator for f in t!(builder.sysroot_libdir(compiler, target).read_dir()) { let f = t!(f); let name = f.file_name().into_string().unwrap(); if helpers::is_dylib(&name) { - builder.run(Command::new(&tool).arg("push").arg(f.path())); + builder.run(BootstrapCommand::new(&tool).arg("push").arg(f.path())); } } } @@ -2924,20 +2921,20 @@ impl Step for Distcheck { builder.ensure(dist::PlainSourceTarball); builder.ensure(dist::Src); - let mut cmd = Command::new("tar"); + let mut cmd = BootstrapCommand::new("tar"); cmd.arg("-xf") .arg(builder.ensure(dist::PlainSourceTarball).tarball()) .arg("--strip-components=1") .current_dir(&dir); - builder.run(&mut cmd); + builder.run(cmd); builder.run( - Command::new("./configure") + BootstrapCommand::new("./configure") .args(&builder.config.configure_args) .arg("--enable-vendor") .current_dir(&dir), ); builder.run( - Command::new(helpers::make(&builder.config.build.triple)) + BootstrapCommand::new(helpers::make(&builder.config.build.triple)) .arg("check") .current_dir(&dir), ); @@ -2948,16 +2945,16 @@ impl Step for Distcheck { let _ = fs::remove_dir_all(&dir); t!(fs::create_dir_all(&dir)); - let mut cmd = Command::new("tar"); + let mut cmd = BootstrapCommand::new("tar"); cmd.arg("-xf") .arg(builder.ensure(dist::Src).tarball()) .arg("--strip-components=1") .current_dir(&dir); - builder.run(&mut cmd); + builder.run(cmd); let toml = dir.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml"); builder.run( - Command::new(&builder.initial_cargo) + BootstrapCommand::new(&builder.initial_cargo) // Will read the libstd Cargo.toml // which uses the unstable `public-dependency` feature. .env("RUSTC_BOOTSTRAP", "1") @@ -2986,7 +2983,7 @@ impl Step for Bootstrap { // Some tests require cargo submodule to be present. builder.build.update_submodule(Path::new("src/tools/cargo")); - let mut check_bootstrap = Command::new(builder.python()); + let mut check_bootstrap = BootstrapCommand::new(builder.python()); check_bootstrap .args(["-m", "unittest", "bootstrap_test.py"]) .env("BUILD_DIR", &builder.out) @@ -2994,9 +2991,9 @@ impl Step for Bootstrap { .current_dir(builder.src.join("src/bootstrap/")); // NOTE: we intentionally don't pass test_args here because the args for unittest and cargo test are mutually incompatible. // Use `python -m unittest` manually if you want to pass arguments. - builder.run_tracked(BootstrapCommand::from(&mut check_bootstrap).delay_failure()); + builder.run(check_bootstrap.delay_failure()); - let mut cmd = Command::new(&builder.initial_cargo); + let mut cmd = BootstrapCommand::new(&builder.initial_cargo); cmd.arg("test") .args(["--features", "bootstrap-self-test"]) .current_dir(builder.src.join("src/bootstrap")) @@ -3071,7 +3068,7 @@ impl Step for TierCheck { self.compiler.host, self.compiler.host, ); - builder.run_tracked(BootstrapCommand::from(&mut cargo.into()).delay_failure()); + builder.run(BootstrapCommand::from(cargo).delay_failure()); } } @@ -3147,8 +3144,7 @@ impl Step for RustInstaller { return; } - let mut cmd = - std::process::Command::new(builder.src.join("src/tools/rust-installer/test.sh")); + let mut cmd = BootstrapCommand::new(builder.src.join("src/tools/rust-installer/test.sh")); let tmpdir = testdir(builder, compiler.host).join("rust-installer"); let _ = std::fs::remove_dir_all(&tmpdir); let _ = std::fs::create_dir_all(&tmpdir); @@ -3157,7 +3153,7 @@ impl Step for RustInstaller { cmd.env("CARGO", &builder.initial_cargo); cmd.env("RUSTC", &builder.initial_rustc); cmd.env("TMP_DIR", &tmpdir); - builder.run_tracked(BootstrapCommand::from(&mut cmd).delay_failure()); + builder.run(cmd.delay_failure()); } fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -3351,8 +3347,7 @@ impl Step for CodegenCranelift { .arg("testsuite.extended_sysroot"); cargo.args(builder.config.test_args()); - let mut cmd: Command = cargo.into(); - builder.run_cmd(BootstrapCommand::from(&mut cmd).fail_fast()); + builder.run(cargo); } } @@ -3477,7 +3472,6 @@ impl Step for CodegenGCC { .arg("--std-tests"); cargo.args(builder.config.test_args()); - let mut cmd: Command = cargo.into(); - builder.run_cmd(BootstrapCommand::from(&mut cmd).fail_fast()); + builder.run(cargo); } } diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index a95a7f5491f37..b34640439121a 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -9,6 +9,7 @@ use crate::core::builder; use crate::core::builder::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun, Step}; use crate::core::config::TargetSelection; use crate::utils::channel::GitInfo; +use crate::utils::exec::BootstrapCommand; use crate::utils::helpers::output; use crate::utils::helpers::{add_dylib_path, exe, t}; use crate::Compiler; @@ -336,6 +337,7 @@ bootstrap_tool!( GenerateWindowsSys, "src/tools/generate-windows-sys", "generate-windows-sys"; RustdocGUITest, "src/tools/rustdoc-gui-test", "rustdoc-gui-test", is_unstable_tool = true, allow_features = "test"; CoverageDump, "src/tools/coverage-dump", "coverage-dump"; + RustcPerfWrapper, "src/tools/rustc-perf-wrapper", "rustc-perf-wrapper"; ); #[derive(Debug, Clone, Hash, PartialEq, Eq)] @@ -432,12 +434,12 @@ pub struct ErrorIndex { } impl ErrorIndex { - pub fn command(builder: &Builder<'_>) -> Command { + pub fn command(builder: &Builder<'_>) -> BootstrapCommand { // Error-index-generator links with the rustdoc library, so we need to add `rustc_lib_paths` // for rustc_private and libLLVM.so, and `sysroot_lib` for libstd, etc. let host = builder.config.build; let compiler = builder.compiler_for(builder.top_stage, host, host); - let mut cmd = Command::new(builder.ensure(ErrorIndex { compiler })); + let mut cmd = BootstrapCommand::new(builder.ensure(ErrorIndex { compiler })); let mut dylib_paths = builder.rustc_lib_paths(compiler); dylib_paths.push(PathBuf::from(&builder.sysroot_libdir(compiler, compiler.host))); add_dylib_path(dylib_paths, &mut cmd); @@ -601,7 +603,7 @@ impl Step for Rustdoc { &self.compiler.host, &target, ); - builder.run(&mut cargo.into()); + builder.run(cargo); // Cargo adds a number of paths to the dylib search path on windows, which results in // the wrong rustdoc being executed. To avoid the conflicting rustdocs, we name the "tool" @@ -856,7 +858,7 @@ impl Step for LlvmBitcodeLinker { &self.extra_features, ); - builder.run(&mut cargo.into()); + builder.run(cargo); let tool_out = builder .cargo_out(self.compiler, Mode::ToolRustc, self.target) @@ -911,13 +913,13 @@ impl Step for LibcxxVersionTool { } let compiler = builder.cxx(self.target).unwrap(); - let mut cmd = Command::new(compiler); + let mut cmd = BootstrapCommand::new(compiler); cmd.arg("-o") .arg(&executable) .arg(builder.src.join("src/tools/libcxx-version/main.cpp")); - builder.run_cmd(&mut cmd); + builder.run(cmd); if !executable.exists() { panic!("Something went wrong. {} is not present", executable.display()); @@ -1045,10 +1047,10 @@ tool_extended!((self, builder), ); impl<'a> Builder<'a> { - /// Gets a `Command` which is ready to run `tool` in `stage` built for + /// Gets a `BootstrapCommand` which is ready to run `tool` in `stage` built for /// `host`. - pub fn tool_cmd(&self, tool: Tool) -> Command { - let mut cmd = Command::new(self.tool_exe(tool)); + pub fn tool_cmd(&self, tool: Tool) -> BootstrapCommand { + let mut cmd = BootstrapCommand::new(self.tool_exe(tool)); let compiler = self.compiler(0, self.config.build); let host = &compiler.host; // Prepares the `cmd` provided to be able to run the `compiler` provided. diff --git a/src/bootstrap/src/core/build_steps/vendor.rs b/src/bootstrap/src/core/build_steps/vendor.rs index e92ab57619b6a..0b999a24a1fb9 100644 --- a/src/bootstrap/src/core/build_steps/vendor.rs +++ b/src/bootstrap/src/core/build_steps/vendor.rs @@ -1,6 +1,6 @@ use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; +use crate::utils::exec::BootstrapCommand; use std::path::{Path, PathBuf}; -use std::process::Command; #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub(crate) struct Vendor { @@ -27,7 +27,7 @@ impl Step for Vendor { } fn run(self, builder: &Builder<'_>) -> Self::Output { - let mut cmd = Command::new(&builder.initial_cargo); + let mut cmd = BootstrapCommand::new(&builder.initial_cargo); cmd.arg("vendor"); if self.versioned_dirs { @@ -59,6 +59,6 @@ impl Step for Vendor { cmd.current_dir(self.root_dir); - builder.run(&mut cmd); + builder.run(cmd); } } diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 14ccbfe0267e8..58d6e7a58e308 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -24,6 +24,7 @@ use crate::utils::helpers::{check_cfg_arg, libdir, linker_flags, output, t, LldT use crate::EXTRA_CHECK_CFGS; use crate::{Build, CLang, Crate, DocTests, GitRepo, Mode}; +use crate::utils::exec::BootstrapCommand; pub use crate::Compiler; use clap::ValueEnum; @@ -1217,7 +1218,7 @@ impl<'a> Builder<'a> { /// Adds the compiler's directory of dynamic libraries to `cmd`'s dynamic /// library lookup path. - pub fn add_rustc_lib_path(&self, compiler: Compiler, cmd: &mut Command) { + pub fn add_rustc_lib_path(&self, compiler: Compiler, cmd: &mut BootstrapCommand) { // Windows doesn't need dylib path munging because the dlls for the // compiler live next to the compiler and the system will find them // automatically. @@ -1250,11 +1251,11 @@ impl<'a> Builder<'a> { self.ensure(tool::Rustdoc { compiler }) } - pub fn cargo_clippy_cmd(&self, run_compiler: Compiler) -> Command { + pub fn cargo_clippy_cmd(&self, run_compiler: Compiler) -> BootstrapCommand { if run_compiler.stage == 0 { // `ensure(Clippy { stage: 0 })` *builds* clippy with stage0, it doesn't use the beta clippy. let cargo_clippy = self.build.config.download_clippy(); - let mut cmd = Command::new(cargo_clippy); + let mut cmd = BootstrapCommand::new(cargo_clippy); cmd.env("CARGO", &self.initial_cargo); return cmd; } @@ -1273,13 +1274,13 @@ impl<'a> Builder<'a> { let mut dylib_path = helpers::dylib_path(); dylib_path.insert(0, self.sysroot(run_compiler).join("lib")); - let mut cmd = Command::new(cargo_clippy); + let mut cmd = BootstrapCommand::new(cargo_clippy); cmd.env(helpers::dylib_path_var(), env::join_paths(&dylib_path).unwrap()); cmd.env("CARGO", &self.initial_cargo); cmd } - pub fn cargo_miri_cmd(&self, run_compiler: Compiler) -> Command { + pub fn cargo_miri_cmd(&self, run_compiler: Compiler) -> BootstrapCommand { assert!(run_compiler.stage > 0, "miri can not be invoked at stage 0"); let build_compiler = self.compiler(run_compiler.stage - 1, self.build.build); @@ -1295,7 +1296,7 @@ impl<'a> Builder<'a> { extra_features: Vec::new(), }); // Invoke cargo-miri, make sure it can find miri and cargo. - let mut cmd = Command::new(cargo_miri); + let mut cmd = BootstrapCommand::new(cargo_miri); cmd.env("MIRI", &miri); cmd.env("CARGO", &self.initial_cargo); // Need to add the `run_compiler` libs. Those are the libs produces *by* `build_compiler`, @@ -1310,8 +1311,8 @@ impl<'a> Builder<'a> { cmd } - pub fn rustdoc_cmd(&self, compiler: Compiler) -> Command { - let mut cmd = Command::new(self.bootstrap_out.join("rustdoc")); + pub fn rustdoc_cmd(&self, compiler: Compiler) -> BootstrapCommand { + let mut cmd = BootstrapCommand::new(self.bootstrap_out.join("rustdoc")); cmd.env("RUSTC_STAGE", compiler.stage.to_string()) .env("RUSTC_SYSROOT", self.sysroot(compiler)) // Note that this is *not* the sysroot_libdir because rustdoc must be linked @@ -1352,7 +1353,7 @@ impl<'a> Builder<'a> { mode: Mode, target: TargetSelection, cmd: &str, // FIXME make this properly typed - ) -> Command { + ) -> BootstrapCommand { let mut cargo; if cmd == "clippy" { cargo = self.cargo_clippy_cmd(compiler); @@ -1365,7 +1366,7 @@ impl<'a> Builder<'a> { cargo = self.cargo_miri_cmd(compiler); cargo.arg("miri").arg(subcmd); } else { - cargo = Command::new(&self.initial_cargo); + cargo = BootstrapCommand::new(&self.initial_cargo); cargo.arg(cmd); } @@ -2104,7 +2105,7 @@ impl<'a> Builder<'a> { // Try to use a sysroot-relative bindir, in case it was configured absolutely. cargo.env("RUSTC_INSTALL_BINDIR", self.config.bindir_relative()); - self.ci_env.force_coloring_in_ci(&mut cargo); + self.ci_env.force_coloring_in_ci(&mut cargo.command); // When we build Rust dylibs they're all intended for intermediate // usage, so make sure we pass the -Cprefer-dynamic flag instead of @@ -2373,7 +2374,7 @@ impl HostFlags { #[derive(Debug)] pub struct Cargo { - command: Command, + command: BootstrapCommand, compiler: Compiler, target: TargetSelection, rustflags: Rustflags, @@ -2598,8 +2599,8 @@ impl Cargo { } } -impl From for Command { - fn from(mut cargo: Cargo) -> Command { +impl From for BootstrapCommand { + fn from(mut cargo: Cargo) -> BootstrapCommand { let rustflags = &cargo.rustflags.0; if !rustflags.is_empty() { cargo.command.env("RUSTFLAGS", rustflags); @@ -2618,7 +2619,12 @@ impl From for Command { if !cargo.allow_features.is_empty() { cargo.command.env("RUSTC_ALLOW_FEATURES", cargo.allow_features); } - cargo.command } } + +impl From for Command { + fn from(cargo: Cargo) -> Command { + BootstrapCommand::from(cargo).command + } +} diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs index eb5152a38312b..aeb608a9ea26b 100644 --- a/src/bootstrap/src/core/config/flags.rs +++ b/src/bootstrap/src/core/config/flags.rs @@ -470,7 +470,9 @@ Arguments: versioned_dirs: bool, }, /// Perform profiling and benchmarking of the compiler using the - /// `rustc-perf` benchmark suite. + /// `rustc-perf-wrapper` tool. + /// + /// You need to pass arguments after `--`, e.g.`x perf -- cachegrind`. Perf {}, } diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index fd077ab2d7c7a..c35398e2eb764 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -11,6 +11,7 @@ use std::{ use build_helper::ci::CiEnv; use xz2::bufread::XzDecoder; +use crate::utils::exec::BootstrapCommand; use crate::utils::helpers::hex_encode; use crate::utils::helpers::{check_run, exe, move_file, program_out_of_date}; use crate::{t, Config}; @@ -56,7 +57,7 @@ impl Config { /// Runs a command, printing out nice contextual information if it fails. /// Returns false if do not execute at all, otherwise returns its /// `status.success()`. - pub(crate) fn check_run(&self, cmd: &mut Command) -> bool { + pub(crate) fn check_run(&self, cmd: &mut BootstrapCommand) -> bool { if self.dry_run() { return true; } @@ -211,7 +212,7 @@ impl Config { fn download_http_with_retries(&self, tempfile: &Path, url: &str, help_on_error: &str) { println!("downloading {url}"); // Try curl. If that fails and we are on windows, fallback to PowerShell. - let mut curl = Command::new("curl"); + let mut curl = BootstrapCommand::new("curl"); curl.args([ "-y", "30", diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index afba907ee92b4..c12449fdc4ae0 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -26,6 +26,7 @@ use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; use std::str; use std::sync::OnceLock; +use std::time::SystemTime; use build_helper::ci::{gha, CiEnv}; use build_helper::exit; @@ -74,7 +75,7 @@ const LLVM_TOOLS: &[&str] = &[ /// LLD file names for all flavors. const LLD_FILE_NAMES: &[&str] = &["ld.lld", "ld64.lld", "lld-link", "wasm-ld"]; -/// Extra --check-cfg to add when building +/// Extra `--check-cfg` to add when building the compiler or tools /// (Mode restriction, config name, config values (if any)) #[allow(clippy::type_complexity)] // It's fine for hard-coded list and type is explained above. const EXTRA_CHECK_CFGS: &[(Option, &str, Option<&[&'static str]>)] = &[ @@ -84,38 +85,9 @@ const EXTRA_CHECK_CFGS: &[(Option, &str, Option<&[&'static str]>)] = &[ (Some(Mode::ToolRustc), "rust_analyzer", None), (Some(Mode::ToolStd), "rust_analyzer", None), (Some(Mode::Codegen), "parallel_compiler", None), - // NOTE: consider updating `check-cfg` entries in `std/Cargo.toml` too. - // cfg(bootstrap) remove these once the bootstrap compiler supports - // `lints.rust.unexpected_cfgs.check-cfg` - (Some(Mode::Std), "stdarch_intel_sde", None), - (Some(Mode::Std), "no_fp_fmt_parse", None), - (Some(Mode::Std), "no_global_oom_handling", None), - (Some(Mode::Std), "no_rc", None), - (Some(Mode::Std), "no_sync", None), - /* Extra values not defined in the built-in targets yet, but used in std */ - (Some(Mode::Std), "target_env", Some(&["libnx", "p2"])), - (Some(Mode::Std), "target_os", Some(&["visionos"])), - (Some(Mode::Std), "target_arch", Some(&["arm64ec", "spirv", "nvptx", "xtensa"])), - (Some(Mode::ToolStd), "target_os", Some(&["visionos"])), - /* Extra names used by dependencies */ - // FIXME: Used by serde_json, but we should not be triggering on external dependencies. - (Some(Mode::Rustc), "no_btreemap_remove_entry", None), - (Some(Mode::ToolRustc), "no_btreemap_remove_entry", None), - // FIXME: Used by crossbeam-utils, but we should not be triggering on external dependencies. - (Some(Mode::Rustc), "crossbeam_loom", None), - (Some(Mode::ToolRustc), "crossbeam_loom", None), - // FIXME: Used by proc-macro2, but we should not be triggering on external dependencies. - (Some(Mode::Rustc), "span_locations", None), - (Some(Mode::ToolRustc), "span_locations", None), - // FIXME: Used by rustix, but we should not be triggering on external dependencies. - (Some(Mode::Rustc), "rustix_use_libc", None), - (Some(Mode::ToolRustc), "rustix_use_libc", None), - // FIXME: Used by filetime, but we should not be triggering on external dependencies. - (Some(Mode::Rustc), "emulate_second_only_system", None), - (Some(Mode::ToolRustc), "emulate_second_only_system", None), - // Needed to avoid the need to copy windows.lib into the sysroot. - (Some(Mode::Rustc), "windows_raw_dylib", None), - (Some(Mode::ToolRustc), "windows_raw_dylib", None), + // Any library specific cfgs like `target_os`, `target_arch` should be put in + // priority the `[lints.rust.unexpected_cfgs.check-cfg]` table + // in the appropriate `library/{std,alloc,core}/Cargo.toml` ]; /// A structure representing a Rust compiler. @@ -575,19 +547,17 @@ impl Build { }; // NOTE: doesn't use `try_run` because this shouldn't print an error if it fails. if !update(true).status().map_or(false, |status| status.success()) { - self.run(&mut update(false)); + self.run(update(false)); } // Save any local changes, but avoid running `git stash pop` if there are none (since it will exit with an error). // diff-index reports the modifications through the exit status - let has_local_modifications = !self.run_cmd( - BootstrapCommand::from(submodule_git().args(["diff-index", "--quiet", "HEAD"])) - .allow_failure() - .output_mode(match self.is_verbose() { - true => OutputMode::All, - false => OutputMode::OnlyOutput, - }), - ); + let has_local_modifications = self + .run( + BootstrapCommand::from(submodule_git().args(["diff-index", "--quiet", "HEAD"])) + .allow_failure(), + ) + .is_failure(); if has_local_modifications { self.run(submodule_git().args(["stash", "push"])); } @@ -939,7 +909,7 @@ impl Build { } /// Adds the `RUST_TEST_THREADS` env var if necessary - fn add_rust_test_threads(&self, cmd: &mut Command) { + fn add_rust_test_threads(&self, cmd: &mut BootstrapCommand) { if env::var_os("RUST_TEST_THREADS").is_none() { cmd.env("RUST_TEST_THREADS", self.jobs().to_string()); } @@ -961,11 +931,14 @@ impl Build { } /// Execute a command and return its output. - fn run_tracked(&self, command: BootstrapCommand<'_>) -> CommandOutput { + /// This method should be used for all command executions in bootstrap. + fn run>(&self, command: C) -> CommandOutput { if self.config.dry_run() { return CommandOutput::default(); } + let mut command = command.into(); + self.verbose(|| println!("running: {command:?}")); let output_mode = command.output_mode.unwrap_or_else(|| match self.is_verbose() { @@ -1024,22 +997,6 @@ impl Build { output } - /// Runs a command, printing out nice contextual information if it fails. - fn run(&self, cmd: &mut Command) { - self.run_cmd(BootstrapCommand::from(cmd).fail_fast().output_mode( - match self.is_verbose() { - true => OutputMode::All, - false => OutputMode::OnlyOutput, - }, - )); - } - - /// A centralized function for running commands that do not return output. - pub(crate) fn run_cmd<'a, C: Into>>(&self, cmd: C) -> bool { - let command = cmd.into(); - self.run_tracked(command).is_success() - } - /// Check if verbosity is greater than the `level` pub fn is_verbose_than(&self, level: usize) -> bool { self.verbosity > level @@ -1691,7 +1648,14 @@ impl Build { if src == dst { return; } - let _ = fs::remove_file(dst); + if let Err(e) = fs::remove_file(dst) { + if cfg!(windows) && e.kind() != io::ErrorKind::NotFound { + // workaround for https://github.com/rust-lang/rust/issues/127126 + // if removing the file fails, attempt to rename it instead. + let now = t!(SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)); + let _ = fs::rename(dst, format!("{}-{}", dst.display(), now.as_nanos())); + } + } let metadata = t!(src.symlink_metadata(), format!("src = {}", src.display())); let mut src = src.to_path_buf(); if metadata.file_type().is_symlink() { diff --git a/src/bootstrap/src/utils/bin_helpers.rs b/src/bootstrap/src/utils/bin_helpers.rs deleted file mode 100644 index 5fbbe0bde0e28..0000000000000 --- a/src/bootstrap/src/utils/bin_helpers.rs +++ /dev/null @@ -1,50 +0,0 @@ -//! This file is meant to be included directly from bootstrap shims to avoid a -//! dependency on the bootstrap library. This reduces the binary size and -//! improves compilation time by reducing the linking time. - -use std::env; -use std::fs::OpenOptions; -use std::io::Write; -use std::process::Command; -use std::str::FromStr; - -/// Parses the value of the "RUSTC_VERBOSE" environment variable and returns it as a `usize`. -/// If it was not defined, returns 0 by default. -/// -/// Panics if "RUSTC_VERBOSE" is defined with the value that is not an unsigned integer. -pub(crate) fn parse_rustc_verbose() -> usize { - match env::var("RUSTC_VERBOSE") { - Ok(s) => usize::from_str(&s).expect("RUSTC_VERBOSE should be an integer"), - Err(_) => 0, - } -} - -/// Parses the value of the "RUSTC_STAGE" environment variable and returns it as a `String`. -/// -/// If "RUSTC_STAGE" was not set, the program will be terminated with 101. -pub(crate) fn parse_rustc_stage() -> String { - env::var("RUSTC_STAGE").unwrap_or_else(|_| { - // Don't panic here; it's reasonable to try and run these shims directly. Give a helpful error instead. - eprintln!("rustc shim: FATAL: RUSTC_STAGE was not set"); - eprintln!("rustc shim: NOTE: use `x.py build -vvv` to see all environment variables set by bootstrap"); - std::process::exit(101); - }) -} - -/// Writes the command invocation to a file if `DUMP_BOOTSTRAP_SHIMS` is set during bootstrap. -/// -/// Before writing it, replaces user-specific values to create generic dumps for cross-environment -/// comparisons. -pub(crate) fn maybe_dump(dump_name: String, cmd: &Command) { - if let Ok(dump_dir) = env::var("DUMP_BOOTSTRAP_SHIMS") { - let dump_file = format!("{dump_dir}/{dump_name}"); - - let mut file = OpenOptions::new().create(true).append(true).open(dump_file).unwrap(); - - let cmd_dump = format!("{:?}\n", cmd); - let cmd_dump = cmd_dump.replace(&env::var("BUILD_OUT").unwrap(), "${BUILD_OUT}"); - let cmd_dump = cmd_dump.replace(&env::var("CARGO_HOME").unwrap(), "${CARGO_HOME}"); - - file.write_all(cmd_dump.as_bytes()).expect("Unable to write file"); - } -} diff --git a/src/bootstrap/src/utils/dylib.rs b/src/bootstrap/src/utils/dylib.rs deleted file mode 100644 index 90bcff59a647c..0000000000000 --- a/src/bootstrap/src/utils/dylib.rs +++ /dev/null @@ -1,40 +0,0 @@ -//! Various utilities for working with dylib paths. - -/// Returns the environment variable which the dynamic library lookup path -/// resides in for this platform. -pub fn dylib_path_var() -> &'static str { - if cfg!(target_os = "windows") { - "PATH" - } else if cfg!(target_vendor = "apple") { - "DYLD_LIBRARY_PATH" - } else if cfg!(target_os = "haiku") { - "LIBRARY_PATH" - } else if cfg!(target_os = "aix") { - "LIBPATH" - } else { - "LD_LIBRARY_PATH" - } -} - -/// Parses the `dylib_path_var()` environment variable, returning a list of -/// paths that are members of this lookup path. -pub fn dylib_path() -> Vec { - let var = match std::env::var_os(dylib_path_var()) { - Some(v) => v, - None => return vec![], - }; - std::env::split_paths(&var).collect() -} - -/// Given an executable called `name`, return the filename for the -/// executable for a particular target. -#[allow(dead_code)] -pub fn exe(name: &str, target: &str) -> String { - if target.contains("windows") { - format!("{name}.exe") - } else if target.contains("uefi") { - format!("{name}.efi") - } else { - name.to_string() - } -} diff --git a/src/bootstrap/src/utils/exec.rs b/src/bootstrap/src/utils/exec.rs index e8c588b75b381..8bcb2301f1ace 100644 --- a/src/bootstrap/src/utils/exec.rs +++ b/src/bootstrap/src/utils/exec.rs @@ -1,4 +1,6 @@ -use std::process::{Command, ExitStatus, Output}; +use std::ffi::OsStr; +use std::path::Path; +use std::process::{Command, CommandArgs, CommandEnvs, ExitStatus, Output}; /// What should be done when the command fails. #[derive(Debug, Copy, Clone)] @@ -24,14 +26,71 @@ pub enum OutputMode { } /// Wrapper around `std::process::Command`. +/// +/// By default, the command will exit bootstrap if it fails. +/// If you want to allow failures, use [allow_failure]. +/// If you want to delay failures until the end of bootstrap, use [delay_failure]. +/// +/// By default, the command will print its stdout/stderr to stdout/stderr of bootstrap +/// ([OutputMode::OnlyOutput]). If bootstrap uses verbose mode, then it will also print the +/// command itself in case of failure ([OutputMode::All]). +/// If you want to handle the output programmatically, use `output_mode(OutputMode::OnlyOnFailure)`. +/// +/// [allow_failure]: BootstrapCommand::allow_failure +/// [delay_failure]: BootstrapCommand::delay_failure #[derive(Debug)] -pub struct BootstrapCommand<'a> { - pub command: &'a mut Command, +pub struct BootstrapCommand { + pub command: Command, pub failure_behavior: BehaviorOnFailure, pub output_mode: Option, } -impl<'a> BootstrapCommand<'a> { +impl BootstrapCommand { + pub fn new>(program: S) -> Self { + Command::new(program).into() + } + + pub fn arg>(&mut self, arg: S) -> &mut Self { + self.command.arg(arg.as_ref()); + self + } + + pub fn args(&mut self, args: I) -> &mut Self + where + I: IntoIterator, + S: AsRef, + { + self.command.args(args); + self + } + + pub fn env(&mut self, key: K, val: V) -> &mut Self + where + K: AsRef, + V: AsRef, + { + self.command.env(key, val); + self + } + + pub fn get_envs(&self) -> CommandEnvs<'_> { + self.command.get_envs() + } + + pub fn get_args(&self) -> CommandArgs<'_> { + self.command.get_args() + } + + pub fn env_remove>(&mut self, key: K) -> &mut Self { + self.command.env_remove(key); + self + } + + pub fn current_dir>(&mut self, dir: P) -> &mut Self { + self.command.current_dir(dir); + self + } + pub fn delay_failure(self) -> Self { Self { failure_behavior: BehaviorOnFailure::DelayFail, ..self } } @@ -54,8 +113,41 @@ impl<'a> BootstrapCommand<'a> { } } -impl<'a> From<&'a mut Command> for BootstrapCommand<'a> { +/// This implementation is temporary, until all `Command` invocations are migrated to +/// `BootstrapCommand`. +impl<'a> From<&'a mut Command> for BootstrapCommand { fn from(command: &'a mut Command) -> Self { + // This is essentially a manual `Command::clone` + let mut cmd = Command::new(command.get_program()); + if let Some(dir) = command.get_current_dir() { + cmd.current_dir(dir); + } + cmd.args(command.get_args()); + for (key, value) in command.get_envs() { + match value { + Some(value) => { + cmd.env(key, value); + } + None => { + cmd.env_remove(key); + } + } + } + + cmd.into() + } +} + +/// This implementation is temporary, until all `Command` invocations are migrated to +/// `BootstrapCommand`. +impl<'a> From<&'a mut BootstrapCommand> for BootstrapCommand { + fn from(command: &'a mut BootstrapCommand) -> Self { + BootstrapCommand::from(&mut command.command) + } +} + +impl From for BootstrapCommand { + fn from(command: Command) -> Self { Self { command, failure_behavior: BehaviorOnFailure::Exit, output_mode: None } } } diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index 59b29eedb7971..adf18c0ace1b4 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -18,7 +18,7 @@ use crate::core::builder::Builder; use crate::core::config::{Config, TargetSelection}; use crate::LldMode; -pub use crate::utils::dylib::{dylib_path, dylib_path_var}; +pub use crate::utils::shared_helpers::{dylib_path, dylib_path_var}; #[cfg(test)] mod tests; @@ -47,10 +47,11 @@ macro_rules! t { } }; } +use crate::utils::exec::BootstrapCommand; pub use t; pub fn exe(name: &str, target: TargetSelection) -> String { - crate::utils::dylib::exe(name, &target.triple) + crate::utils::shared_helpers::exe(name, &target.triple) } /// Returns `true` if the file name given looks like a dynamic library. @@ -72,7 +73,7 @@ pub fn libdir(target: TargetSelection) -> &'static str { /// Adds a list of lookup paths to `cmd`'s dynamic library lookup path. /// If the dylib_path_var is already set for this cmd, the old value will be overwritten! -pub fn add_dylib_path(path: Vec, cmd: &mut Command) { +pub fn add_dylib_path(path: Vec, cmd: &mut BootstrapCommand) { let mut list = dylib_path(); for path in path { list.insert(0, path); @@ -81,7 +82,7 @@ pub fn add_dylib_path(path: Vec, cmd: &mut Command) { } /// Adds a list of lookup paths to `cmd`'s link library lookup path. -pub fn add_link_lib_path(path: Vec, cmd: &mut Command) { +pub fn add_link_lib_path(path: Vec, cmd: &mut BootstrapCommand) { let mut list = link_lib_path(); for path in path { list.insert(0, path); @@ -241,8 +242,9 @@ pub fn is_valid_test_suite_arg<'a, P: AsRef>( } } -pub fn check_run(cmd: &mut Command, print_cmd_on_fail: bool) -> bool { - let status = match cmd.status() { +// FIXME: get rid of this function +pub fn check_run(cmd: &mut BootstrapCommand, print_cmd_on_fail: bool) -> bool { + let status = match cmd.command.status() { Ok(status) => status, Err(e) => { println!("failed to execute command: {cmd:?}\nERROR: {e}"); @@ -437,7 +439,7 @@ pub fn linker_flags( } pub fn add_rustdoc_cargo_linker_args( - cmd: &mut Command, + cmd: &mut BootstrapCommand, builder: &Builder<'_>, target: TargetSelection, lld_threads: LldThreads, diff --git a/src/bootstrap/src/utils/mod.rs b/src/bootstrap/src/utils/mod.rs index cb535f0e1632a..53b41f1578060 100644 --- a/src/bootstrap/src/utils/mod.rs +++ b/src/bootstrap/src/utils/mod.rs @@ -6,11 +6,11 @@ pub(crate) mod cache; pub(crate) mod cc_detect; pub(crate) mod change_tracker; pub(crate) mod channel; -pub(crate) mod dylib; pub(crate) mod exec; pub(crate) mod helpers; pub(crate) mod job; #[cfg(feature = "build-metrics")] pub(crate) mod metrics; pub(crate) mod render_tests; +pub(crate) mod shared_helpers; pub(crate) mod tarball; diff --git a/src/bootstrap/src/utils/render_tests.rs b/src/bootstrap/src/utils/render_tests.rs index 5c9918bce32e1..2e99bc68a8b75 100644 --- a/src/bootstrap/src/utils/render_tests.rs +++ b/src/bootstrap/src/utils/render_tests.rs @@ -7,14 +7,18 @@ //! to reimplement all the rendering logic in this module because of that. use crate::core::builder::Builder; +use crate::utils::exec::BootstrapCommand; use std::io::{BufRead, BufReader, Read, Write}; -use std::process::{ChildStdout, Command, Stdio}; +use std::process::{ChildStdout, Stdio}; use std::time::Duration; use termcolor::{Color, ColorSpec, WriteColor}; const TERSE_TESTS_PER_LINE: usize = 88; -pub(crate) fn add_flags_and_try_run_tests(builder: &Builder<'_>, cmd: &mut Command) -> bool { +pub(crate) fn add_flags_and_try_run_tests( + builder: &Builder<'_>, + cmd: &mut BootstrapCommand, +) -> bool { if !cmd.get_args().any(|arg| arg == "--") { cmd.arg("--"); } @@ -23,7 +27,11 @@ pub(crate) fn add_flags_and_try_run_tests(builder: &Builder<'_>, cmd: &mut Comma try_run_tests(builder, cmd, false) } -pub(crate) fn try_run_tests(builder: &Builder<'_>, cmd: &mut Command, stream: bool) -> bool { +pub(crate) fn try_run_tests( + builder: &Builder<'_>, + cmd: &mut BootstrapCommand, + stream: bool, +) -> bool { if builder.config.dry_run() { return true; } @@ -41,7 +49,8 @@ pub(crate) fn try_run_tests(builder: &Builder<'_>, cmd: &mut Command, stream: bo } } -fn run_tests(builder: &Builder<'_>, cmd: &mut Command, stream: bool) -> bool { +fn run_tests(builder: &Builder<'_>, cmd: &mut BootstrapCommand, stream: bool) -> bool { + let cmd = &mut cmd.command; cmd.stdout(Stdio::piped()); builder.verbose(|| println!("running: {cmd:?}")); diff --git a/src/bootstrap/src/utils/shared_helpers.rs b/src/bootstrap/src/utils/shared_helpers.rs new file mode 100644 index 0000000000000..7150c84313c55 --- /dev/null +++ b/src/bootstrap/src/utils/shared_helpers.rs @@ -0,0 +1,112 @@ +//! This module serves two purposes: +//! 1. It is part of the `utils` module and used in other parts of bootstrap. +//! 2. It is embedded inside bootstrap shims to avoid a dependency on the bootstrap library. +//! Therefore, this module should never use any other bootstrap module. This reduces binary +//! size and improves compilation time by minimizing linking time. + +#![allow(dead_code)] + +use std::env; +use std::ffi::OsString; +use std::fs::OpenOptions; +use std::io::Write; +use std::process::Command; +use std::str::FromStr; + +#[cfg(test)] +mod tests; + +/// Returns the environment variable which the dynamic library lookup path +/// resides in for this platform. +pub fn dylib_path_var() -> &'static str { + if cfg!(target_os = "windows") { + "PATH" + } else if cfg!(target_vendor = "apple") { + "DYLD_LIBRARY_PATH" + } else if cfg!(target_os = "haiku") { + "LIBRARY_PATH" + } else if cfg!(target_os = "aix") { + "LIBPATH" + } else { + "LD_LIBRARY_PATH" + } +} + +/// Parses the `dylib_path_var()` environment variable, returning a list of +/// paths that are members of this lookup path. +pub fn dylib_path() -> Vec { + let var = match std::env::var_os(dylib_path_var()) { + Some(v) => v, + None => return vec![], + }; + std::env::split_paths(&var).collect() +} + +/// Given an executable called `name`, return the filename for the +/// executable for a particular target. +pub fn exe(name: &str, target: &str) -> String { + if target.contains("windows") { + format!("{name}.exe") + } else if target.contains("uefi") { + format!("{name}.efi") + } else { + name.to_string() + } +} + +/// Parses the value of the "RUSTC_VERBOSE" environment variable and returns it as a `usize`. +/// If it was not defined, returns 0 by default. +/// +/// Panics if "RUSTC_VERBOSE" is defined with the value that is not an unsigned integer. +pub fn parse_rustc_verbose() -> usize { + match env::var("RUSTC_VERBOSE") { + Ok(s) => usize::from_str(&s).expect("RUSTC_VERBOSE should be an integer"), + Err(_) => 0, + } +} + +/// Parses the value of the "RUSTC_STAGE" environment variable and returns it as a `String`. +/// +/// If "RUSTC_STAGE" was not set, the program will be terminated with 101. +pub fn parse_rustc_stage() -> String { + env::var("RUSTC_STAGE").unwrap_or_else(|_| { + // Don't panic here; it's reasonable to try and run these shims directly. Give a helpful error instead. + eprintln!("rustc shim: FATAL: RUSTC_STAGE was not set"); + eprintln!("rustc shim: NOTE: use `x.py build -vvv` to see all environment variables set by bootstrap"); + std::process::exit(101); + }) +} + +/// Writes the command invocation to a file if `DUMP_BOOTSTRAP_SHIMS` is set during bootstrap. +/// +/// Before writing it, replaces user-specific values to create generic dumps for cross-environment +/// comparisons. +pub fn maybe_dump(dump_name: String, cmd: &Command) { + if let Ok(dump_dir) = env::var("DUMP_BOOTSTRAP_SHIMS") { + let dump_file = format!("{dump_dir}/{dump_name}"); + + let mut file = OpenOptions::new().create(true).append(true).open(dump_file).unwrap(); + + let cmd_dump = format!("{:?}\n", cmd); + let cmd_dump = cmd_dump.replace(&env::var("BUILD_OUT").unwrap(), "${BUILD_OUT}"); + let cmd_dump = cmd_dump.replace(&env::var("CARGO_HOME").unwrap(), "${CARGO_HOME}"); + + file.write_all(cmd_dump.as_bytes()).expect("Unable to write file"); + } +} + +/// Finds `key` and returns its value from the given list of arguments `args`. +pub fn parse_value_from_args<'a>(args: &'a [OsString], key: &str) -> Option<&'a str> { + let mut args = args.iter(); + while let Some(arg) = args.next() { + let arg = arg.to_str().unwrap(); + + if let Some(value) = arg.strip_prefix(&format!("{key}=")) { + return Some(value); + } else if arg == key { + return args.next().map(|v| v.to_str().unwrap()); + } + } + + None +} diff --git a/src/bootstrap/src/utils/shared_helpers/tests.rs b/src/bootstrap/src/utils/shared_helpers/tests.rs new file mode 100644 index 0000000000000..da7924276f7c8 --- /dev/null +++ b/src/bootstrap/src/utils/shared_helpers/tests.rs @@ -0,0 +1,28 @@ +use super::parse_value_from_args; + +#[test] +fn test_parse_value_from_args() { + let args = vec![ + "--stage".into(), + "1".into(), + "--version".into(), + "2".into(), + "--target".into(), + "x86_64-unknown-linux".into(), + ]; + + assert_eq!(parse_value_from_args(args.as_slice(), "--stage").unwrap(), "1"); + assert_eq!(parse_value_from_args(args.as_slice(), "--version").unwrap(), "2"); + assert_eq!(parse_value_from_args(args.as_slice(), "--target").unwrap(), "x86_64-unknown-linux"); + assert!(parse_value_from_args(args.as_slice(), "random-key").is_none()); + + let args = vec![ + "app-name".into(), + "--key".into(), + "value".into(), + "random-value".into(), + "--sysroot=/x/y/z".into(), + ]; + assert_eq!(parse_value_from_args(args.as_slice(), "--key").unwrap(), "value"); + assert_eq!(parse_value_from_args(args.as_slice(), "--sysroot").unwrap(), "/x/y/z"); +} diff --git a/src/bootstrap/src/utils/tarball.rs b/src/bootstrap/src/utils/tarball.rs index fd934f18de23f..5cc319826dbf3 100644 --- a/src/bootstrap/src/utils/tarball.rs +++ b/src/bootstrap/src/utils/tarball.rs @@ -5,14 +5,12 @@ //! In uplifting, a tarball from Stage N captures essential components //! to assemble Stage N + 1 compiler. -use std::{ - path::{Path, PathBuf}, - process::Command, -}; +use std::path::{Path, PathBuf}; use crate::core::builder::Builder; use crate::core::{build_steps::dist::distdir, builder::Kind}; use crate::utils::channel; +use crate::utils::exec::BootstrapCommand; use crate::utils::helpers::{move_file, t}; #[derive(Copy, Clone)] @@ -300,7 +298,7 @@ impl<'a> Tarball<'a> { } } - fn non_bare_args(&self, cmd: &mut Command) { + fn non_bare_args(&self, cmd: &mut BootstrapCommand) { cmd.arg("--rel-manifest-dir=rustlib") .arg("--legacy-manifest-dirs=rustlib,cargo") .arg(format!("--product-name={}", self.product_name)) @@ -312,7 +310,7 @@ impl<'a> Tarball<'a> { .arg(distdir(self.builder)); } - fn run(self, build_cli: impl FnOnce(&Tarball<'a>, &mut Command)) -> GeneratedTarball { + fn run(self, build_cli: impl FnOnce(&Tarball<'a>, &mut BootstrapCommand)) -> GeneratedTarball { t!(std::fs::create_dir_all(&self.overlay_dir)); self.builder.create(&self.overlay_dir.join("version"), &self.overlay.version(self.builder)); if let Some(info) = self.builder.rust_info().info() { @@ -353,7 +351,7 @@ impl<'a> Tarball<'a> { }; cmd.args(["--compression-profile", compression_profile]); - self.builder.run(&mut cmd); + self.builder.run(cmd); // Ensure there are no symbolic links in the tarball. In particular, // rustup-toolchain-install-master and most versions of Windows can't handle symbolic links. diff --git a/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile index 55c737bd0aa31..d395665166365 100644 --- a/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile @@ -23,7 +23,30 @@ ENV CC_loongarch64_unknown_linux_gnu=loongarch64-unknown-linux-gnu-gcc \ AR_loongarch64_unknown_linux_gnu=loongarch64-unknown-linux-gnu-ar \ CXX_loongarch64_unknown_linux_gnu=loongarch64-unknown-linux-gnu-g++ +# We re-use the Linux toolchain for bare-metal, because upstream bare-metal +# target support for LoongArch is only available from GCC 14+. +# +# See: https://github.com/gcc-mirror/gcc/commit/976f4f9e4770 +ENV CC_loongarch64_unknown_none=loongarch64-unknown-linux-gnu-gcc \ + AR_loongarch64_unknown_none=loongarch64-unknown-linux-gnu-ar \ + CXX_loongarch64_unknown_none=loongarch64-unknown-linux-gnu-g++ \ + CFLAGS_loongarch64_unknown_none="-ffreestanding -mabi=lp64d" \ + CXXFLAGS_loongarch64_unknown_none="-ffreestanding -mabi=lp64d" \ + CC_loongarch64_unknown_none_softfloat=loongarch64-unknown-linux-gnu-gcc \ + AR_loongarch64_unknown_none_softfloat=loongarch64-unknown-linux-gnu-ar \ + CXX_loongarch64_unknown_none_softfloat=loongarch64-unknown-linux-gnu-g++ \ + CFLAGS_loongarch64_unknown_none_softfloat="-ffreestanding -mabi=lp64s -mfpu=none" \ + CXXFLAGS_loongarch64_unknown_none_softfloat="-ffreestanding -mabi=lp64s -mfpu=none" + ENV HOSTS=loongarch64-unknown-linux-gnu +ENV TARGETS=$HOSTS +ENV TARGETS=$TARGETS,loongarch64-unknown-none +ENV TARGETS=$TARGETS,loongarch64-unknown-none-softfloat + +ENV RUST_CONFIGURE_ARGS \ + --enable-extended \ + --enable-full-tools \ + --enable-profiler \ + --disable-docs -ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs -ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS +ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $TARGETS diff --git a/src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile b/src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile index 560adf971ba48..62dbfaaa67315 100644 --- a/src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile @@ -27,7 +27,8 @@ ENV HOSTS=loongarch64-unknown-linux-musl ENV RUST_CONFIGURE_ARGS \ --enable-extended \ - --enable-lld \ + --enable-full-tools \ + --enable-profiler \ --disable-docs \ --set target.loongarch64-unknown-linux-musl.crt-static=false \ --musl-root-loongarch64=/x-tools/loongarch64-unknown-linux-musl/loongarch64-unknown-linux-musl/sysroot/usr 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 bb6254942cbab..e3cb396b78297 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile @@ -121,8 +121,6 @@ ENV TARGETS=$TARGETS,armv7-unknown-linux-gnueabi ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabi ENV TARGETS=$TARGETS,i686-unknown-freebsd ENV TARGETS=$TARGETS,x86_64-unknown-none -ENV TARGETS=$TARGETS,loongarch64-unknown-none -ENV TARGETS=$TARGETS,loongarch64-unknown-none-softfloat ENV TARGETS=$TARGETS,aarch64-unknown-uefi ENV TARGETS=$TARGETS,i686-unknown-uefi ENV TARGETS=$TARGETS,x86_64-unknown-uefi diff --git a/src/ci/docker/host-x86_64/dist-x86_64-netbsd/build-netbsd-toolchain.sh b/src/ci/docker/host-x86_64/dist-x86_64-netbsd/build-netbsd-toolchain.sh index e0c008b76fa8b..4a42f5da29fcc 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-netbsd/build-netbsd-toolchain.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-netbsd/build-netbsd-toolchain.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # ignore-tidy-linelength -set -ex +set -eux hide_output() { set +x @@ -20,6 +20,22 @@ exit 1 set -x } +# Download, verify SHA512, and remove the downloaded file +# Usage: +download() { + fname="$1" + shift + url="$1" + shift + sha="$1" + shift + + curl "$url" -o "$fname" + echo "$sha $fname" | shasum -a 512 --check || exit 1 + "$@" + rm "$fname" +} + mkdir netbsd cd netbsd @@ -27,17 +43,31 @@ mkdir -p /x-tools/x86_64-unknown-netbsd/sysroot # URL=https://ci-mirrors.rust-lang.org/rustc -SOURCE_URL=https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.0/source/sets -curl $SOURCE_URL/src.tgz | tar xzf - -curl $SOURCE_URL/gnusrc.tgz | tar xzf - -curl $SOURCE_URL/sharesrc.tgz | tar xzf - -curl $SOURCE_URL/syssrc.tgz | tar xzf - - -BINARY_URL=https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.0/amd64/binary/sets -curl $BINARY_URL/base.tar.xz | \ - tar xJf - -C /x-tools/x86_64-unknown-netbsd/sysroot ./usr/include ./usr/lib ./lib -curl $BINARY_URL/comp.tar.xz | \ - tar xJf - -C /x-tools/x86_64-unknown-netbsd/sysroot ./usr/include ./usr/lib +# Hashes come from https://cdn.netbsd.org/pub/NetBSD/security/hashes/NetBSD-9.0_hashes.asc +SRC_SHA=2c791ae009a6929c6fc893ec5df7e62910ee8207e0b2159d6937309c03efe175b6ae1e445829a13d041b6851334ad35c521f2fa03c97675d4a05f1fafe58ede0 +GNUSRC_SHA=3710085a73feecf6a843415271ec794c90146b03f6bbd30f07c9e0c79febf8995d557e40194f1e05db655e4f5ef2fae97563f8456fceaae65d4ea98857a83b1c +SHARESRC_SHA=f080776ed82c3ac5d6272dee39746f87897d8e6984996caf5bf6d87bf11d9c9e0c1ad5c437c21258bd278bb6fd76974946e878f548517885f71c556096231369 +SYSSRC_SHA=60b9ddf4cc6402256473e2e1eefeabd9001aa4e205208715ecc6d6fc3f5b400e469944580077271b8e80562a4c2f601249e69e07a504f46744e0c50335f1cbf1 +BASE_SHA=b5926b107cebf40c3c19b4f6cd039b610987dd7f819e7cdde3bd1e5230a856906e7930b15ab242d52ced9f0bda01d574be59488b8dbb95fa5df2987d0a70995f +COMP_SHA=38ea54f30d5fc2afea87e5096f06873e00182789e8ad9cec0cb3e9f7c538c1aa4779e63fd401a36ba02676158e83fa5c95e8e87898db59c1914fb206aecd82d2 + +# FIXME: the archive URL is being used temporarily while the CDN is down. +# We should serve this from our own CDN +# SOURCE_URL=https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.0/source/sets +SOURCE_URL=http://archive.netbsd.org/pub/NetBSD-archive/NetBSD-9.0/source/sets +download src.tgz "$SOURCE_URL/src.tgz" "$SRC_SHA" tar xzf src.tgz +download gnusrc.tgz "$SOURCE_URL/gnusrc.tgz" "$GNUSRC_SHA" tar xzf gnusrc.tgz +download sharesrc.tgz "$SOURCE_URL/sharesrc.tgz" "$SHARESRC_SHA" tar xzf sharesrc.tgz +download syssrc.tgz "$SOURCE_URL/syssrc.tgz" "$SYSSRC_SHA" tar xzf syssrc.tgz + +# FIXME: the archive URL is being used temporarily while the CDN is down. +# We should serve this from our own CDN +# BINARY_URL=https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.0/amd64/binary/sets +BINARY_URL=http://archive.netbsd.org/pub/NetBSD-archive/NetBSD-9.0/amd64/binary/sets +download base.tar.xz "$BINARY_URL/base.tar.xz" "$BASE_SHA" \ + tar xJf base.tar.xz -C /x-tools/x86_64-unknown-netbsd/sysroot ./usr/include ./usr/lib ./lib +download comp.tar.xz "$BINARY_URL/comp.tar.xz" "$COMP_SHA" \ + tar xJf comp.tar.xz -C /x-tools/x86_64-unknown-netbsd/sysroot ./usr/include ./usr/lib cd usr/src diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-integration/Dockerfile b/src/ci/docker/host-x86_64/x86_64-fuchsia/Dockerfile similarity index 88% rename from src/ci/docker/host-x86_64/x86_64-gnu-integration/Dockerfile rename to src/ci/docker/host-x86_64/x86_64-fuchsia/Dockerfile index a944f370c6b30..ba3e8bdb68754 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-integration/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-fuchsia/Dockerfile @@ -1,5 +1,6 @@ # This job builds a toolchain capable of building Fuchsia, and then builds -# Fuchsia. See the build-fuchsia.sh script in this directory for more details. +# Fuchsia as an integration test of the toolchain. See the build-fuchsia.sh +# script in this directory for more details. FROM ubuntu:22.04 @@ -24,7 +25,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ && rm -rf /var/lib/apt/lists/* # Duplicated in dist-various-2 Dockerfile. -# FIXME: Move to canonical triple ENV \ AR_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-ar \ CC_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-clang \ @@ -48,10 +48,6 @@ ENV CARGO_TARGET_X86_64_UNKNOWN_FUCHSIA_RUSTFLAGS \ ENV TARGETS=x86_64-unknown-fuchsia ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnu -ENV TARGETS=$TARGETS,wasm32-unknown-unknown - -# Fuchsia clang does not have wasm target enabled, use system clang. -ENV CC_wasm32_unknown_unknown=clang-15 COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh @@ -76,4 +72,4 @@ ENV RUST_CONFIGURE_ARGS \ --set target.x86_64-unknown-fuchsia.linker=/usr/local/bin/ld.lld ENV SCRIPT \ python3 ../x.py install --target $TARGETS compiler/rustc library/std clippy && \ - bash ../src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh + bash ../src/ci/docker/host-x86_64/x86_64-fuchsia/build-fuchsia.sh diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh b/src/ci/docker/host-x86_64/x86_64-fuchsia/build-fuchsia.sh similarity index 89% rename from src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh rename to src/ci/docker/host-x86_64/x86_64-fuchsia/build-fuchsia.sh index 2bb1d0a633871..c806b886dae8f 100755 --- a/src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh +++ b/src/ci/docker/host-x86_64/x86_64-fuchsia/build-fuchsia.sh @@ -5,14 +5,14 @@ # # You may run this script locally using Docker with the following command: # -# $ src/ci/docker/run.sh x86_64-gnu-integration +# $ src/ci/docker/run.sh x86_64-fuchsia # # Alternatively, from within the container with --dev, assuming you have made it # as far as building the toolchain with the above command: # -# $ src/ci/docker/run.sh --dev x86_64-gnu-integration +# $ src/ci/docker/run.sh --dev x86_64-fuchsia # docker# git config --global --add safe.directory /checkout/obj/fuchsia -# docker# ../src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh +# docker# ../src/ci/docker/host-x86_64/x86_64-fuchsia/build-fuchsia.sh # # Also see the docs in the rustc-dev-guide for more info: # https://github.com/rust-lang/rustc-dev-guide/pull/1989 @@ -21,7 +21,7 @@ set -euf -o pipefail # Set this variable to 1 to disable updating the Fuchsia checkout. This is # useful for making local changes. You can find the Fuchsia checkout in -# `obj/x86_64-gnu-integration/fuchsia` in your local checkout after running this +# `obj/x86_64-fuchsia/fuchsia` in your local checkout after running this # job for the first time. KEEP_CHECKOUT= @@ -35,7 +35,7 @@ PICK_REFS=() # commit hash of fuchsia.git and some other repos in the "monorepo" checkout, in # addition to versions of prebuilts. It should be bumped regularly by the # Fuchsia team – we aim for every 1-2 months. -INTEGRATION_SHA=737ebdd83afa47b742ca8325fad0176952fcefbd +INTEGRATION_SHA=d1d2f20efe46e22be179953dd6726c96eced54ab checkout=fuchsia jiri=.jiri_root/bin/jiri diff --git a/src/ci/docker/host-x86_64/rfl/Dockerfile b/src/ci/docker/host-x86_64/x86_64-rust-for-linux/Dockerfile similarity index 100% rename from src/ci/docker/host-x86_64/rfl/Dockerfile rename to src/ci/docker/host-x86_64/x86_64-rust-for-linux/Dockerfile diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index e3903c3dd5a1f..a6e12c6ff954d 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -208,6 +208,18 @@ auto: - image: test-various <<: *job-linux-4c + - image: x86_64-fuchsia + # Only run this job on the nightly channel. Fuchsia requires + # nightly features to compile, and this job would fail if + # executed on beta and stable. + only_on_channel: nightly + <<: *job-linux-8c + + # Tests integration with Rust for Linux. + # Builds stage 1 compiler and tries to compile a few RfL examples with it. + - image: x86_64-rust-for-linux + <<: *job-linux-8c + - image: x86_64-gnu <<: *job-linux-4c @@ -229,13 +241,6 @@ auto: - image: x86_64-gnu-aux <<: *job-linux-4c - - image: x86_64-gnu-integration - # Only run this job on the nightly channel. Fuchsia requires - # nightly features to compile, and this job would fail if - # executed on beta and stable. - only_on_channel: nightly - <<: *job-linux-8c - - image: x86_64-gnu-debug <<: *job-linux-4c @@ -465,8 +470,3 @@ auto: RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler SCRIPT: python x.py dist bootstrap --include-default-paths <<: *job-windows-8c - - # Tests integration with Rust for Linux. - # Builds stage 1 compiler and tries to compile a few RfL examples with it. - - image: rfl - <<: *job-linux-8c diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 71dc8c4ca0f92..f5cd4bd217a32 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -168,12 +168,12 @@ target | std | notes `i686-unknown-freebsd` | ✓ | 32-bit FreeBSD [^x86_32-floats-return-ABI] `i686-unknown-linux-musl` | ✓ | 32-bit Linux with musl 1.2.3 [^x86_32-floats-return-ABI] [`i686-unknown-uefi`](platform-support/unknown-uefi.md) | ? | 32-bit UEFI -[`loongarch64-unknown-none`](platform-support/loongarch-none.md) | * | | LoongArch64 Bare-metal (LP64D ABI) -[`loongarch64-unknown-none-softfloat`](platform-support/loongarch-none.md) | * | | LoongArch64 Bare-metal (LP64S ABI) +[`loongarch64-unknown-none`](platform-support/loongarch-none.md) | * | LoongArch64 Bare-metal (LP64D ABI) +[`loongarch64-unknown-none-softfloat`](platform-support/loongarch-none.md) | * | LoongArch64 Bare-metal (LP64S ABI) [`nvptx64-nvidia-cuda`](platform-support/nvptx64-nvidia-cuda.md) | * | --emit=asm generates PTX code that [runs on NVIDIA GPUs] [`riscv32imac-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | Bare RISC-V (RV32IMAC ISA) [`riscv32i-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | Bare RISC-V (RV32I ISA) -[`riscv32im-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | | Bare RISC-V (RV32IM ISA) +[`riscv32im-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | Bare RISC-V (RV32IM ISA) [`riscv32imc-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | Bare RISC-V (RV32IMC ISA) [`riscv32imafc-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | Bare RISC-V (RV32IMAFC ISA) `riscv64gc-unknown-none-elf` | * | Bare RISC-V (RV64IMAFDC ISA) @@ -193,7 +193,7 @@ target | std | notes `wasm32-unknown-unknown` | ✓ | WebAssembly `wasm32-wasi` | ✓ | WebAssembly with WASI (undergoing a [rename to `wasm32-wasip1`][wasi-rename]) [`wasm32-wasip1`](platform-support/wasm32-wasip1.md) | ✓ | WebAssembly with WASI -[`wasm32-wasip1-threads`](platform-support/wasm32-wasip1-threads.md) | ✓ | | WebAssembly with WASI Preview 1 and threads +[`wasm32-wasip1-threads`](platform-support/wasm32-wasip1-threads.md) | ✓ | WebAssembly with WASI Preview 1 and threads [`x86_64-apple-ios`](platform-support/apple-ios.md) | ✓ | 64-bit x86 iOS [`x86_64-fortanix-unknown-sgx`](platform-support/x86_64-fortanix-unknown-sgx.md) | ✓ | [Fortanix ABI] for 64-bit Intel SGX `x86_64-fuchsia` | ✓ | Alias for `x86_64-unknown-fuchsia` diff --git a/src/doc/rustc/src/platform-support/loongarch-linux.md b/src/doc/rustc/src/platform-support/loongarch-linux.md index e8f55b8bfce10..45eb0a81216d8 100644 --- a/src/doc/rustc/src/platform-support/loongarch-linux.md +++ b/src/doc/rustc/src/platform-support/loongarch-linux.md @@ -1,30 +1,24 @@ -# loongarch\*-unknown-linux-\* +# `loongarch*-unknown-linux-*` -**Tier: 2** +**Tier: 2 (with Host Tools)** -[LoongArch] is a new RISC ISA developed by Loongson Technology Corporation Limited. +[LoongArch][la-docs] Linux targets. +LoongArch is a RISC ISA developed by Loongson Technology Corporation Limited. -[LoongArch]: https://loongson.github.io/LoongArch-Documentation/README-EN.html +| Target | Description | +|--------|-------------| +| `loongarch64-unknown-linux-gnu` | LoongArch64 Linux, LP64D ABI (kernel 5.19, glibc 2.36) | +| `loongarch64-unknown-linux-musl` | LoongArch64 Linux, LP64D ABI (kernel 5.19, musl 1.2.5) | -The target name follow this format: `--`, where `` specifies the CPU family/model, `` specifies the vendor and `` the operating system name. -While the integer base ABI is implied by the machine field, the floating point base ABI type is encoded into the os field of the specifier using the string suffix ``. +These support both native and cross builds, and have full support for `std`. -| `` | `Description` | -|------------------------|--------------------------------------------------------------------| -| f64 | The base ABI use 64-bits FPRs for parameter passing. (lp64d)| -| f32 | The base ABI uses 32-bit FPRs for parameter passing. (lp64f)| -| sf | The base ABI uses no FPR for parameter passing. (lp64s) | +Reference material: -
+* [LoongArch ISA manuals][la-docs] +* [Application Binary Interface for the LoongArch™ Architecture][la-abi-specs] -|`ABI type(Base ABI/ABI extension)`| `C library` | `kernel` | `target tuple` | -|----------------------------------|-------------|----------|----------------------------------| -| lp64d/base | glibc | linux | loongarch64-unknown-linux-gnu | -| lp64f/base | glibc | linux | loongarch64-unknown-linux-gnuf32 | -| lp64s/base | glibc | linux | loongarch64-unknown-linux-gnusf | -| lp64d/base | musl libc | linux | loongarch64-unknown-linux-musl| -| lp64f/base | musl libc | linux | loongarch64-unknown-linux-muslf32| -| lp64s/base | musl libc | linux | loongarch64-unknown-linux-muslsf | +[la-abi-specs]: https://github.com/loongson/la-abi-specs +[la-docs]: https://loongson.github.io/LoongArch-Documentation/README-EN.html ## Target maintainers @@ -35,23 +29,57 @@ While the integer base ABI is implied by the machine field, the floating po ## Requirements -This target is cross-compiled. -A GNU toolchain for LoongArch target is required. It can be downloaded from https://github.com/loongson/build-tools/releases, or built from the source code of GCC (12.1.0 or later) and Binutils (2.40 or later). +### OS Version -## Building the target +The minimum supported Linux version is 5.19. -The target can be built by enabling it for a `rustc` build. +Some Linux distributions, mostly commercial ones, may provide forked Linux +kernels that has a version number less than 5.19 for their LoongArch ports. +Such kernels may still get patched to be compatible with the upstream Linux +5.19 UAPI, therefore supporting the targets described in this document, but +this is not always the case. The `rustup` installer contains a check for this, +and will abort if incompatibility is detected. + +### Host toolchain + +The targets require a reasonably up-to-date LoongArch toolchain on the host. +Currently the following components are used by the Rust CI to build the target, +and the versions can be seen as the minimum requirement: + +* GNU Binutils 2.40 +* GCC 13.x +* glibc 2.36 +* linux-headers 5.19 + +Of these, glibc and linux-headers are at their respective earliest versions with +mainline LoongArch support, so it is impossible to use older versions of these. +Older versions of Binutils and GCC will not work either, due to lack of support +for newer LoongArch ELF relocation types, among other features. + +Recent LLVM/Clang toolchains may be able to build the targets, but are not +currently being actively tested. + +## Building + +These targets are distributed through `rustup`, and otherwise require no +special configuration. + +If you need to build your own Rust for some reason though, the targets can be +simply enabled in `config.toml`. For example: ```toml [build] target = ["loongarch64-unknown-linux-gnu"] ``` -Make sure `loongarch64-unknown-linux-gnu-gcc` can be searched from the directories specified in`$PATH`. Alternatively, you can use GNU LoongArch Toolchain by adding the following to `config.toml`: +Make sure the LoongArch toolchain binaries are reachable from `$PATH`. +Alternatively, you can explicitly configure the paths in `config.toml`: ```toml [target.loongarch64-unknown-linux-gnu] -# ADJUST THIS PATH TO POINT AT YOUR TOOLCHAIN +# Adjust the paths to point at your toolchain +# Suppose the toolchain is placed at /TOOLCHAIN_PATH, and the cross prefix is +# "loongarch64-unknown-linux-gnu-": cc = "/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-gcc" cxx = "/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-g++" ar = "/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-ar" @@ -59,36 +87,51 @@ ranlib = "/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-ranlib" linker = "/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-gcc" ``` -## Cross-compilation +### Cross-compilation -This target can be cross-compiled on a `x86_64-unknown-linux-gnu` host. Cross-compilation on other hosts may work but is not tested. +This target can be cross-compiled on a `x86_64-unknown-linux-gnu` host. +Other hosts are also likely to work, but not actively tested. + +You can test the cross build directly on the host, thanks to QEMU linux-user emulation. +An example is given below: + +```sh +# Suppose the cross toolchain is placed at $TOOLCHAIN_PATH, with a cross prefix +# of "loongarch64-unknown-linux-gnu-". +export CC_loongarch64_unknown_linux_gnu="$TOOLCHAIN_PATH"/bin/loongarch64-unknown-linux-gnu-gcc +export CXX_loongarch64_unknown_linux_gnu="$TOOLCHAIN_PATH"/bin/loongarch64-unknown-linux-gnu-g++ +export AR_loongarch64_unknown_linux_gnu="$TOOLCHAIN_PATH"/bin/loongarch64-unknown-linux-gnu-gcc-ar +export CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNU_LINKER="$TOOLCHAIN_PATH"/bin/loongarch64-unknown-linux-gnu-gcc + +# Point qemu-loongarch64 to the LoongArch sysroot. +# Suppose the sysroot is located at "sysroot" below the toolchain root: +export CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNU_RUNNER="qemu-loongarch64 -L $TOOLCHAIN_PATH/sysroot" +# Or alternatively, if binfmt_misc is set up for running LoongArch binaries +# transparently: +export QEMU_LD_PREFIX="$TOOLCHAIN_PATH"/sysroot -## Testing -To test a cross-compiled binary on your build system, install the qemu binary that supports the LoongArch architecture and execute the following commands. -```text -CC_loongarch64_unknown_linux_gnu=/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-gcc \ -CXX_loongarch64_unknown_linux_gnu=/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-g++ \ -AR_loongarch64_unknown_linux_gnu=/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-gcc-ar \ -CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNUN_LINKER=/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-gcc \ -# SET TARGET SYSTEM LIBRARY PATH -CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNUN_RUNNER="qemu-loongarch64 -L /TOOLCHAIN_PATH/TARGET_LIBRARY_PATH" \ cargo run --target loongarch64-unknown-linux-gnu --release ``` -Tested on x86 architecture, other architectures not tested. -## Building Rust programs +## Testing + +There are no special requirements for testing and running the targets. +For testing cross builds on the host, please refer to the "Cross-compilation" +section above. -Rust does not yet ship pre-compiled artifacts for this target. To compile for this target, you will either need to build Rust with the target enabled (see "Building the target" above), or build your own copy of `std` by using `build-std` or similar. +## Building Rust programs -If `rustc` has support for that target and the library artifacts are available, then Rust static libraries can be built for that target: +As the targets are available through `rustup`, it is very easy to build Rust +programs for these targets: same as with other architectures. +Note that you will need a LoongArch C/C++ toolchain for linking, or if you want +to compile C code along with Rust (such as for Rust crates with C dependencies). -```shell -$ rustc --target loongarch64-unknown-linux-gnu your-code.rs --crate-type staticlib -$ ls libyour_code.a +```sh +rustup target add loongarch64-unknown-linux-gnu +cargo build --target loongarch64-unknown-linux-gnu ``` -On Rust Nightly it's possible to build without the target artifacts available: +Availability of pre-built artifacts through `rustup` are as follows: -```text -cargo build -Z build-std --target loongarch64-unknown-linux-gnu -``` +* `loongarch64-unknown-linux-gnu`: since Rust 1.71; +* `loongarch64-unknown-linux-musl`: since Rust 1.81. diff --git a/src/doc/rustc/src/platform-support/loongarch-none.md b/src/doc/rustc/src/platform-support/loongarch-none.md index 68d7c9d85e444..110a7cc3424d4 100644 --- a/src/doc/rustc/src/platform-support/loongarch-none.md +++ b/src/doc/rustc/src/platform-support/loongarch-none.md @@ -4,10 +4,10 @@ Freestanding/bare-metal LoongArch64 binaries in ELF format: firmware, kernels, etc. -| Target | Descriptions | -|------------------------------------|-------------------------------------------------------| -| loongarch64-unknown-none | LoongArch 64-bit, LP64D ABI (freestanding, hardfloat) | -| loongarch64-unknown-none-softfloat | LoongArch 64-bit, LP64S ABI (freestanding, softfloat) | +| Target | Description | +|--------|-------------| +| `loongarch64-unknown-none` | LoongArch 64-bit, LP64D ABI (freestanding, hard-float) | +| `loongarch64-unknown-none-softfloat` | LoongArch 64-bit, LP64S ABI (freestanding, soft-float) | ## Target maintainers @@ -19,6 +19,8 @@ Freestanding/bare-metal LoongArch64 binaries in ELF format: firmware, kernels, e This target is cross-compiled. There is no support for `std`. There is no default allocator, but it's possible to use `alloc` by supplying an allocator. +The `*-softfloat` target does not assume existence of FPU or any other LoongArch +ISA extension, and does not make use of any non-GPR register. This allows the generated code to run in environments, such as kernels, which may need to avoid the use of such registers or which may have special considerations about the use of such registers (e.g. saving and restoring them to avoid breaking @@ -26,54 +28,64 @@ userspace code using the same registers). You can change code generation to use additional CPU features via the `-C target-feature=` codegen options to rustc, or via the `#[target_feature]` mechanism within Rust code. -By default, code generated with this target should run on any `loongarch` -hardware; enabling additional target features may raise this baseline. +By default, code generated with the soft-float target should run on any +LoongArch64 hardware, with the hard-float target additionally requiring an FPU; +enabling additional target features may raise this baseline. -Code generated with this target will use the `small` code model by default. +Code generated with the targets will use the `small` code model by default. You can change this using the `-C code-model=` option to rustc. -On `loongarch64-unknown-none*`, `extern "C"` uses the [standard calling -convention](https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html). +On `loongarch64-unknown-none*`, `extern "C"` uses the [architecture's standard calling convention][lapcs]. -This target generates binaries in the ELF format. Any alternate formats or +[lapcs]: https://github.com/loongson/la-abi-specs/blob/release/lapcs.adoc + +The targets generate binaries in the ELF format. Any alternate formats or special considerations for binary layout will require linker options or linker scripts. ## Building the target -You can build Rust with support for the target by adding it to the `target` +You can build Rust with support for the targets by adding them to the `target` list in `config.toml`: ```toml [build] build-stage = 1 -target = ["loongarch64-unknown-none"] +target = [ + "loongarch64-unknown-none", + "loongarch64-unknown-none-softfloat", +] ``` +## Testing + +As the targets support a variety of different environments and do not support +`std`, they do not support running the Rust test suite. + ## Building Rust programs -```text +Starting with Rust 1.74, precompiled artifacts are provided via `rustup`: + +```sh +# install cross-compile toolchain +rustup target add loongarch64-unknown-none # target flag may be used with any cargo or rustc command cargo build --target loongarch64-unknown-none ``` -## Testing - -As `loongarch64-unknown-none*` supports a variety of different environments and does -not support `std`, this target does not support running the Rust test suite. - ## Cross-compilation toolchains and C code -If you want to compile C code along with Rust (such as for Rust crates with C -dependencies), you will need an appropriate `loongarch` toolchain. +For cross builds, you will need an appropriate LoongArch C/C++ toolchain for +linking, or if you want to compile C code along with Rust (such as for Rust +crates with C dependencies). Rust *may* be able to use an `loongarch64-unknown-linux-gnu-` toolchain with appropriate standalone flags to build for this toolchain (depending on the assumptions of that toolchain, see below), or you may wish to use a separate `loongarch64-unknown-none` toolchain. -On some `loongarch` hosts that use ELF binaries, you *may* be able to use the host +On some LoongArch hosts that use ELF binaries, you *may* be able to use the host C toolchain, if it does not introduce assumptions about the host environment that don't match the expectations of a standalone environment. Otherwise, you may need a separate toolchain for standalone/freestanding development, just as -when cross-compiling from a non-`loongarch` platform. +when cross-compiling from a non-LoongArch platform. diff --git a/src/doc/style-guide/src/nightly.md b/src/doc/style-guide/src/nightly.md index 66e7fa3c9f89c..d870edf18882e 100644 --- a/src/doc/style-guide/src/nightly.md +++ b/src/doc/style-guide/src/nightly.md @@ -5,3 +5,15 @@ This chapter documents style and formatting for nightly-only syntax. The rest of Style and formatting for nightly-only syntax should be removed from this chapter and integrated into the appropriate sections of the style guide at the time of stabilization. There is no guarantee of the stability of this chapter in contrast to the rest of the style guide. Refer to the style team policy for nightly formatting procedure regarding breaking changes to this chapter. + +### `feature(precise_capturing)` + +A `use<'a, T>` precise capturing bound is formatted as if it were a single path segment with non-turbofished angle-bracketed args, like a trait bound whose identifier is `use`. + +``` +fn foo() -> impl Sized + use<'a> {} + +// is formatted analogously to: + +fn foo() -> impl Sized + Use<'a> {} +``` diff --git a/src/etc/completions/x.py.fish b/src/etc/completions/x.py.fish index 2072f76a48181..805fc8aa8ccd0 100644 --- a/src/etc/completions/x.py.fish +++ b/src/etc/completions/x.py.fish @@ -48,7 +48,7 @@ complete -c x.py -n "__fish_use_subcommand" -f -a "run" -d 'Run tools contained complete -c x.py -n "__fish_use_subcommand" -f -a "setup" -d 'Set up the environment for development' complete -c x.py -n "__fish_use_subcommand" -f -a "suggest" -d 'Suggest a subset of tests to run, based on modified files' complete -c x.py -n "__fish_use_subcommand" -f -a "vendor" -d 'Vendor dependencies' -complete -c x.py -n "__fish_use_subcommand" -f -a "perf" -d 'Perform profiling and benchmarking of the compiler using the `rustc-perf` benchmark suite' +complete -c x.py -n "__fish_use_subcommand" -f -a "perf" -d 'Perform profiling and benchmarking of the compiler using the `rustc-perf-wrapper` tool' complete -c x.py -n "__fish_seen_subcommand_from build" -l config -d 'TOML configuration file for build' -r -F complete -c x.py -n "__fish_seen_subcommand_from build" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_seen_subcommand_from build" -l build -d 'build target of the stage0 compiler' -r -f diff --git a/src/etc/completions/x.py.ps1 b/src/etc/completions/x.py.ps1 index 919382d441ffc..ce590d2fa4897 100644 --- a/src/etc/completions/x.py.ps1 +++ b/src/etc/completions/x.py.ps1 @@ -75,7 +75,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('setup', 'setup', [CompletionResultType]::ParameterValue, 'Set up the environment for development') [CompletionResult]::new('suggest', 'suggest', [CompletionResultType]::ParameterValue, 'Suggest a subset of tests to run, based on modified files') [CompletionResult]::new('vendor', 'vendor', [CompletionResultType]::ParameterValue, 'Vendor dependencies') - [CompletionResult]::new('perf', 'perf', [CompletionResultType]::ParameterValue, 'Perform profiling and benchmarking of the compiler using the `rustc-perf` benchmark suite') + [CompletionResult]::new('perf', 'perf', [CompletionResultType]::ParameterValue, 'Perform profiling and benchmarking of the compiler using the `rustc-perf-wrapper` tool') break } 'x.py;build' { diff --git a/src/etc/completions/x.py.zsh b/src/etc/completions/x.py.zsh index bbebf8b892d1f..fc8be4f788127 100644 --- a/src/etc/completions/x.py.zsh +++ b/src/etc/completions/x.py.zsh @@ -856,7 +856,7 @@ _x.py_commands() { 'setup:Set up the environment for development' \ 'suggest:Suggest a subset of tests to run, based on modified files' \ 'vendor:Vendor dependencies' \ -'perf:Perform profiling and benchmarking of the compiler using the \`rustc-perf\` benchmark suite' \ +'perf:Perform profiling and benchmarking of the compiler using the \`rustc-perf-wrapper\` tool' \ ) _describe -t commands 'x.py commands' commands "$@" } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 22565ea402803..b5660cd849246 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -549,7 +549,7 @@ fn clean_generic_param_def<'tcx>( }, ) } - ty::GenericParamDefKind::Const { has_default, is_host_effect } => ( + ty::GenericParamDefKind::Const { has_default, synthetic, is_host_effect: _ } => ( def.name, GenericParamDefKind::Const { ty: Box::new(clean_middle_ty( @@ -572,7 +572,7 @@ fn clean_generic_param_def<'tcx>( } else { None }, - is_host_effect, + synthetic, }, ), }; @@ -628,13 +628,13 @@ fn clean_generic_param<'tcx>( }, ) } - hir::GenericParamKind::Const { ty, default, is_host_effect } => ( + hir::GenericParamKind::Const { ty, default, synthetic, is_host_effect: _ } => ( param.name.ident().name, GenericParamDefKind::Const { ty: Box::new(clean_ty(ty, cx)), default: default .map(|ct| Box::new(ty::Const::from_anon_const(cx.tcx, ct.def_id).to_string())), - is_host_effect, + synthetic, }, ), }; @@ -1411,7 +1411,11 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( let mut generics = clean_ty_generics( cx, tcx.generics_of(assoc_item.def_id), - ty::GenericPredicates { parent: None, predicates }, + ty::GenericPredicates { + parent: None, + predicates, + effects_min_tys: ty::List::empty(), + }, ); simplify::move_bounds_to_generic_parameters(&mut generics); diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index af61eb6ae8de8..58eef36677b23 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -113,7 +113,7 @@ fn trait_is_same_or_supertrait(cx: &DocContext<'_>, child: DefId, trait_: DefId) if child == trait_ { return true; } - let predicates = cx.tcx.super_predicates_of(child); + let predicates = cx.tcx.explicit_super_predicates_of(child); debug_assert!(cx.tcx.generics_of(child).has_self); let self_ty = cx.tcx.types.self_param; predicates diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index c4020f2a450bc..9050a1c12078b 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1321,7 +1321,7 @@ pub(crate) enum GenericParamDefKind { Lifetime { outlives: ThinVec }, Type { bounds: ThinVec, default: Option>, synthetic: bool }, // Option> makes this type smaller than `Option` would. - Const { ty: Box, default: Option>, is_host_effect: bool }, + Const { ty: Box, default: Option>, synthetic: bool }, } impl GenericParamDefKind { @@ -1345,7 +1345,7 @@ impl GenericParamDef { pub(crate) fn is_synthetic_param(&self) -> bool { match self.kind { GenericParamDefKind::Lifetime { .. } => false, - GenericParamDefKind::Const { is_host_effect, .. } => is_host_effect, + GenericParamDefKind::Const { synthetic: is_host_effect, .. } => is_host_effect, GenericParamDefKind::Type { synthetic, .. } => synthetic, } } diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index d099a97f1cba2..b965ab019cc4f 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -466,7 +466,7 @@ impl FromWithTcx for GenericParamDefKind { default: default.map(|x| (*x).into_tcx(tcx)), synthetic, }, - Const { ty, default, is_host_effect: _ } => GenericParamDefKind::Const { + Const { ty, default, synthetic: _ } => GenericParamDefKind::Const { type_: (*ty).into_tcx(tcx), default: default.map(|x| *x), }, @@ -501,14 +501,12 @@ impl FromWithTcx for WherePredicate { synthetic, } } - clean::GenericParamDefKind::Const { - ty, - default, - is_host_effect: _, - } => GenericParamDefKind::Const { - type_: (*ty).into_tcx(tcx), - default: default.map(|d| *d), - }, + clean::GenericParamDefKind::Const { ty, default, synthetic: _ } => { + GenericParamDefKind::Const { + type_: (*ty).into_tcx(tcx), + default: default.map(|d| *d), + } + } }; GenericParamDef { name, kind } }) diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 440b02a1fa75b..37f7e7ed38518 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1507,6 +1507,15 @@ impl Disambiguator { fn from_str(link: &str) -> Result, (String, Range)> { use Disambiguator::{Kind, Namespace as NS, Primitive}; + let suffixes = [ + // If you update this list, please also update the relevant rustdoc book section! + ("!()", DefKind::Macro(MacroKind::Bang)), + ("!{}", DefKind::Macro(MacroKind::Bang)), + ("![]", DefKind::Macro(MacroKind::Bang)), + ("()", DefKind::Fn), + ("!", DefKind::Macro(MacroKind::Bang)), + ]; + if let Some(idx) = link.find('@') { let (prefix, rest) = link.split_at(idx); let d = match prefix { @@ -1530,16 +1539,23 @@ impl Disambiguator { "prim" | "primitive" => Primitive, _ => return Err((format!("unknown disambiguator `{prefix}`"), 0..idx)), }; + + for (suffix, kind) in suffixes { + if let Some(path_str) = rest.strip_suffix(suffix) { + if d.ns() != Kind(kind).ns() { + return Err(( + format!("unmatched disambiguator `{prefix}` and suffix `{suffix}`"), + 0..idx, + )); + } else if path_str.len() > 1 { + // path_str != "@" + return Ok(Some((d, &path_str[1..], &rest[1..]))); + } + } + } + Ok(Some((d, &rest[1..], &rest[1..]))) } else { - let suffixes = [ - // If you update this list, please also update the relevant rustdoc book section! - ("!()", DefKind::Macro(MacroKind::Bang)), - ("!{}", DefKind::Macro(MacroKind::Bang)), - ("![]", DefKind::Macro(MacroKind::Bang)), - ("()", DefKind::Fn), - ("!", DefKind::Macro(MacroKind::Bang)), - ]; for (suffix, kind) in suffixes { if let Some(path_str) = link.strip_suffix(suffix) { // Avoid turning `!` or `()` into an empty string diff --git a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs index 170ecf896b4e1..67b48878ca513 100644 --- a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs +++ b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs @@ -246,7 +246,7 @@ fn collect_supertrait_bounds<'tcx>(cx: &LateContext<'tcx>, bounds: GenericBounds && let [.., path] = poly_trait.trait_ref.path.segments && poly_trait.bound_generic_params.is_empty() && let Some(trait_def_id) = path.res.opt_def_id() - && let predicates = cx.tcx.super_predicates_of(trait_def_id).predicates + && let predicates = cx.tcx.explicit_super_predicates_of(trait_def_id).predicates // If the trait has no supertrait, there is no need to collect anything from that bound && !predicates.is_empty() { diff --git a/src/tools/clippy/clippy_lints/src/methods/type_id_on_box.rs b/src/tools/clippy/clippy_lints/src/methods/type_id_on_box.rs index 6f9b38fcf83cc..b62ecef0069af 100644 --- a/src/tools/clippy/clippy_lints/src/methods/type_id_on_box.rs +++ b/src/tools/clippy/clippy_lints/src/methods/type_id_on_box.rs @@ -24,7 +24,7 @@ fn is_subtrait_of_any(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { cx.tcx.is_diagnostic_item(sym::Any, tr.def_id) || cx .tcx - .super_predicates_of(tr.def_id) + .explicit_super_predicates_of(tr.def_id) .predicates .iter() .any(|(clause, _)| { diff --git a/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs b/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs index 4922c87b206c0..a1d8ec3b32ec9 100644 --- a/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs +++ b/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs @@ -91,7 +91,7 @@ fn path_to_sized_bound(cx: &LateContext<'_>, trait_bound: &PolyTraitRef<'_>) -> return true; } - for &(predicate, _) in cx.tcx.super_predicates_of(trait_def_id).predicates { + for &(predicate, _) in cx.tcx.explicit_super_predicates_of(trait_def_id).predicates { if let ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() && trait_predicate.polarity == PredicatePolarity::Positive && !path.contains(&trait_predicate.def_id()) diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed index 921dcf0b16261..f8fc935f3679d 100644 --- a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed +++ b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed @@ -104,15 +104,18 @@ fn main() {} struct D; +/* FIXME(effects) impl const Drop for D { fn drop(&mut self) { todo!(); } } +*/ // Lint this, since it can be dropped in const contexts // FIXME(effects) -fn d(this: D) {} +const fn d(this: D) {} +//~^ ERROR: this could be a `const fn` mod msrv { struct Foo(*const u8, &'static u8); diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs index 58e639cc7fd1f..5e4e2c58e5a4d 100644 --- a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs +++ b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs @@ -104,15 +104,18 @@ fn main() {} struct D; +/* FIXME(effects) impl const Drop for D { fn drop(&mut self) { todo!(); } } +*/ // Lint this, since it can be dropped in const contexts // FIXME(effects) fn d(this: D) {} +//~^ ERROR: this could be a `const fn` mod msrv { struct Foo(*const u8, &'static u8); diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr index 8999af761e314..8302b074127e6 100644 --- a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr +++ b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr @@ -157,7 +157,18 @@ LL | const fn msrv_1_46() -> i32 { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:122:9 + --> tests/ui/missing_const_for_fn/could_be_const.rs:117:1 + | +LL | fn d(this: D) {} + | ^^^^^^^^^^^^^^^^ + | +help: make the function `const` + | +LL | const fn d(this: D) {} + | +++++ + +error: this could be a `const fn` + --> tests/ui/missing_const_for_fn/could_be_const.rs:125:9 | LL | / fn deref_ptr_can_be_const(self) -> usize { LL | | @@ -171,7 +182,7 @@ LL | const fn deref_ptr_can_be_const(self) -> usize { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:127:9 + --> tests/ui/missing_const_for_fn/could_be_const.rs:130:9 | LL | / fn deref_copied_val(self) -> usize { LL | | @@ -185,7 +196,7 @@ LL | const fn deref_copied_val(self) -> usize { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:138:5 + --> tests/ui/missing_const_for_fn/could_be_const.rs:141:5 | LL | / fn union_access_can_be_const() { LL | | @@ -200,7 +211,7 @@ LL | const fn union_access_can_be_const() { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:152:9 + --> tests/ui/missing_const_for_fn/could_be_const.rs:155:9 | LL | / pub fn new(strings: Vec) -> Self { LL | | Self { strings } @@ -213,7 +224,7 @@ LL | pub const fn new(strings: Vec) -> Self { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:157:9 + --> tests/ui/missing_const_for_fn/could_be_const.rs:160:9 | LL | / pub fn empty() -> Self { LL | | Self { strings: Vec::new() } @@ -226,7 +237,7 @@ LL | pub const fn empty() -> Self { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:168:9 + --> tests/ui/missing_const_for_fn/could_be_const.rs:171:9 | LL | / pub fn new(text: String) -> Self { LL | | let vec = Vec::new(); @@ -239,5 +250,5 @@ help: make the function `const` LL | pub const fn new(text: String) -> Self { | +++++ -error: aborting due to 17 previous errors +error: aborting due to 18 previous errors diff --git a/src/tools/compiletest/src/command-list.rs b/src/tools/compiletest/src/command-list.rs index 6e1685a8a9456..6735e9faa7a67 100644 --- a/src/tools/compiletest/src/command-list.rs +++ b/src/tools/compiletest/src/command-list.rs @@ -53,6 +53,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "ignore-gnu", "ignore-haiku", "ignore-horizon", + "ignore-i686-pc-windows-gnu", "ignore-i686-pc-windows-msvc", "ignore-illumos", "ignore-ios", @@ -174,6 +175,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "only-bpf", "only-cdb", "only-gnu", + "only-i686-pc-windows-gnu", "only-i686-pc-windows-msvc", "only-ios", "only-linux", diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index fd59ad3b8f130..912aa11ded053 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -9ed2ab3790ff41bf741dd690befd6a1c1e2b23ca +7d97c59438e933e86f557ed999da3b8dfc6855a7 diff --git a/src/tools/run-make-support/Cargo.toml b/src/tools/run-make-support/Cargo.toml index e3837a2f8cc4e..ec3b8a96ef3b6 100644 --- a/src/tools/run-make-support/Cargo.toml +++ b/src/tools/run-make-support/Cargo.toml @@ -4,6 +4,7 @@ version = "0.2.0" edition = "2021" [dependencies] +bstr = "1.6.0" object = "0.34.0" similar = "2.5.0" wasmparser = "0.118.2" diff --git a/src/tools/run-make-support/src/command.rs b/src/tools/run-make-support/src/command.rs index 0a1bd9b0b34f5..ee651704c6fd0 100644 --- a/src/tools/run-make-support/src/command.rs +++ b/src/tools/run-make-support/src/command.rs @@ -185,14 +185,14 @@ impl CompletedProcess { /// Checks that `stdout` does not contain `unexpected`. #[track_caller] pub fn assert_stdout_not_contains>(&self, unexpected: S) -> &Self { - assert_not_contains(&self.stdout_utf8(), unexpected.as_ref()); + assert_not_contains(&self.stdout_utf8(), unexpected); self } /// Checks that `stdout` contains `expected`. #[track_caller] pub fn assert_stdout_contains>(&self, expected: S) -> &Self { - assert_contains(&self.stdout_utf8(), expected.as_ref()); + assert_contains(&self.stdout_utf8(), expected); self } @@ -206,14 +206,14 @@ impl CompletedProcess { /// Checks that `stderr` contains `expected`. #[track_caller] pub fn assert_stderr_contains>(&self, expected: S) -> &Self { - assert_contains(&self.stderr_utf8(), expected.as_ref()); + assert_contains(&self.stderr_utf8(), expected); self } /// Checks that `stderr` does not contain `unexpected`. #[track_caller] pub fn assert_stderr_not_contains>(&self, unexpected: S) -> &Self { - assert_not_contains(&self.stdout_utf8(), unexpected.as_ref()); + assert_not_contains(&self.stdout_utf8(), unexpected); self } diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index 771cda630af6a..294dae109425f 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -21,6 +21,7 @@ use std::io; use std::panic; use std::path::{Path, PathBuf}; +pub use bstr; pub use gimli; pub use object; pub use regex; @@ -408,7 +409,9 @@ pub fn read_dir(dir: impl AsRef, mut callback: F) { /// Check that `actual` is equal to `expected`. Panic otherwise. #[track_caller] -pub fn assert_equals(actual: &str, expected: &str) { +pub fn assert_equals, S2: AsRef>(actual: S1, expected: S2) { + let actual = actual.as_ref(); + let expected = expected.as_ref(); if actual != expected { eprintln!("=== ACTUAL TEXT ==="); eprintln!("{}", actual); @@ -420,7 +423,9 @@ pub fn assert_equals(actual: &str, expected: &str) { /// Check that `haystack` contains `needle`. Panic otherwise. #[track_caller] -pub fn assert_contains(haystack: &str, needle: &str) { +pub fn assert_contains, S2: AsRef>(haystack: S1, needle: S2) { + let haystack = haystack.as_ref(); + let needle = needle.as_ref(); if !haystack.contains(needle) { eprintln!("=== HAYSTACK ==="); eprintln!("{}", haystack); @@ -432,7 +437,9 @@ pub fn assert_contains(haystack: &str, needle: &str) { /// Check that `haystack` does not contain `needle`. Panic otherwise. #[track_caller] -pub fn assert_not_contains(haystack: &str, needle: &str) { +pub fn assert_not_contains, S2: AsRef>(haystack: S1, needle: S2) { + let haystack = haystack.as_ref(); + let needle = needle.as_ref(); if haystack.contains(needle) { eprintln!("=== HAYSTACK ==="); eprintln!("{}", haystack); @@ -524,11 +531,12 @@ macro_rules! impl_common_helpers { /// Generic command arguments provider. Prefer specific helper methods if possible. /// Note that for some executables, arguments might be platform specific. For C/C++ /// compilers, arguments might be platform *and* compiler specific. - pub fn args(&mut self, args: &[S]) -> &mut Self + pub fn args(&mut self, args: V) -> &mut Self where + V: AsRef<[S]>, S: AsRef<::std::ffi::OsStr>, { - self.cmd.args(args); + self.cmd.args(args.as_ref()); self } diff --git a/src/tools/run-make-support/src/llvm.rs b/src/tools/run-make-support/src/llvm.rs index 7f42223bf7f5a..4c9e9a5323025 100644 --- a/src/tools/run-make-support/src/llvm.rs +++ b/src/tools/run-make-support/src/llvm.rs @@ -180,6 +180,13 @@ impl LlvmFilecheck { self.cmd.arg(path.as_ref()); self } + + /// `--input-file` option. + pub fn input_file>(&mut self, input_file: P) -> &mut Self { + self.cmd.arg("--input-file"); + self.cmd.arg(input_file.as_ref()); + self + } } impl LlvmObjdump { diff --git a/src/tools/run-make-support/src/rustc.rs b/src/tools/run-make-support/src/rustc.rs index 28ece1dff128d..3f23c1b8f9e76 100644 --- a/src/tools/run-make-support/src/rustc.rs +++ b/src/tools/run-make-support/src/rustc.rs @@ -106,6 +106,17 @@ impl Rustc { self } + /// Remap source path prefixes in all output. + pub fn remap_path_prefix>(&mut self, from: P, to: P) -> &mut Self { + let from = from.as_ref().to_string_lossy(); + let to = to.as_ref().to_string_lossy(); + + self.cmd.arg("--remap-path-prefix"); + self.cmd.arg(format!("{from}={to}")); + + self + } + /// Specify path to the input file. pub fn input>(&mut self, path: P) -> &mut Self { self.cmd.arg(path.as_ref()); @@ -190,7 +201,8 @@ impl Rustc { } /// Specify the target triple, or a path to a custom target json spec file. - pub fn target(&mut self, target: &str) -> &mut Self { + pub fn target>(&mut self, target: S) -> &mut Self { + let target = target.as_ref(); self.cmd.arg(format!("--target={target}")); self } diff --git a/src/tools/run-make-support/src/rustdoc.rs b/src/tools/run-make-support/src/rustdoc.rs index fb00427b1c199..2be962ad88828 100644 --- a/src/tools/run-make-support/src/rustdoc.rs +++ b/src/tools/run-make-support/src/rustdoc.rs @@ -104,7 +104,8 @@ impl Rustdoc { } /// Specify the target triple, or a path to a custom target json spec file. - pub fn target(&mut self, target: &str) -> &mut Self { + pub fn target>(&mut self, target: S) -> &mut Self { + let target = target.as_ref(); self.cmd.arg(format!("--target={target}")); self } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs index c92d4e78ffa71..7755a9b9748be 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs @@ -49,7 +49,6 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "bindings_with_variant_name", description: r##"detects pattern bindings with the same name as one of the matched variants"##, }, - Lint { label: "box_pointers", description: r##"use of owned (Box type) heap memory"## }, Lint { label: "break_with_label_and_loop", description: r##"`break` expression with label and unlabeled loop as value expression"##, diff --git a/src/tools/rustc-perf-wrapper/Cargo.toml b/src/tools/rustc-perf-wrapper/Cargo.toml new file mode 100644 index 0000000000000..416bfef41d7fd --- /dev/null +++ b/src/tools/rustc-perf-wrapper/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "rustc-perf-wrapper" +version = "0.1.0" +edition = "2021" + +[dependencies] +clap = { version = "4.5.7", features = ["derive", "env"] } diff --git a/src/tools/rustc-perf-wrapper/README.md b/src/tools/rustc-perf-wrapper/README.md new file mode 100644 index 0000000000000..d7655459a2fe1 --- /dev/null +++ b/src/tools/rustc-perf-wrapper/README.md @@ -0,0 +1,3 @@ +# rustc-perf wrapper +Utility tool for invoking [`rustc-perf`](https://github.com/rust-lang/rustc-perf) for benchmarking/profiling +a stage1/2 compiler built by bootstrap using `x perf -- `. diff --git a/src/tools/rustc-perf-wrapper/src/config.rs b/src/tools/rustc-perf-wrapper/src/config.rs new file mode 100644 index 0000000000000..a88abfe472377 --- /dev/null +++ b/src/tools/rustc-perf-wrapper/src/config.rs @@ -0,0 +1,45 @@ +use std::fmt::{Display, Formatter}; + +#[derive(Clone, Copy, Debug, clap::ValueEnum)] +#[value(rename_all = "PascalCase")] +pub enum Profile { + Check, + Debug, + Doc, + Opt, + Clippy, +} + +impl Display for Profile { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let name = match self { + Profile::Check => "Check", + Profile::Debug => "Debug", + Profile::Doc => "Doc", + Profile::Opt => "Opt", + Profile::Clippy => "Clippy", + }; + f.write_str(name) + } +} + +#[derive(Clone, Copy, Debug, clap::ValueEnum)] +#[value(rename_all = "PascalCase")] +pub enum Scenario { + Full, + IncrFull, + IncrUnchanged, + IncrPatched, +} + +impl Display for Scenario { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let name = match self { + Scenario::Full => "Full", + Scenario::IncrFull => "IncrFull", + Scenario::IncrUnchanged => "IncrUnchanged", + Scenario::IncrPatched => "IncrPatched", + }; + f.write_str(name) + } +} diff --git a/src/tools/rustc-perf-wrapper/src/main.rs b/src/tools/rustc-perf-wrapper/src/main.rs new file mode 100644 index 0000000000000..1c0d1745f3d98 --- /dev/null +++ b/src/tools/rustc-perf-wrapper/src/main.rs @@ -0,0 +1,130 @@ +use crate::config::{Profile, Scenario}; +use clap::Parser; +use std::path::PathBuf; +use std::process::Command; + +mod config; + +/// Performs profiling or benchmarking with [`rustc-perf`](https://github.com/rust-lang/rustc-perf) +/// using a locally built compiler. +#[derive(Debug, clap::Parser)] +// Hide arguments from BuildContext in the default usage string. +// Clap does not seem to have a way of disabling the usage of these arguments. +#[clap(override_usage = "rustc-perf-wrapper [OPTIONS] ")] +pub struct Args { + #[clap(subcommand)] + cmd: PerfCommand, + + #[clap(flatten)] + opts: SharedOpts, + + #[clap(flatten)] + ctx: BuildContext, +} + +#[derive(Debug, clap::Parser)] +enum PerfCommand { + /// Run `profile_local eprintln`. + /// This executes the compiler on the given benchmarks and stores its stderr output. + Eprintln, + /// Run `profile_local samply` + /// This executes the compiler on the given benchmarks and profiles it with `samply`. + /// You need to install `samply`, e.g. using `cargo install samply`. + Samply, + /// Run `profile_local cachegrind`. + /// This executes the compiler on the given benchmarks under `Cachegrind`. + Cachegrind, +} + +impl PerfCommand { + fn is_profiling(&self) -> bool { + match self { + PerfCommand::Eprintln | PerfCommand::Samply | PerfCommand::Cachegrind => true, + } + } +} + +#[derive(Debug, clap::Parser)] +struct SharedOpts { + /// Select the benchmarks that you want to run (separated by commas). + /// If unspecified, all benchmarks will be executed. + #[clap(long, global = true, value_delimiter = ',')] + include: Vec, + /// Select the scenarios that should be benchmarked. + #[clap( + long, + global = true, + value_delimiter = ',', + default_value = "Full,IncrFull,IncrUnchanged,IncrPatched" + )] + scenarios: Vec, + /// Select the profiles that should be benchmarked. + #[clap(long, global = true, value_delimiter = ',', default_value = "Check,Debug,Opt")] + profiles: Vec, +} + +/// These arguments are mostly designed to be passed from bootstrap, not by users +/// directly. +#[derive(Debug, clap::Parser)] +struct BuildContext { + /// Compiler binary that will be benchmarked/profiled. + #[clap(long, hide = true, env = "RUSTC_REAL")] + compiler: PathBuf, + /// rustc-perf collector binary that will be used for running benchmarks/profilers. + #[clap(long, hide = true, env = "PERF_COLLECTOR")] + collector: PathBuf, + /// Directory where to store results. + #[clap(long, hide = true, env = "PERF_RESULT_DIR")] + results_dir: PathBuf, +} + +fn main() { + let args = Args::parse(); + run(args); +} + +fn run(args: Args) { + let mut cmd = Command::new(args.ctx.collector); + match &args.cmd { + PerfCommand::Eprintln => { + cmd.arg("profile_local").arg("eprintln"); + } + PerfCommand::Samply => { + cmd.arg("profile_local").arg("samply"); + } + PerfCommand::Cachegrind => { + cmd.arg("profile_local").arg("cachegrind"); + } + } + if args.cmd.is_profiling() { + cmd.arg("--out-dir").arg(&args.ctx.results_dir); + } + + if !args.opts.include.is_empty() { + cmd.arg("--include").arg(args.opts.include.join(",")); + } + if !args.opts.profiles.is_empty() { + cmd.arg("--profiles") + .arg(args.opts.profiles.iter().map(|p| p.to_string()).collect::>().join(",")); + } + if !args.opts.scenarios.is_empty() { + cmd.arg("--scenarios") + .arg(args.opts.scenarios.iter().map(|p| p.to_string()).collect::>().join(",")); + } + cmd.arg(&args.ctx.compiler); + + println!("Running `rustc-perf` using `{}`", args.ctx.compiler.display()); + + const MANIFEST_DIR: &str = env!("CARGO_MANIFEST_DIR"); + + let rustc_perf_dir = PathBuf::from(MANIFEST_DIR).join("../rustc-perf"); + + // We need to set the working directory to `src/tools/perf`, so that it can find the directory + // with compile-time benchmarks. + let cmd = cmd.current_dir(rustc_perf_dir); + cmd.status().expect("error while running rustc-perf collector"); + + if args.cmd.is_profiling() { + println!("You can find the results at `{}`", args.ctx.results_dir.display()); + } +} diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index a29d57d160312..276d2d694cda0 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -18,7 +18,6 @@ run-make/cross-lang-lto-clang/Makefile run-make/cross-lang-lto-pgo-smoketest/Makefile run-make/cross-lang-lto-upstream-rlibs/Makefile run-make/cross-lang-lto/Makefile -run-make/debug-assertions/Makefile run-make/dep-info-doesnt-run-much/Makefile run-make/dep-info-spaces/Makefile run-make/dep-info/Makefile @@ -27,7 +26,6 @@ run-make/dump-mono-stats/Makefile run-make/dylib-chain/Makefile run-make/emit-path-unhashed/Makefile run-make/emit-shared-files/Makefile -run-make/emit-stack-sizes/Makefile run-make/emit-to-stdout/Makefile run-make/env-dep-info/Makefile run-make/export-executable-symbols/Makefile @@ -70,7 +68,6 @@ run-make/issue-37839/Makefile run-make/issue-40535/Makefile run-make/issue-47384/Makefile run-make/issue-47551/Makefile -run-make/issue-68794-textrel-on-minimal-lib/Makefile run-make/issue-69368/Makefile run-make/issue-83045/Makefile run-make/issue-83112-incr-test-moved-file/Makefile @@ -83,13 +80,11 @@ run-make/jobserver-error/Makefile run-make/libs-through-symlinks/Makefile run-make/libtest-json/Makefile run-make/libtest-junit/Makefile -run-make/libtest-padding/Makefile run-make/libtest-thread-limit/Makefile run-make/link-cfg/Makefile run-make/link-framework/Makefile run-make/link-path-order/Makefile run-make/linkage-attr-on-static/Makefile -run-make/llvm-ident/Makefile run-make/long-linker-command-lines-cmd-exe/Makefile run-make/long-linker-command-lines/Makefile run-make/longjmp-across-rust/Makefile @@ -101,8 +96,6 @@ run-make/macos-fat-archive/Makefile run-make/manual-link/Makefile run-make/metadata-dep-info/Makefile run-make/min-global-align/Makefile -run-make/mingw-export-call-convention/Makefile -run-make/mismatching-target-triples/Makefile run-make/missing-crate-dependency/Makefile run-make/mixing-libs/Makefile run-make/msvc-opt-minsize/Makefile @@ -115,13 +108,11 @@ run-make/obey-crate-type-flag/Makefile run-make/optimization-remarks-dir-pgo/Makefile run-make/optimization-remarks-dir/Makefile run-make/output-type-permutations/Makefile -run-make/override-aliased-flags/Makefile run-make/panic-abort-eh_frame/Makefile run-make/pass-linker-flags-flavor/Makefile run-make/pass-linker-flags-from-dep/Makefile run-make/pass-linker-flags/Makefile run-make/pass-non-c-like-enum-to-c/Makefile -run-make/pdb-alt-path/Makefile run-make/pdb-buildinfo-cl-cmd/Makefile run-make/pgo-gen-lto/Makefile run-make/pgo-gen-no-imp-symbols/Makefile @@ -129,15 +120,12 @@ run-make/pgo-gen/Makefile run-make/pgo-indirect-call-promotion/Makefile run-make/pgo-use/Makefile run-make/pointer-auth-link-with-c/Makefile -run-make/pretty-print-to-file/Makefile -run-make/pretty-print-with-dep-file/Makefile run-make/print-calling-conventions/Makefile run-make/print-target-list/Makefile run-make/profile/Makefile run-make/prune-link-args/Makefile run-make/raw-dylib-alt-calling-convention/Makefile run-make/raw-dylib-c/Makefile -run-make/raw-dylib-cross-compilation/Makefile run-make/raw-dylib-custom-dlltool/Makefile run-make/raw-dylib-import-name-type/Makefile run-make/raw-dylib-inline-cross-dylib/Makefile @@ -145,11 +133,9 @@ run-make/raw-dylib-link-ordinal/Makefile run-make/raw-dylib-stdcall-ordinal/Makefile run-make/redundant-libs/Makefile run-make/remap-path-prefix-dwarf/Makefile -run-make/remap-path-prefix/Makefile run-make/reproducible-build-2/Makefile run-make/reproducible-build/Makefile run-make/return-non-c-like-enum-from-c/Makefile -run-make/return-non-c-like-enum/Makefile run-make/rlib-chain/Makefile run-make/rlib-format-packed-bundled-libs-2/Makefile run-make/rlib-format-packed-bundled-libs-3/Makefile @@ -187,11 +173,5 @@ run-make/track-path-dep-info/Makefile run-make/track-pgo-dep-info/Makefile run-make/translation/Makefile run-make/type-mismatch-same-crate-name/Makefile -run-make/unknown-mod-stdin/Makefile run-make/unstable-flag-required/Makefile -run-make/used-cdylib-macos/Makefile -run-make/volatile-intrinsics/Makefile -run-make/wasm-exceptions-nostd/Makefile -run-make/wasm-override-linker/Makefile -run-make/weird-output-filenames/Makefile run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile diff --git a/src/tools/tidy/src/ext_tool_checks.rs b/src/tools/tidy/src/ext_tool_checks.rs index 1df4921ef864a..8ce44115ef322 100644 --- a/src/tools/tidy/src/ext_tool_checks.rs +++ b/src/tools/tidy/src/ext_tool_checks.rs @@ -364,11 +364,10 @@ fn create_venv_at_path(path: &Path) -> Result<(), Error> { let stderr = String::from_utf8_lossy(&out.stderr); let err = if stderr.contains("No module named virtualenv") { - Error::Generic( + Error::Generic(format!( "virtualenv not found: you may need to install it \ - (`python3 -m pip install venv`)" - .to_owned(), - ) + (`{sys_py} -m pip install virtualenv`)" + )) } else { Error::Generic(format!( "failed to create venv at '{}' using {sys_py}: {stderr}", diff --git a/tests/codegen-units/item-collection/drop_in_place_intrinsic.rs b/tests/codegen-units/item-collection/drop_in_place_intrinsic.rs index 947faa165a9cb..d87ad41e70d58 100644 --- a/tests/codegen-units/item-collection/drop_in_place_intrinsic.rs +++ b/tests/codegen-units/item-collection/drop_in_place_intrinsic.rs @@ -1,6 +1,7 @@ // //@ compile-flags:-Zprint-mono-items=eager //@ compile-flags:-Zinline-in-all-cgus +//@ compile-flags:-Zinline-mir=no #![feature(start)] diff --git a/tests/crashes/119717.rs b/tests/crashes/119717.rs deleted file mode 100644 index 22746548e02cb..0000000000000 --- a/tests/crashes/119717.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ known-bug: #119717 -#![feature(const_trait_impl, effects)] - -use std::ops::{FromResidual, Try}; - -impl const FromResidual for T { - fn from_residual(t: T) -> _ { - t - } -} diff --git a/tests/crashes/119924-6.rs b/tests/crashes/119924-6.rs index 01c4f43e8fd43..f1cc9d2915915 100644 --- a/tests/crashes/119924-6.rs +++ b/tests/crashes/119924-6.rs @@ -1,4 +1,5 @@ //@ known-bug: #119924 +//@ compile-flags: -Znext-solver #![feature(const_trait_impl, effects)] struct S; diff --git a/tests/crashes/123664.rs b/tests/crashes/123664.rs deleted file mode 100644 index 80c415fe07bd7..0000000000000 --- a/tests/crashes/123664.rs +++ /dev/null @@ -1,4 +0,0 @@ -//@ known-bug: #123664 -#![feature(generic_const_exprs, effects)] -const fn with_positive() {} -pub fn main() {} diff --git a/tests/crashes/124857.rs b/tests/crashes/124857.rs deleted file mode 100644 index 4b952fd64ccfb..0000000000000 --- a/tests/crashes/124857.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ known-bug: rust-lang/rust#124857 -//@ compile-flags: -Znext-solver=coherence - -#![feature(effects)] - -#[const_trait] -trait Foo {} - -impl const Foo for i32 {} - -impl const Foo for T where T: ~const Foo {} diff --git a/tests/crashes/126148.rs b/tests/crashes/126148.rs deleted file mode 100644 index 79f8887b40154..0000000000000 --- a/tests/crashes/126148.rs +++ /dev/null @@ -1,23 +0,0 @@ -//@ known-bug: rust-lang/rust#126148 - -#![feature(effects)] -use std::ops::{FromResidual, Try}; - -struct TryMe; -struct Error; - -impl const FromResidual for TryMe {} - -impl const Try for TryMe { - type Output = (); - type Residual = Error; -} - -const fn t() -> TryMe { - TryMe?; - TryMe -} - -const _: () = { - t(); -}; diff --git a/tests/crashes/126646.rs b/tests/crashes/126646.rs new file mode 100644 index 0000000000000..24e3530320a89 --- /dev/null +++ b/tests/crashes/126646.rs @@ -0,0 +1,18 @@ +//@ known-bug: rust-lang/rust#126646 +mod foo { + pub trait Callable { + type Output; + fn call() -> Self::Output; + } + + impl<'a, V: ?Sized> Callable for &'a () { + type Output = (); + } +} +use foo::*; + +fn test<'a>() -> impl Sized { + <&'a () as Callable>::call() +} + +fn main() {} diff --git a/tests/crashes/126648.rs b/tests/crashes/126648.rs new file mode 100644 index 0000000000000..1cf3e44bba9bc --- /dev/null +++ b/tests/crashes/126648.rs @@ -0,0 +1,8 @@ +//@ known-bug: rust-lang/rust#126648 +struct Outest(*const &'a ()); + +fn make() -> Outest {} + +fn main() { + if let Outest("foo") = make() {} +} diff --git a/tests/crashes/126666.rs b/tests/crashes/126666.rs new file mode 100644 index 0000000000000..58526707c9ab4 --- /dev/null +++ b/tests/crashes/126666.rs @@ -0,0 +1,18 @@ +//@ known-bug: rust-lang/rust#126666 +#![feature(const_mut_refs)] +#![feature(const_refs_to_static)] +#![feature(object_safe_for_dispatch)] + +struct Meh { + x: &'static dyn UnsafeCell, +} + +const MUH: Meh = Meh { + x: &mut *(&READONLY as *const _ as *mut _), +}; + +static READONLY: i32 = 0; + +trait UnsafeCell<'a> {} + +pub fn main() {} diff --git a/tests/crashes/126667.rs b/tests/crashes/126667.rs new file mode 100644 index 0000000000000..27b170d6da5fc --- /dev/null +++ b/tests/crashes/126667.rs @@ -0,0 +1,14 @@ +//@ known-bug: rust-lang/rust#126667 +#![warn(rust_2021_compatibility)] + +trait Static<'a> {} + +struct Foo((u32, u32)); + +fn main() { + type T = impl Static; + let foo: T = Foo((1u32, 2u32)); + let x = move || { + let Foo((a, b)) = foo; + }; +} diff --git a/tests/crashes/126680.rs b/tests/crashes/126680.rs new file mode 100644 index 0000000000000..b1566d5e6beed --- /dev/null +++ b/tests/crashes/126680.rs @@ -0,0 +1,21 @@ +//@ known-bug: rust-lang/rust#126680 +//@ compile-flags: -Zvalidate-mir +#![feature(type_alias_impl_trait)] +type Bar = impl std::fmt::Display; + +use std::path::Path; + +struct A { + pub func: fn(check: Bar, b: Option<&Path>), +} +const MY_A: A = A { + func: |check, b| { + if check { + () + } else if let Some(_) = b.and_then(|p| p.parent()) { + () + } + }, +}; + +fn main() {} diff --git a/tests/crashes/126696.rs b/tests/crashes/126696.rs new file mode 100644 index 0000000000000..51dcf6cf29405 --- /dev/null +++ b/tests/crashes/126696.rs @@ -0,0 +1,24 @@ +//@ known-bug: rust-lang/rust#126696 +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn can_double(x: [(); N]) +where + [(); N * 2]:, +{ + x[0]; + unimplemented!() +} + +fn foo() +where + [(); (N + 1) * 2]:, +{ + can_double([(); { N + 1 }]); + // Adding an explicit constant generic causes the ICE to go away + // can_double::<{N + 1}>([(); { N + 1 }]); +} + +fn main() { + foo::<1>(); +} diff --git a/tests/crashes/126725.rs b/tests/crashes/126725.rs new file mode 100644 index 0000000000000..d7a7d21ae4244 --- /dev/null +++ b/tests/crashes/126725.rs @@ -0,0 +1,20 @@ +//@ known-bug: rust-lang/rust#126725 +trait Foo { + fn foo<'a>(&'a self) -> <&'a impl Sized as Bar>::Output; +} + +trait Bar { + type Output; +} + +struct X(i32); + +impl<'a> Bar for &'a X { + type Output = &'a i32; +} + +impl Foo for X { + fn foo<'a>(&'a self) -> <&'a Self as Bar>::Output { + &self.0 + } +} diff --git a/tests/crashes/126744.rs b/tests/crashes/126744.rs new file mode 100644 index 0000000000000..ed562c86e61b2 --- /dev/null +++ b/tests/crashes/126744.rs @@ -0,0 +1,8 @@ +//@ known-bug: rust-lang/rust#126744 +struct X {,} + +fn main() { + || { + if let X { x: 1,} = (X {}) {} + }; +} diff --git a/tests/crashes/126850.rs b/tests/crashes/126850.rs new file mode 100644 index 0000000000000..0ddc24c8bb151 --- /dev/null +++ b/tests/crashes/126850.rs @@ -0,0 +1,11 @@ +//@ known-bug: rust-lang/rust#126850 +fn bug() -> impl Iterator< + Item = [(); { + |found: &String| Some(false); + 4 + }], +> { + std::iter::empty() +} + +fn main() {} diff --git a/tests/mir-opt/building/issue_101867.main.built.after.mir b/tests/mir-opt/building/issue_101867.main.built.after.mir index 0f7917dbb5cbf..5c50b3db5cad6 100644 --- a/tests/mir-opt/building/issue_101867.main.built.after.mir +++ b/tests/mir-opt/building/issue_101867.main.built.after.mir @@ -27,13 +27,13 @@ fn main() -> () { StorageLive(_5); PlaceMention(_1); _6 = discriminant(_1); - switchInt(move _6) -> [1: bb6, otherwise: bb4]; + switchInt(move _6) -> [1: bb4, otherwise: bb3]; } bb1: { StorageLive(_3); StorageLive(_4); - _4 = begin_panic::<&str>(const "explicit panic") -> bb10; + _4 = begin_panic::<&str>(const "explicit panic") -> bb8; } bb2: { @@ -43,12 +43,11 @@ fn main() -> () { } bb3: { - FakeRead(ForMatchedPlace(None), _1); - unreachable; + goto -> bb7; } bb4: { - goto -> bb9; + falseEdge -> [real: bb6, imaginary: bb3]; } bb5: { @@ -56,14 +55,6 @@ fn main() -> () { } bb6: { - falseEdge -> [real: bb8, imaginary: bb4]; - } - - bb7: { - goto -> bb4; - } - - bb8: { _5 = ((_1 as Some).0: u8); _0 = const (); StorageDead(_5); @@ -71,12 +62,12 @@ fn main() -> () { return; } - bb9: { + bb7: { StorageDead(_5); goto -> bb1; } - bb10 (cleanup): { + bb8 (cleanup): { resume; } } diff --git a/tests/mir-opt/building/logical_or_in_conditional.test_complex.built.after.mir b/tests/mir-opt/building/logical_or_in_conditional.test_complex.built.after.mir index fd8eb370ca958..3e16efe6980d9 100644 --- a/tests/mir-opt/building/logical_or_in_conditional.test_complex.built.after.mir +++ b/tests/mir-opt/building/logical_or_in_conditional.test_complex.built.after.mir @@ -19,22 +19,21 @@ fn test_complex() -> () { bb0: { StorageLive(_1); StorageLive(_2); - _2 = E::f() -> [return: bb1, unwind: bb38]; + _2 = E::f() -> [return: bb1, unwind: bb34]; } bb1: { PlaceMention(_2); _3 = discriminant(_2); - switchInt(move _3) -> [0: bb5, otherwise: bb3]; + switchInt(move _3) -> [0: bb3, otherwise: bb2]; } bb2: { - FakeRead(ForMatchedPlace(None), _2); - unreachable; + goto -> bb21; } bb3: { - goto -> bb23; + falseEdge -> [real: bb5, imaginary: bb2]; } bb4: { @@ -42,175 +41,158 @@ fn test_complex() -> () { } bb5: { - falseEdge -> [real: bb7, imaginary: bb3]; + StorageLive(_4); + _4 = always_true() -> [return: bb6, unwind: bb34]; } bb6: { - goto -> bb3; + switchInt(move _4) -> [0: bb8, otherwise: bb7]; } bb7: { - StorageLive(_4); - _4 = always_true() -> [return: bb8, unwind: bb38]; - } - - bb8: { - switchInt(move _4) -> [0: bb10, otherwise: bb9]; - } - - bb9: { StorageLive(_5); StorageLive(_6); StorageLive(_7); _7 = Droppy(const 0_u8); _6 = (_7.0: u8); _5 = Gt(move _6, const 0_u8); - switchInt(move _5) -> [0: bb12, otherwise: bb11]; + switchInt(move _5) -> [0: bb10, otherwise: bb9]; } - bb10: { - goto -> bb16; + bb8: { + goto -> bb14; } - bb11: { - drop(_7) -> [return: bb13, unwind: bb38]; + bb9: { + drop(_7) -> [return: bb11, unwind: bb34]; } - bb12: { - goto -> bb14; + bb10: { + goto -> bb12; } - bb13: { + bb11: { StorageDead(_7); StorageDead(_6); - goto -> bb20; + goto -> bb18; } - bb14: { - drop(_7) -> [return: bb15, unwind: bb38]; + bb12: { + drop(_7) -> [return: bb13, unwind: bb34]; } - bb15: { + bb13: { StorageDead(_7); StorageDead(_6); - goto -> bb16; + goto -> bb14; } - bb16: { + bb14: { StorageLive(_8); StorageLive(_9); StorageLive(_10); _10 = Droppy(const 1_u8); _9 = (_10.0: u8); _8 = Gt(move _9, const 1_u8); - switchInt(move _8) -> [0: bb18, otherwise: bb17]; + switchInt(move _8) -> [0: bb16, otherwise: bb15]; } - bb17: { - drop(_10) -> [return: bb19, unwind: bb38]; + bb15: { + drop(_10) -> [return: bb17, unwind: bb34]; } - bb18: { - goto -> bb21; + bb16: { + goto -> bb19; } - bb19: { + bb17: { StorageDead(_10); StorageDead(_9); - goto -> bb20; + goto -> bb18; } - bb20: { + bb18: { _1 = const (); - goto -> bb24; + goto -> bb22; } - bb21: { - drop(_10) -> [return: bb22, unwind: bb38]; + bb19: { + drop(_10) -> [return: bb20, unwind: bb34]; } - bb22: { + bb20: { StorageDead(_10); StorageDead(_9); - goto -> bb23; + goto -> bb21; } - bb23: { + bb21: { _1 = const (); - goto -> bb24; + goto -> bb22; } - bb24: { + bb22: { StorageDead(_8); StorageDead(_5); StorageDead(_4); StorageDead(_2); StorageDead(_1); StorageLive(_11); - _11 = always_true() -> [return: bb25, unwind: bb38]; + _11 = always_true() -> [return: bb23, unwind: bb34]; } - bb25: { - switchInt(move _11) -> [0: bb27, otherwise: bb26]; + bb23: { + switchInt(move _11) -> [0: bb25, otherwise: bb24]; } - bb26: { - goto -> bb36; + bb24: { + goto -> bb32; } - bb27: { - goto -> bb28; + bb25: { + goto -> bb26; } - bb28: { + bb26: { StorageLive(_12); - _12 = E::f() -> [return: bb29, unwind: bb38]; + _12 = E::f() -> [return: bb27, unwind: bb34]; } - bb29: { + bb27: { PlaceMention(_12); _13 = discriminant(_12); - switchInt(move _13) -> [1: bb33, otherwise: bb31]; - } - - bb30: { - FakeRead(ForMatchedPlace(None), _12); - unreachable; + switchInt(move _13) -> [1: bb29, otherwise: bb28]; } - bb31: { - goto -> bb36; - } - - bb32: { - goto -> bb30; + bb28: { + goto -> bb32; } - bb33: { - falseEdge -> [real: bb35, imaginary: bb31]; + bb29: { + falseEdge -> [real: bb31, imaginary: bb28]; } - bb34: { - goto -> bb31; + bb30: { + goto -> bb28; } - bb35: { + bb31: { _0 = const (); - goto -> bb37; + goto -> bb33; } - bb36: { + bb32: { _0 = const (); - goto -> bb37; + goto -> bb33; } - bb37: { + bb33: { StorageDead(_11); StorageDead(_12); return; } - bb38 (cleanup): { + bb34 (cleanup): { resume; } } diff --git a/tests/mir-opt/gvn.remove_casts_must_change_both_sides.GVN.panic-abort.diff b/tests/mir-opt/gvn.remove_casts_must_change_both_sides.GVN.panic-abort.diff new file mode 100644 index 0000000000000..8b4bfb70401b3 --- /dev/null +++ b/tests/mir-opt/gvn.remove_casts_must_change_both_sides.GVN.panic-abort.diff @@ -0,0 +1,16 @@ +- // MIR for `remove_casts_must_change_both_sides` before GVN ++ // MIR for `remove_casts_must_change_both_sides` after GVN + + fn remove_casts_must_change_both_sides(_1: &*mut u8, _2: *mut u8) -> bool { + let mut _0: bool; + let mut _3: *const u8; + let mut _4: *const u8; + + bb0: { + _3 = (*_1) as *const u8 (PtrToPtr); + _4 = _2 as *const u8 (PtrToPtr); + _0 = Eq(_3, _4); + return; + } + } + diff --git a/tests/mir-opt/gvn.remove_casts_must_change_both_sides.GVN.panic-unwind.diff b/tests/mir-opt/gvn.remove_casts_must_change_both_sides.GVN.panic-unwind.diff new file mode 100644 index 0000000000000..8b4bfb70401b3 --- /dev/null +++ b/tests/mir-opt/gvn.remove_casts_must_change_both_sides.GVN.panic-unwind.diff @@ -0,0 +1,16 @@ +- // MIR for `remove_casts_must_change_both_sides` before GVN ++ // MIR for `remove_casts_must_change_both_sides` after GVN + + fn remove_casts_must_change_both_sides(_1: &*mut u8, _2: *mut u8) -> bool { + let mut _0: bool; + let mut _3: *const u8; + let mut _4: *const u8; + + bb0: { + _3 = (*_1) as *const u8 (PtrToPtr); + _4 = _2 as *const u8 (PtrToPtr); + _0 = Eq(_3, _4); + return; + } + } + diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs index 86f42d23f3835..c7fae0bd08108 100644 --- a/tests/mir-opt/gvn.rs +++ b/tests/mir-opt/gvn.rs @@ -926,6 +926,25 @@ unsafe fn cast_pointer_then_transmute(thin: *mut u32, fat: *mut [u8]) { let fat_addr: usize = std::intrinsics::transmute(fat as *const ()); } +#[custom_mir(dialect = "analysis")] +fn remove_casts_must_change_both_sides(mut_a: &*mut u8, mut_b: *mut u8) -> bool { + // CHECK-LABEL: fn remove_casts_must_change_both_sides( + mir! { + // We'd like to remove these casts, but we can't change *both* of them + // to be locals, so make sure we don't change one without the other, as + // that would be a type error. + { + // CHECK: [[A:_.+]] = (*_1) as *const u8 (PtrToPtr); + let a = *mut_a as *const u8; + // CHECK: [[B:_.+]] = _2 as *const u8 (PtrToPtr); + let b = mut_b as *const u8; + // CHECK: _0 = Eq([[A]], [[B]]); + RET = a == b; + Return() + } + } +} + fn main() { subexpression_elimination(2, 4, 5); wrap_unwrap(5); @@ -995,3 +1014,4 @@ fn identity(x: T) -> T { // EMIT_MIR gvn.generic_cast_metadata.GVN.diff // EMIT_MIR gvn.cast_pointer_eq.GVN.diff // EMIT_MIR gvn.cast_pointer_then_transmute.GVN.diff +// EMIT_MIR gvn.remove_casts_must_change_both_sides.GVN.diff diff --git a/tests/mir-opt/gvn_ptr_eq_with_constant.main.GVN.diff b/tests/mir-opt/gvn_ptr_eq_with_constant.main.GVN.diff new file mode 100644 index 0000000000000..3af78d9b6ce98 --- /dev/null +++ b/tests/mir-opt/gvn_ptr_eq_with_constant.main.GVN.diff @@ -0,0 +1,52 @@ +- // MIR for `main` before GVN ++ // MIR for `main` after GVN + + fn main() -> () { + let mut _0: (); + let _1: bool; + let mut _2: *mut u8; + scope 1 (inlined dangling_mut::) { + let mut _3: usize; + scope 2 (inlined align_of::) { + } + scope 3 (inlined without_provenance_mut::) { + } + } + scope 4 (inlined Foo::::cmp_ptr) { + let mut _4: *const u8; + let mut _5: *mut u8; + let mut _6: *const u8; + scope 5 (inlined std::ptr::eq::) { + } + } + + bb0: { + StorageLive(_1); + StorageLive(_2); + StorageLive(_3); +- _3 = AlignOf(u8); +- _2 = _3 as *mut u8 (Transmute); ++ _3 = const 1_usize; ++ _2 = const {0x1 as *mut u8}; + StorageDead(_3); + StorageLive(_4); + StorageLive(_5); +- _5 = _2; +- _4 = _2 as *const u8 (PtrToPtr); ++ _5 = const {0x1 as *mut u8}; ++ _4 = const {0x1 as *const u8}; + StorageDead(_5); + StorageLive(_6); +- _6 = const Foo::::SENTINEL as *const u8 (PtrToPtr); +- _1 = Eq(_4, _6); ++ _6 = const {0x1 as *const u8}; ++ _1 = const true; + StorageDead(_6); + StorageDead(_4); + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; + } + } + diff --git a/tests/mir-opt/gvn_ptr_eq_with_constant.rs b/tests/mir-opt/gvn_ptr_eq_with_constant.rs new file mode 100644 index 0000000000000..d8025072ee3d3 --- /dev/null +++ b/tests/mir-opt/gvn_ptr_eq_with_constant.rs @@ -0,0 +1,23 @@ +// skip-filecheck +//@ test-mir-pass: GVN +//@ only-64bit +//@ compile-flags: -Z mir-enable-passes=+Inline + +// Regression for + +#![feature(strict_provenance)] + +struct Foo(std::marker::PhantomData); + +impl Foo { + const SENTINEL: *mut T = std::ptr::dangling_mut(); + + fn cmp_ptr(a: *mut T) -> bool { + std::ptr::eq(a, Self::SENTINEL) + } +} + +// EMIT_MIR gvn_ptr_eq_with_constant.main.GVN.diff +pub fn main() { + Foo::::cmp_ptr(std::ptr::dangling_mut()); +} diff --git a/tests/mir-opt/inline/inline_more_in_non_inline.marked_inline_direct.Inline.after.panic-abort.mir b/tests/mir-opt/inline/inline_more_in_non_inline.marked_inline_direct.Inline.after.panic-abort.mir new file mode 100644 index 0000000000000..522f772c6f48e --- /dev/null +++ b/tests/mir-opt/inline/inline_more_in_non_inline.marked_inline_direct.Inline.after.panic-abort.mir @@ -0,0 +1,22 @@ +// MIR for `marked_inline_direct` after Inline + +fn marked_inline_direct(_1: i32) -> () { + debug x => _1; + let mut _0: (); + let _2: (); + let mut _3: i32; + + bb0: { + StorageLive(_2); + StorageLive(_3); + _3 = _1; + _2 = call_twice(move _3) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_3); + StorageDead(_2); + _0 = const (); + return; + } +} diff --git a/tests/mir-opt/inline/inline_more_in_non_inline.marked_inline_direct.Inline.after.panic-unwind.mir b/tests/mir-opt/inline/inline_more_in_non_inline.marked_inline_direct.Inline.after.panic-unwind.mir new file mode 100644 index 0000000000000..722b02eeba806 --- /dev/null +++ b/tests/mir-opt/inline/inline_more_in_non_inline.marked_inline_direct.Inline.after.panic-unwind.mir @@ -0,0 +1,22 @@ +// MIR for `marked_inline_direct` after Inline + +fn marked_inline_direct(_1: i32) -> () { + debug x => _1; + let mut _0: (); + let _2: (); + let mut _3: i32; + + bb0: { + StorageLive(_2); + StorageLive(_3); + _3 = _1; + _2 = call_twice(move _3) -> [return: bb1, unwind continue]; + } + + bb1: { + StorageDead(_3); + StorageDead(_2); + _0 = const (); + return; + } +} diff --git a/tests/mir-opt/inline/inline_more_in_non_inline.marked_inline_indirect.Inline.after.panic-abort.mir b/tests/mir-opt/inline/inline_more_in_non_inline.marked_inline_indirect.Inline.after.panic-abort.mir new file mode 100644 index 0000000000000..63b91cbce2d60 --- /dev/null +++ b/tests/mir-opt/inline/inline_more_in_non_inline.marked_inline_indirect.Inline.after.panic-abort.mir @@ -0,0 +1,27 @@ +// MIR for `marked_inline_indirect` after Inline + +fn marked_inline_indirect(_1: i32) -> () { + debug x => _1; + let mut _0: (); + let _2: (); + let mut _3: i32; + scope 1 (inlined marked_inline_direct) { + let _4: (); + } + + bb0: { + StorageLive(_2); + StorageLive(_3); + _3 = _1; + StorageLive(_4); + _4 = call_twice(move _3) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_4); + StorageDead(_3); + StorageDead(_2); + _0 = const (); + return; + } +} diff --git a/tests/mir-opt/inline/inline_more_in_non_inline.marked_inline_indirect.Inline.after.panic-unwind.mir b/tests/mir-opt/inline/inline_more_in_non_inline.marked_inline_indirect.Inline.after.panic-unwind.mir new file mode 100644 index 0000000000000..7c84e98dd516c --- /dev/null +++ b/tests/mir-opt/inline/inline_more_in_non_inline.marked_inline_indirect.Inline.after.panic-unwind.mir @@ -0,0 +1,27 @@ +// MIR for `marked_inline_indirect` after Inline + +fn marked_inline_indirect(_1: i32) -> () { + debug x => _1; + let mut _0: (); + let _2: (); + let mut _3: i32; + scope 1 (inlined marked_inline_direct) { + let _4: (); + } + + bb0: { + StorageLive(_2); + StorageLive(_3); + _3 = _1; + StorageLive(_4); + _4 = call_twice(move _3) -> [return: bb1, unwind continue]; + } + + bb1: { + StorageDead(_4); + StorageDead(_3); + StorageDead(_2); + _0 = const (); + return; + } +} diff --git a/tests/mir-opt/inline/inline_more_in_non_inline.monomorphic_not_inline.Inline.after.panic-abort.mir b/tests/mir-opt/inline/inline_more_in_non_inline.monomorphic_not_inline.Inline.after.panic-abort.mir new file mode 100644 index 0000000000000..989014b8b476d --- /dev/null +++ b/tests/mir-opt/inline/inline_more_in_non_inline.monomorphic_not_inline.Inline.after.panic-abort.mir @@ -0,0 +1,34 @@ +// MIR for `monomorphic_not_inline` after Inline + +fn monomorphic_not_inline(_1: i32) -> () { + debug x => _1; + let mut _0: (); + let _2: (); + let mut _3: i32; + scope 1 (inlined call_twice) { + let _4: (); + let _5: (); + } + + bb0: { + StorageLive(_2); + StorageLive(_3); + _3 = _1; + StorageLive(_4); + StorageLive(_5); + _4 = other_thing(_3) -> [return: bb2, unwind unreachable]; + } + + bb1: { + StorageDead(_5); + StorageDead(_4); + StorageDead(_3); + StorageDead(_2); + _0 = const (); + return; + } + + bb2: { + _5 = other_thing(move _3) -> [return: bb1, unwind unreachable]; + } +} diff --git a/tests/mir-opt/inline/inline_more_in_non_inline.monomorphic_not_inline.Inline.after.panic-unwind.mir b/tests/mir-opt/inline/inline_more_in_non_inline.monomorphic_not_inline.Inline.after.panic-unwind.mir new file mode 100644 index 0000000000000..bd200719bbbe9 --- /dev/null +++ b/tests/mir-opt/inline/inline_more_in_non_inline.monomorphic_not_inline.Inline.after.panic-unwind.mir @@ -0,0 +1,34 @@ +// MIR for `monomorphic_not_inline` after Inline + +fn monomorphic_not_inline(_1: i32) -> () { + debug x => _1; + let mut _0: (); + let _2: (); + let mut _3: i32; + scope 1 (inlined call_twice) { + let _4: (); + let _5: (); + } + + bb0: { + StorageLive(_2); + StorageLive(_3); + _3 = _1; + StorageLive(_4); + StorageLive(_5); + _4 = other_thing(_3) -> [return: bb2, unwind continue]; + } + + bb1: { + StorageDead(_5); + StorageDead(_4); + StorageDead(_3); + StorageDead(_2); + _0 = const (); + return; + } + + bb2: { + _5 = other_thing(move _3) -> [return: bb1, unwind continue]; + } +} diff --git a/tests/mir-opt/inline/inline_more_in_non_inline.rs b/tests/mir-opt/inline/inline_more_in_non_inline.rs new file mode 100644 index 0000000000000..5968b97047096 --- /dev/null +++ b/tests/mir-opt/inline/inline_more_in_non_inline.rs @@ -0,0 +1,46 @@ +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY +//@ compile-flags: -O --crate-type lib + +// To avoid MIR blow-up, don't inline large callees into simple shim callers, +// but *do* inline other trivial things. + +extern "Rust" { + fn other_thing(x: i32); +} + +#[inline] +unsafe fn call_twice(x: i32) { + unsafe { + other_thing(x); + other_thing(x); + } +} + +// EMIT_MIR inline_more_in_non_inline.monomorphic_not_inline.Inline.after.mir +#[no_mangle] +pub unsafe fn monomorphic_not_inline(x: i32) { + // CHECK-LABEL: monomorphic_not_inline + // CHECK: other_thing + // CHECK: other_thing + unsafe { call_twice(x) }; +} + +// EMIT_MIR inline_more_in_non_inline.marked_inline_direct.Inline.after.mir +#[inline] +pub unsafe fn marked_inline_direct(x: i32) { + // CHECK-LABEL: marked_inline_direct + // CHECK-NOT: other_thing + // CHECK: call_twice + // CHECK-NOT: other_thing + unsafe { call_twice(x) }; +} + +// EMIT_MIR inline_more_in_non_inline.marked_inline_indirect.Inline.after.mir +#[inline] +pub unsafe fn marked_inline_indirect(x: i32) { + // CHECK-LABEL: marked_inline_indirect + // CHECK-NOT: other_thing + // CHECK: call_twice + // CHECK-NOT: other_thing + unsafe { marked_inline_direct(x) }; +} diff --git a/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff index 45ce933a55ad2..2a36ccaab110a 100644 --- a/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff @@ -11,30 +11,10 @@ + scope 1 (inlined std::ptr::drop_in_place::> - shim(Some(Vec))) { + let mut _6: &mut std::vec::Vec; + let mut _7: (); -+ scope 2 (inlined as Drop>::drop) { -+ let mut _8: *mut [A]; -+ let mut _9: *mut A; -+ let mut _10: usize; -+ scope 3 (inlined Vec::::as_mut_ptr) { -+ let mut _11: &alloc::raw_vec::RawVec; -+ scope 4 (inlined alloc::raw_vec::RawVec::::ptr) { -+ let mut _13: std::ptr::NonNull; -+ scope 5 (inlined Unique::::as_ptr) { -+ scope 6 (inlined NonNull::::as_ptr) { -+ let mut _12: *const A; -+ } -+ } -+ } -+ } -+ scope 7 (inlined slice_from_raw_parts_mut::) { -+ scope 8 (inlined std::ptr::from_raw_parts_mut::<[A], A>) { -+ } -+ } -+ } + } -+ scope 9 (inlined std::ptr::drop_in_place::> - shim(Some(Option))) { -+ let mut _14: isize; -+ let mut _15: isize; ++ scope 2 (inlined std::ptr::drop_in_place::> - shim(Some(Option))) { ++ let mut _8: isize; ++ let mut _9: isize; + } bb0: { @@ -45,24 +25,7 @@ + StorageLive(_6); + StorageLive(_7); + _6 = &mut (*_4); -+ StorageLive(_8); -+ StorageLive(_9); -+ StorageLive(_11); -+ _11 = &((*_6).0: alloc::raw_vec::RawVec); -+ StorageLive(_13); -+ _13 = ((((*_6).0: alloc::raw_vec::RawVec).0: std::ptr::Unique).0: std::ptr::NonNull); -+ StorageLive(_12); -+ _12 = (_13.0: *const A); -+ _9 = move _12 as *mut A (PtrToPtr); -+ StorageDead(_12); -+ StorageDead(_13); -+ StorageDead(_11); -+ StorageLive(_10); -+ _10 = ((*_6).1: usize); -+ _8 = *mut [A] from (_9, _10); -+ StorageDead(_10); -+ StorageDead(_9); -+ _7 = std::ptr::drop_in_place::<[A]>(move _8) -> [return: bb2, unwind unreachable]; ++ _7 = as Drop>::drop(move _6) -> [return: bb2, unwind unreachable]; } bb1: { @@ -73,20 +36,19 @@ StorageLive(_5); _5 = _2; - _0 = std::ptr::drop_in_place::>(move _5) -> [return: bb2, unwind unreachable]; -+ StorageLive(_14); -+ StorageLive(_15); -+ _14 = discriminant((*_5)); -+ switchInt(move _14) -> [0: bb3, otherwise: bb4]; ++ StorageLive(_8); ++ StorageLive(_9); ++ _8 = discriminant((*_5)); ++ switchInt(move _8) -> [0: bb3, otherwise: bb4]; } bb2: { -+ StorageDead(_8); + drop(((*_4).0: alloc::raw_vec::RawVec)) -> [return: bb1, unwind unreachable]; + } + + bb3: { -+ StorageDead(_15); -+ StorageDead(_14); ++ StorageDead(_9); ++ StorageDead(_8); StorageDead(_5); return; + } diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir index 79c5bcfe9cd5c..fbb887fe76a59 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir @@ -7,90 +7,19 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { let mut _11: std::slice::Iter<'_, T>; let mut _12: std::iter::Rev>; let mut _13: std::iter::Rev>; - let mut _37: std::option::Option<&T>; - let mut _39: &impl Fn(&T); - let mut _40: (&T,); - let _41: (); + let mut _15: std::option::Option<&T>; + let mut _16: isize; + let mut _18: &impl Fn(&T); + let mut _19: (&T,); + let _20: (); scope 1 { debug iter => _13; - let _38: &T; + let _17: &T; scope 2 { - debug x => _38; + debug x => _17; } scope 17 (inlined > as Iterator>::next) { - scope 18 (inlined as DoubleEndedIterator>::next_back) { - let mut _14: *const *const T; - let mut _15: *const std::ptr::NonNull; - let mut _20: bool; - let mut _21: *const T; - let _36: &T; - scope 19 { - let _16: std::ptr::NonNull; - let _22: usize; - scope 20 { - } - scope 21 { - scope 25 (inlined as PartialEq>::eq) { - let mut _17: std::ptr::NonNull; - scope 26 (inlined NonNull::::as_ptr) { - let mut _18: *const T; - } - scope 27 (inlined NonNull::::as_ptr) { - let mut _19: *const T; - } - } - } - scope 22 (inlined std::ptr::const_ptr::::addr) { - scope 23 (inlined std::ptr::const_ptr::::cast::<()>) { - } - } - scope 24 (inlined std::ptr::const_ptr::::cast::>) { - } - } - scope 28 (inlined std::slice::Iter::<'_, T>::next_back_unchecked) { - let _29: std::ptr::NonNull; - scope 29 (inlined std::slice::Iter::<'_, T>::pre_dec_end) { - let mut _23: *mut *const T; - let mut _24: *mut std::ptr::NonNull; - let mut _25: std::ptr::NonNull; - let mut _28: std::ptr::NonNull; - let mut _30: *mut *const T; - let mut _31: *mut usize; - let mut _32: usize; - let mut _33: usize; - scope 30 { - scope 31 { - } - scope 32 { - scope 35 (inlined NonNull::::sub) { - scope 36 (inlined core::num::::unchecked_neg) { - scope 37 (inlined core::ub_checks::check_language_ub) { - scope 38 (inlined core::ub_checks::check_language_ub::runtime) { - } - } - } - scope 39 (inlined NonNull::::offset) { - let mut _26: *const T; - let mut _27: *const T; - } - } - } - scope 33 (inlined std::ptr::mut_ptr::::cast::) { - } - scope 34 (inlined std::ptr::mut_ptr::::cast::>) { - } - } - } - scope 40 (inlined NonNull::::as_ref::<'_>) { - let mut _34: std::ptr::NonNull; - scope 41 (inlined NonNull::::as_ptr) { - let mut _35: *const T; - } - scope 42 (inlined std::ptr::mut_ptr::::cast_const) { - } - } - } - } + let mut _14: &mut std::slice::Iter<'_, T>; } } scope 3 (inlined core::slice::::iter) { @@ -178,147 +107,45 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb4: { - StorageLive(_37); - StorageLive(_22); - StorageLive(_21); - StorageLive(_16); - StorageLive(_36); - StorageLive(_20); - switchInt(const ::IS_ZST) -> [0: bb5, otherwise: bb6]; + StorageLive(_15); + StorageLive(_14); + _14 = &mut (_13.0: std::slice::Iter<'_, T>); + _15 = as DoubleEndedIterator>::next_back(move _14) -> [return: bb5, unwind unreachable]; } bb5: { - StorageLive(_15); - StorageLive(_14); - _14 = &raw const ((_13.0: std::slice::Iter<'_, T>).1: *const T); - _15 = _14 as *const std::ptr::NonNull (PtrToPtr); StorageDead(_14); - _16 = (*_15); - StorageDead(_15); - StorageLive(_18); - StorageLive(_19); - StorageLive(_17); - _17 = ((_13.0: std::slice::Iter<'_, T>).0: std::ptr::NonNull); - _18 = (_17.0: *const T); - StorageDead(_17); - _19 = (_16.0: *const T); - _20 = Eq(_18, _19); - StorageDead(_19); - StorageDead(_18); - goto -> bb7; + _16 = discriminant(_15); + switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - _21 = ((_13.0: std::slice::Iter<'_, T>).1: *const T); - _22 = _21 as usize (Transmute); - _20 = Eq(_22, const 0_usize); - goto -> bb7; + StorageDead(_15); + StorageDead(_13); + drop(_2) -> [return: bb7, unwind unreachable]; } bb7: { - switchInt(move _20) -> [0: bb8, otherwise: bb16]; + return; } bb8: { - StorageLive(_35); - StorageLive(_29); - StorageLive(_31); - StorageLive(_24); - switchInt(const ::IS_ZST) -> [0: bb9, otherwise: bb13]; + _17 = ((_15 as Some).0: &T); + StorageLive(_18); + _18 = &_2; + StorageLive(_19); + _19 = (_17,); + _20 = >::call(move _18, move _19) -> [return: bb9, unwind unreachable]; } bb9: { - StorageLive(_23); - _23 = &raw mut ((_13.0: std::slice::Iter<'_, T>).1: *const T); - _24 = _23 as *mut std::ptr::NonNull (PtrToPtr); - StorageDead(_23); - StorageLive(_28); - _25 = (*_24); - switchInt(const ::IS_ZST) -> [0: bb10, otherwise: bb11]; - } - - bb10: { - StorageLive(_27); - StorageLive(_26); - _26 = (_25.0: *const T); - _27 = Offset(move _26, const -1_isize); - StorageDead(_26); - _28 = NonNull:: { pointer: move _27 }; - StorageDead(_27); - goto -> bb12; - } - - bb11: { - _28 = _25; - goto -> bb12; - } - - bb12: { - (*_24) = move _28; - StorageDead(_28); - _29 = (*_24); - goto -> bb14; - } - - bb13: { - StorageLive(_30); - _30 = &raw mut ((_13.0: std::slice::Iter<'_, T>).1: *const T); - _31 = _30 as *mut usize (PtrToPtr); - StorageDead(_30); - StorageLive(_33); - StorageLive(_32); - _32 = (*_31); - _33 = SubUnchecked(move _32, const 1_usize); - StorageDead(_32); - (*_31) = move _33; - StorageDead(_33); - _29 = ((_13.0: std::slice::Iter<'_, T>).0: std::ptr::NonNull); - goto -> bb14; - } - - bb14: { - StorageDead(_24); - StorageDead(_31); - StorageLive(_34); - _34 = _29; - _35 = (_34.0: *const T); - StorageDead(_34); - _36 = &(*_35); - StorageDead(_29); - StorageDead(_35); - _37 = Option::<&T>::Some(_36); - StorageDead(_20); - StorageDead(_36); - StorageDead(_16); - StorageDead(_21); - StorageDead(_22); - _38 = ((_37 as Some).0: &T); - StorageLive(_39); - _39 = &_2; - StorageLive(_40); - _40 = (_38,); - _41 = >::call(move _39, move _40) -> [return: bb15, unwind unreachable]; - } - - bb15: { - StorageDead(_40); - StorageDead(_39); - StorageDead(_37); + StorageDead(_19); + StorageDead(_18); + StorageDead(_15); goto -> bb4; } - bb16: { - StorageDead(_20); - StorageDead(_36); - StorageDead(_16); - StorageDead(_21); - StorageDead(_22); - StorageDead(_37); - StorageDead(_13); - drop(_2) -> [return: bb17, unwind unreachable]; - } - - bb17: { - return; + bb10: { + unreachable; } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir index 7c107a23f9e0b..db9409f72ab1a 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir @@ -7,90 +7,19 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { let mut _11: std::slice::Iter<'_, T>; let mut _12: std::iter::Rev>; let mut _13: std::iter::Rev>; - let mut _37: std::option::Option<&T>; - let mut _39: &impl Fn(&T); - let mut _40: (&T,); - let _41: (); + let mut _15: std::option::Option<&T>; + let mut _16: isize; + let mut _18: &impl Fn(&T); + let mut _19: (&T,); + let _20: (); scope 1 { debug iter => _13; - let _38: &T; + let _17: &T; scope 2 { - debug x => _38; + debug x => _17; } scope 17 (inlined > as Iterator>::next) { - scope 18 (inlined as DoubleEndedIterator>::next_back) { - let mut _14: *const *const T; - let mut _15: *const std::ptr::NonNull; - let mut _20: bool; - let mut _21: *const T; - let _36: &T; - scope 19 { - let _16: std::ptr::NonNull; - let _22: usize; - scope 20 { - } - scope 21 { - scope 25 (inlined as PartialEq>::eq) { - let mut _17: std::ptr::NonNull; - scope 26 (inlined NonNull::::as_ptr) { - let mut _18: *const T; - } - scope 27 (inlined NonNull::::as_ptr) { - let mut _19: *const T; - } - } - } - scope 22 (inlined std::ptr::const_ptr::::addr) { - scope 23 (inlined std::ptr::const_ptr::::cast::<()>) { - } - } - scope 24 (inlined std::ptr::const_ptr::::cast::>) { - } - } - scope 28 (inlined std::slice::Iter::<'_, T>::next_back_unchecked) { - let _29: std::ptr::NonNull; - scope 29 (inlined std::slice::Iter::<'_, T>::pre_dec_end) { - let mut _23: *mut *const T; - let mut _24: *mut std::ptr::NonNull; - let mut _25: std::ptr::NonNull; - let mut _28: std::ptr::NonNull; - let mut _30: *mut *const T; - let mut _31: *mut usize; - let mut _32: usize; - let mut _33: usize; - scope 30 { - scope 31 { - } - scope 32 { - scope 35 (inlined NonNull::::sub) { - scope 36 (inlined core::num::::unchecked_neg) { - scope 37 (inlined core::ub_checks::check_language_ub) { - scope 38 (inlined core::ub_checks::check_language_ub::runtime) { - } - } - } - scope 39 (inlined NonNull::::offset) { - let mut _26: *const T; - let mut _27: *const T; - } - } - } - scope 33 (inlined std::ptr::mut_ptr::::cast::) { - } - scope 34 (inlined std::ptr::mut_ptr::::cast::>) { - } - } - } - scope 40 (inlined NonNull::::as_ref::<'_>) { - let mut _34: std::ptr::NonNull; - scope 41 (inlined NonNull::::as_ptr) { - let mut _35: *const T; - } - scope 42 (inlined std::ptr::mut_ptr::::cast_const) { - } - } - } - } + let mut _14: &mut std::slice::Iter<'_, T>; } } scope 3 (inlined core::slice::::iter) { @@ -178,155 +107,53 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb4: { - StorageLive(_37); - StorageLive(_22); - StorageLive(_21); - StorageLive(_16); - StorageLive(_36); - StorageLive(_20); - switchInt(const ::IS_ZST) -> [0: bb5, otherwise: bb6]; + StorageLive(_15); + StorageLive(_14); + _14 = &mut (_13.0: std::slice::Iter<'_, T>); + _15 = as DoubleEndedIterator>::next_back(move _14) -> [return: bb5, unwind: bb11]; } bb5: { - StorageLive(_15); - StorageLive(_14); - _14 = &raw const ((_13.0: std::slice::Iter<'_, T>).1: *const T); - _15 = _14 as *const std::ptr::NonNull (PtrToPtr); StorageDead(_14); - _16 = (*_15); - StorageDead(_15); - StorageLive(_18); - StorageLive(_19); - StorageLive(_17); - _17 = ((_13.0: std::slice::Iter<'_, T>).0: std::ptr::NonNull); - _18 = (_17.0: *const T); - StorageDead(_17); - _19 = (_16.0: *const T); - _20 = Eq(_18, _19); - StorageDead(_19); - StorageDead(_18); - goto -> bb7; + _16 = discriminant(_15); + switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - _21 = ((_13.0: std::slice::Iter<'_, T>).1: *const T); - _22 = _21 as usize (Transmute); - _20 = Eq(_22, const 0_usize); - goto -> bb7; + StorageDead(_15); + StorageDead(_13); + drop(_2) -> [return: bb7, unwind continue]; } bb7: { - switchInt(move _20) -> [0: bb8, otherwise: bb18]; + return; } bb8: { - StorageLive(_35); - StorageLive(_29); - StorageLive(_31); - StorageLive(_24); - switchInt(const ::IS_ZST) -> [0: bb9, otherwise: bb13]; + _17 = ((_15 as Some).0: &T); + StorageLive(_18); + _18 = &_2; + StorageLive(_19); + _19 = (_17,); + _20 = >::call(move _18, move _19) -> [return: bb9, unwind: bb11]; } bb9: { - StorageLive(_23); - _23 = &raw mut ((_13.0: std::slice::Iter<'_, T>).1: *const T); - _24 = _23 as *mut std::ptr::NonNull (PtrToPtr); - StorageDead(_23); - StorageLive(_28); - _25 = (*_24); - switchInt(const ::IS_ZST) -> [0: bb10, otherwise: bb11]; + StorageDead(_19); + StorageDead(_18); + StorageDead(_15); + goto -> bb4; } bb10: { - StorageLive(_27); - StorageLive(_26); - _26 = (_25.0: *const T); - _27 = Offset(move _26, const -1_isize); - StorageDead(_26); - _28 = NonNull:: { pointer: move _27 }; - StorageDead(_27); - goto -> bb12; - } - - bb11: { - _28 = _25; - goto -> bb12; - } - - bb12: { - (*_24) = move _28; - StorageDead(_28); - _29 = (*_24); - goto -> bb14; - } - - bb13: { - StorageLive(_30); - _30 = &raw mut ((_13.0: std::slice::Iter<'_, T>).1: *const T); - _31 = _30 as *mut usize (PtrToPtr); - StorageDead(_30); - StorageLive(_33); - StorageLive(_32); - _32 = (*_31); - _33 = SubUnchecked(move _32, const 1_usize); - StorageDead(_32); - (*_31) = move _33; - StorageDead(_33); - _29 = ((_13.0: std::slice::Iter<'_, T>).0: std::ptr::NonNull); - goto -> bb14; + unreachable; } - bb14: { - StorageDead(_24); - StorageDead(_31); - StorageLive(_34); - _34 = _29; - _35 = (_34.0: *const T); - StorageDead(_34); - _36 = &(*_35); - StorageDead(_29); - StorageDead(_35); - _37 = Option::<&T>::Some(_36); - StorageDead(_20); - StorageDead(_36); - StorageDead(_16); - StorageDead(_21); - StorageDead(_22); - _38 = ((_37 as Some).0: &T); - StorageLive(_39); - _39 = &_2; - StorageLive(_40); - _40 = (_38,); - _41 = >::call(move _39, move _40) -> [return: bb15, unwind: bb16]; + bb11 (cleanup): { + drop(_2) -> [return: bb12, unwind terminate(cleanup)]; } - bb15: { - StorageDead(_40); - StorageDead(_39); - StorageDead(_37); - goto -> bb4; - } - - bb16 (cleanup): { - drop(_2) -> [return: bb17, unwind terminate(cleanup)]; - } - - bb17 (cleanup): { + bb12 (cleanup): { resume; } - - bb18: { - StorageDead(_20); - StorageDead(_36); - StorageDead(_16); - StorageDead(_21); - StorageDead(_22); - StorageDead(_37); - StorageDead(_13); - drop(_2) -> [return: bb19, unwind continue]; - } - - bb19: { - return; - } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-abort.mir index 2df346c081c8e..78f96bf419559 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-abort.mir @@ -3,205 +3,12 @@ fn slice_iter_mut_next_back(_1: &mut std::slice::IterMut<'_, T>) -> Option<&mut T> { debug it => _1; let mut _0: std::option::Option<&mut T>; - scope 1 (inlined as DoubleEndedIterator>::next_back) { - let mut _2: *const *mut T; - let mut _3: *const std::ptr::NonNull; - let mut _8: bool; - let mut _9: *mut T; - let mut _25: &mut T; - scope 2 { - let _4: std::ptr::NonNull; - let _10: usize; - scope 3 { - } - scope 4 { - scope 8 (inlined as PartialEq>::eq) { - let mut _5: std::ptr::NonNull; - scope 9 (inlined NonNull::::as_ptr) { - let mut _6: *const T; - } - scope 10 (inlined NonNull::::as_ptr) { - let mut _7: *const T; - } - } - } - scope 5 (inlined std::ptr::mut_ptr::::addr) { - scope 6 (inlined std::ptr::mut_ptr::::cast::<()>) { - } - } - scope 7 (inlined std::ptr::const_ptr::::cast::>) { - } - } - scope 11 (inlined std::slice::IterMut::<'_, T>::next_back_unchecked) { - let mut _17: std::ptr::NonNull; - scope 12 (inlined std::slice::IterMut::<'_, T>::pre_dec_end) { - let mut _11: *mut *mut T; - let mut _12: *mut std::ptr::NonNull; - let mut _13: std::ptr::NonNull; - let mut _16: std::ptr::NonNull; - let mut _18: *mut *mut T; - let mut _19: *mut usize; - let mut _20: usize; - let mut _21: usize; - scope 13 { - scope 14 { - } - scope 15 { - scope 18 (inlined NonNull::::sub) { - scope 19 (inlined core::num::::unchecked_neg) { - scope 20 (inlined core::ub_checks::check_language_ub) { - scope 21 (inlined core::ub_checks::check_language_ub::runtime) { - } - } - } - scope 22 (inlined NonNull::::offset) { - let mut _14: *const T; - let mut _15: *const T; - } - } - } - scope 16 (inlined std::ptr::mut_ptr::::cast::) { - } - scope 17 (inlined std::ptr::mut_ptr::::cast::>) { - } - } - } - scope 23 (inlined NonNull::::as_mut::<'_>) { - let mut _22: std::ptr::NonNull; - let mut _24: *mut T; - scope 24 (inlined NonNull::::as_ptr) { - let mut _23: *const T; - } - } - } - } bb0: { - StorageLive(_10); - StorageLive(_9); - StorageLive(_4); - StorageLive(_25); - StorageLive(_8); - switchInt(const ::IS_ZST) -> [0: bb1, otherwise: bb2]; + _0 = as DoubleEndedIterator>::next_back(move _1) -> [return: bb1, unwind unreachable]; } bb1: { - StorageLive(_3); - StorageLive(_2); - _2 = &raw const ((*_1).1: *mut T); - _3 = _2 as *const std::ptr::NonNull (PtrToPtr); - StorageDead(_2); - _4 = (*_3); - StorageDead(_3); - StorageLive(_6); - StorageLive(_7); - StorageLive(_5); - _5 = ((*_1).0: std::ptr::NonNull); - _6 = (_5.0: *const T); - StorageDead(_5); - _7 = (_4.0: *const T); - _8 = Eq(_6, _7); - StorageDead(_7); - StorageDead(_6); - goto -> bb3; - } - - bb2: { - _9 = ((*_1).1: *mut T); - _10 = _9 as usize (Transmute); - _8 = Eq(_10, const 0_usize); - goto -> bb3; - } - - bb3: { - switchInt(move _8) -> [0: bb4, otherwise: bb11]; - } - - bb4: { - StorageLive(_24); - StorageLive(_17); - StorageLive(_19); - StorageLive(_12); - switchInt(const ::IS_ZST) -> [0: bb5, otherwise: bb9]; - } - - bb5: { - StorageLive(_11); - _11 = &raw mut ((*_1).1: *mut T); - _12 = _11 as *mut std::ptr::NonNull (PtrToPtr); - StorageDead(_11); - StorageLive(_16); - _13 = (*_12); - switchInt(const ::IS_ZST) -> [0: bb6, otherwise: bb7]; - } - - bb6: { - StorageLive(_15); - StorageLive(_14); - _14 = (_13.0: *const T); - _15 = Offset(move _14, const -1_isize); - StorageDead(_14); - _16 = NonNull:: { pointer: move _15 }; - StorageDead(_15); - goto -> bb8; - } - - bb7: { - _16 = _13; - goto -> bb8; - } - - bb8: { - (*_12) = move _16; - StorageDead(_16); - _17 = (*_12); - goto -> bb10; - } - - bb9: { - StorageLive(_18); - _18 = &raw mut ((*_1).1: *mut T); - _19 = _18 as *mut usize (PtrToPtr); - StorageDead(_18); - StorageLive(_21); - StorageLive(_20); - _20 = (*_19); - _21 = SubUnchecked(move _20, const 1_usize); - StorageDead(_20); - (*_19) = move _21; - StorageDead(_21); - _17 = ((*_1).0: std::ptr::NonNull); - goto -> bb10; - } - - bb10: { - StorageDead(_12); - StorageDead(_19); - StorageLive(_22); - _22 = _17; - StorageLive(_23); - _23 = (_22.0: *const T); - _24 = move _23 as *mut T (PtrToPtr); - StorageDead(_23); - StorageDead(_22); - _25 = &mut (*_24); - StorageDead(_17); - StorageDead(_24); - _0 = Option::<&mut T>::Some(_25); - goto -> bb12; - } - - bb11: { - _0 = const {transmute(0x0000000000000000): Option<&mut T>}; - goto -> bb12; - } - - bb12: { - StorageDead(_8); - StorageDead(_25); - StorageDead(_4); - StorageDead(_9); - StorageDead(_10); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-unwind.mir index 2df346c081c8e..dfe5e206fadaf 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-unwind.mir @@ -3,205 +3,12 @@ fn slice_iter_mut_next_back(_1: &mut std::slice::IterMut<'_, T>) -> Option<&mut T> { debug it => _1; let mut _0: std::option::Option<&mut T>; - scope 1 (inlined as DoubleEndedIterator>::next_back) { - let mut _2: *const *mut T; - let mut _3: *const std::ptr::NonNull; - let mut _8: bool; - let mut _9: *mut T; - let mut _25: &mut T; - scope 2 { - let _4: std::ptr::NonNull; - let _10: usize; - scope 3 { - } - scope 4 { - scope 8 (inlined as PartialEq>::eq) { - let mut _5: std::ptr::NonNull; - scope 9 (inlined NonNull::::as_ptr) { - let mut _6: *const T; - } - scope 10 (inlined NonNull::::as_ptr) { - let mut _7: *const T; - } - } - } - scope 5 (inlined std::ptr::mut_ptr::::addr) { - scope 6 (inlined std::ptr::mut_ptr::::cast::<()>) { - } - } - scope 7 (inlined std::ptr::const_ptr::::cast::>) { - } - } - scope 11 (inlined std::slice::IterMut::<'_, T>::next_back_unchecked) { - let mut _17: std::ptr::NonNull; - scope 12 (inlined std::slice::IterMut::<'_, T>::pre_dec_end) { - let mut _11: *mut *mut T; - let mut _12: *mut std::ptr::NonNull; - let mut _13: std::ptr::NonNull; - let mut _16: std::ptr::NonNull; - let mut _18: *mut *mut T; - let mut _19: *mut usize; - let mut _20: usize; - let mut _21: usize; - scope 13 { - scope 14 { - } - scope 15 { - scope 18 (inlined NonNull::::sub) { - scope 19 (inlined core::num::::unchecked_neg) { - scope 20 (inlined core::ub_checks::check_language_ub) { - scope 21 (inlined core::ub_checks::check_language_ub::runtime) { - } - } - } - scope 22 (inlined NonNull::::offset) { - let mut _14: *const T; - let mut _15: *const T; - } - } - } - scope 16 (inlined std::ptr::mut_ptr::::cast::) { - } - scope 17 (inlined std::ptr::mut_ptr::::cast::>) { - } - } - } - scope 23 (inlined NonNull::::as_mut::<'_>) { - let mut _22: std::ptr::NonNull; - let mut _24: *mut T; - scope 24 (inlined NonNull::::as_ptr) { - let mut _23: *const T; - } - } - } - } bb0: { - StorageLive(_10); - StorageLive(_9); - StorageLive(_4); - StorageLive(_25); - StorageLive(_8); - switchInt(const ::IS_ZST) -> [0: bb1, otherwise: bb2]; + _0 = as DoubleEndedIterator>::next_back(move _1) -> [return: bb1, unwind continue]; } bb1: { - StorageLive(_3); - StorageLive(_2); - _2 = &raw const ((*_1).1: *mut T); - _3 = _2 as *const std::ptr::NonNull (PtrToPtr); - StorageDead(_2); - _4 = (*_3); - StorageDead(_3); - StorageLive(_6); - StorageLive(_7); - StorageLive(_5); - _5 = ((*_1).0: std::ptr::NonNull); - _6 = (_5.0: *const T); - StorageDead(_5); - _7 = (_4.0: *const T); - _8 = Eq(_6, _7); - StorageDead(_7); - StorageDead(_6); - goto -> bb3; - } - - bb2: { - _9 = ((*_1).1: *mut T); - _10 = _9 as usize (Transmute); - _8 = Eq(_10, const 0_usize); - goto -> bb3; - } - - bb3: { - switchInt(move _8) -> [0: bb4, otherwise: bb11]; - } - - bb4: { - StorageLive(_24); - StorageLive(_17); - StorageLive(_19); - StorageLive(_12); - switchInt(const ::IS_ZST) -> [0: bb5, otherwise: bb9]; - } - - bb5: { - StorageLive(_11); - _11 = &raw mut ((*_1).1: *mut T); - _12 = _11 as *mut std::ptr::NonNull (PtrToPtr); - StorageDead(_11); - StorageLive(_16); - _13 = (*_12); - switchInt(const ::IS_ZST) -> [0: bb6, otherwise: bb7]; - } - - bb6: { - StorageLive(_15); - StorageLive(_14); - _14 = (_13.0: *const T); - _15 = Offset(move _14, const -1_isize); - StorageDead(_14); - _16 = NonNull:: { pointer: move _15 }; - StorageDead(_15); - goto -> bb8; - } - - bb7: { - _16 = _13; - goto -> bb8; - } - - bb8: { - (*_12) = move _16; - StorageDead(_16); - _17 = (*_12); - goto -> bb10; - } - - bb9: { - StorageLive(_18); - _18 = &raw mut ((*_1).1: *mut T); - _19 = _18 as *mut usize (PtrToPtr); - StorageDead(_18); - StorageLive(_21); - StorageLive(_20); - _20 = (*_19); - _21 = SubUnchecked(move _20, const 1_usize); - StorageDead(_20); - (*_19) = move _21; - StorageDead(_21); - _17 = ((*_1).0: std::ptr::NonNull); - goto -> bb10; - } - - bb10: { - StorageDead(_12); - StorageDead(_19); - StorageLive(_22); - _22 = _17; - StorageLive(_23); - _23 = (_22.0: *const T); - _24 = move _23 as *mut T (PtrToPtr); - StorageDead(_23); - StorageDead(_22); - _25 = &mut (*_24); - StorageDead(_17); - StorageDead(_24); - _0 = Option::<&mut T>::Some(_25); - goto -> bb12; - } - - bb11: { - _0 = const {transmute(0x0000000000000000): Option<&mut T>}; - goto -> bb12; - } - - bb12: { - StorageDead(_8); - StorageDead(_25); - StorageDead(_4); - StorageDead(_9); - StorageDead(_10); return; } } diff --git a/tests/run-make/arguments-non-c-like-enum/rmake.rs b/tests/run-make/arguments-non-c-like-enum/rmake.rs index 88f4d664aa626..036691e850931 100644 --- a/tests/run-make/arguments-non-c-like-enum/rmake.rs +++ b/tests/run-make/arguments-non-c-like-enum/rmake.rs @@ -10,8 +10,8 @@ pub fn main() { cc().input("test.c") .input(static_lib_name("nonclike")) .out_exe("test") - .args(&extra_c_flags()) - .args(&extra_cxx_flags()) + .args(extra_c_flags()) + .args(extra_cxx_flags()) .inspect(|cmd| eprintln!("{cmd:?}")) .run(); run("test"); diff --git a/tests/run-make/c-link-to-rust-staticlib/rmake.rs b/tests/run-make/c-link-to-rust-staticlib/rmake.rs index 2edd36b9ec0b7..d60b37524f43c 100644 --- a/tests/run-make/c-link-to-rust-staticlib/rmake.rs +++ b/tests/run-make/c-link-to-rust-staticlib/rmake.rs @@ -9,7 +9,7 @@ use std::fs; fn main() { rustc().input("foo.rs").run(); - cc().input("bar.c").input(static_lib_name("foo")).out_exe("bar").args(&extra_c_flags()).run(); + cc().input("bar.c").input(static_lib_name("foo")).out_exe("bar").args(extra_c_flags()).run(); run("bar"); remove_file(static_lib_name("foo")); run("bar"); diff --git a/tests/run-make/c-link-to-rust-va-list-fn/rmake.rs b/tests/run-make/c-link-to-rust-va-list-fn/rmake.rs index a01e259bce010..63904bea6227b 100644 --- a/tests/run-make/c-link-to-rust-va-list-fn/rmake.rs +++ b/tests/run-make/c-link-to-rust-va-list-fn/rmake.rs @@ -12,7 +12,7 @@ fn main() { cc().input("test.c") .input(static_lib_name("checkrust")) .out_exe("test") - .args(&extra_c_flags()) + .args(extra_c_flags()) .run(); run("test"); } diff --git a/tests/run-make/comment-section/rmake.rs b/tests/run-make/comment-section/rmake.rs index 41df04da7a578..188c6dcb25d2e 100644 --- a/tests/run-make/comment-section/rmake.rs +++ b/tests/run-make/comment-section/rmake.rs @@ -21,7 +21,7 @@ fn main() { .stdin("fn main() {}") .emit("link,obj") .arg("-Csave-temps") - .target(&target) + .target(target) .run(); // Check linked output has a `.comment` section with the expected content. diff --git a/tests/run-make/compressed-debuginfo/rmake.rs b/tests/run-make/compressed-debuginfo/rmake.rs index 9c6d50ab243cd..3a656f28c2241 100644 --- a/tests/run-make/compressed-debuginfo/rmake.rs +++ b/tests/run-make/compressed-debuginfo/rmake.rs @@ -5,7 +5,7 @@ // FIXME: This test isn't comprehensive and isn't covering all possible combinations. -use run_make_support::{assert_contains, cmd, run_in_tmpdir, rustc}; +use run_make_support::{assert_contains, cmd, llvm_readobj, run_in_tmpdir, rustc}; fn check_compression(compression: &str, to_find: &str) { run_in_tmpdir(|| { @@ -19,12 +19,11 @@ fn check_compression(compression: &str, to_find: &str) { .run(); let stderr = out.stderr_utf8(); if stderr.is_empty() { - // FIXME: `readelf` might need to be replaced with `llvm-readelf`. - cmd("readelf").arg("-t").arg("foo.o").run().assert_stdout_contains(to_find); + llvm_readobj().arg("-t").arg("foo.o").run().assert_stdout_contains(to_find); } else { assert_contains( - &stderr, - &format!("unknown debuginfo compression algorithm {compression}"), + stderr, + format!("unknown debuginfo compression algorithm {compression}"), ); } }); diff --git a/tests/run-make/debug-assertions/Makefile b/tests/run-make/debug-assertions/Makefile deleted file mode 100644 index 4501459e9d1d8..0000000000000 --- a/tests/run-make/debug-assertions/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -# ignore-cross-compile -# needs-unwind -include ../tools.mk - -all: - $(RUSTC) debug.rs -C debug-assertions=no - $(call RUN,debug) good - $(RUSTC) debug.rs -C opt-level=0 - $(call RUN,debug) bad - $(RUSTC) debug.rs -C opt-level=1 - $(call RUN,debug) good - $(RUSTC) debug.rs -C opt-level=2 - $(call RUN,debug) good - $(RUSTC) debug.rs -C opt-level=3 - $(call RUN,debug) good - $(RUSTC) debug.rs -C opt-level=s - $(call RUN,debug) good - $(RUSTC) debug.rs -C opt-level=z - $(call RUN,debug) good - $(RUSTC) debug.rs -O - $(call RUN,debug) good - $(RUSTC) debug.rs - $(call RUN,debug) bad - $(RUSTC) debug.rs -C debug-assertions=yes -O - $(call RUN,debug) bad - $(RUSTC) debug.rs -C debug-assertions=yes -C opt-level=1 - $(call RUN,debug) bad diff --git a/tests/run-make/debug-assertions/debug.rs b/tests/run-make/debug-assertions/debug.rs index 9eebf60ded09b..1f27c04a16d45 100644 --- a/tests/run-make/debug-assertions/debug.rs +++ b/tests/run-make/debug-assertions/debug.rs @@ -1,15 +1,13 @@ +#![allow(internal_features)] #![feature(rustc_attrs)] #![deny(warnings)] -use std::env; use std::thread; fn main() { - let should_fail = env::args().nth(1) == Some("bad".to_string()); - - assert_eq!(thread::spawn(debug_assert_eq).join().is_err(), should_fail); - assert_eq!(thread::spawn(debug_assert).join().is_err(), should_fail); - assert_eq!(thread::spawn(overflow).join().is_err(), should_fail); + assert!(thread::spawn(debug_assert_eq).join().is_ok()); + assert!(thread::spawn(debug_assert).join().is_ok()); + assert!(thread::spawn(overflow).join().is_ok()); } fn debug_assert_eq() { diff --git a/tests/run-make/debug-assertions/rmake.rs b/tests/run-make/debug-assertions/rmake.rs new file mode 100644 index 0000000000000..ba8be9488a8d8 --- /dev/null +++ b/tests/run-make/debug-assertions/rmake.rs @@ -0,0 +1,37 @@ +// debug.rs contains some "debug assertion" statements which +// should only be enabled in either non-optimized builds or when +// `-C debug-assertions` is set to yes. These debug assertions +// are guaranteed to fail, so this test checks that the run command +// fails where debug assertions should be activated, and succeeds where +// debug assertions should be disabled. +// See https://github.com/rust-lang/rust/pull/22980 + +//@ ignore-cross-compile +//@ needs-unwind + +use run_make_support::{run, run_fail, rustc}; + +fn main() { + rustc().input("debug.rs").arg("-Cdebug-assertions=no").run(); + run("debug"); + rustc().input("debug.rs").opt_level("0").run(); + run_fail("debug"); + rustc().input("debug.rs").opt_level("1").run(); + run("debug"); + rustc().input("debug.rs").opt_level("2").run(); + run("debug"); + rustc().input("debug.rs").opt_level("3").run(); + run("debug"); + rustc().input("debug.rs").opt_level("s").run(); + run("debug"); + rustc().input("debug.rs").opt_level("z").run(); + run("debug"); + rustc().input("debug.rs").opt().run(); + run("debug"); + rustc().input("debug.rs").run(); + run_fail("debug"); + rustc().input("debug.rs").opt().arg("-Cdebug-assertions=yes").run(); + run_fail("debug"); + rustc().input("debug.rs").opt_level("1").arg("-Cdebug-assertions=yes").run(); + run_fail("debug"); +} diff --git a/tests/run-make/emit-stack-sizes/Makefile b/tests/run-make/emit-stack-sizes/Makefile deleted file mode 100644 index b546fcba5121e..0000000000000 --- a/tests/run-make/emit-stack-sizes/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -include ../tools.mk - -# ignore-windows -# ignore-apple -# -# This feature only works when the output object format is ELF so we ignore -# Apple and Windows - -# check that the .stack_sizes section is generated -all: - $(RUSTC) -C opt-level=3 -Z emit-stack-sizes --emit=obj foo.rs - size -A $(TMPDIR)/foo.o | $(CGREP) .stack_sizes diff --git a/tests/run-make/emit-stack-sizes/rmake.rs b/tests/run-make/emit-stack-sizes/rmake.rs new file mode 100644 index 0000000000000..53cc9ee5943f8 --- /dev/null +++ b/tests/run-make/emit-stack-sizes/rmake.rs @@ -0,0 +1,23 @@ +// Running rustc with the -Z emit-stack-sizes +// flag enables diagnostics to seek stack overflows +// at compile time. This test compiles a rust file +// with this flag, then checks that the output object +// file contains the section "stack_sizes", where +// this diagnostics information should be located. +// See https://github.com/rust-lang/rust/pull/51946 + +//@ ignore-windows +//@ ignore-apple +// Reason: this feature only works when the output object format is ELF. +// This won't be the case on Windows/OSX - for example, OSX produces a Mach-O binary. + +use run_make_support::{llvm_readobj, rustc}; + +fn main() { + rustc().opt_level("3").arg("-Zemit-stack-sizes").emit("obj").input("foo.rs").run(); + llvm_readobj() + .arg("--section-headers") + .input("foo.o") + .run() + .assert_stdout_contains(".stack_sizes"); +} diff --git a/tests/run-make/glibc-staticlib-args/rmake.rs b/tests/run-make/glibc-staticlib-args/rmake.rs index 8ab10419ab9d3..fc13be538123b 100644 --- a/tests/run-make/glibc-staticlib-args/rmake.rs +++ b/tests/run-make/glibc-staticlib-args/rmake.rs @@ -11,8 +11,8 @@ fn main() { cc().input("program.c") .arg(static_lib_name("library")) .out_exe("program") - .args(&extra_c_flags()) - .args(&extra_cxx_flags()) + .args(extra_c_flags()) + .args(extra_cxx_flags()) .run(); run(&bin_name("program")); } diff --git a/tests/run-make/inaccessible-temp-dir/rmake.rs b/tests/run-make/inaccessible-temp-dir/rmake.rs index c6bfae4cc01db..6b3e9e0b29e38 100644 --- a/tests/run-make/inaccessible-temp-dir/rmake.rs +++ b/tests/run-make/inaccessible-temp-dir/rmake.rs @@ -28,7 +28,7 @@ fn main() { // Run rustc with `-Z temps-dir` set to a directory *inside* the inaccessible one, // so that it can't create `tmp`. rustc() - .target(&target()) + .target(target()) .input("program.rs") .arg("-Ztemps-dir=inaccessible/tmp") .run_fail() diff --git a/tests/run-make/issue-68794-textrel-on-minimal-lib/Makefile b/tests/run-make/issue-68794-textrel-on-minimal-lib/Makefile deleted file mode 100644 index 6140b39c0e2aa..0000000000000 --- a/tests/run-make/issue-68794-textrel-on-minimal-lib/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -# ignore-cross-compile -# Regression test for issue #68794 -# -# Verify that no text relocations are accidentally introduced by linking a -# minimal rust staticlib. -# -# The test links a rust static library into a shared library, and checks that -# the linker doesn't have to flag the resulting file as containing TEXTRELs. - -include ../tools.mk - -# only-linux - -all: - $(RUSTC) foo.rs - $(CC) bar.c $(call STATICLIB,foo) -fPIC -shared -o $(call DYLIB,bar) \ - $(EXTRACFLAGS) $(EXTRACXXFLAGS) - readelf -d $(call DYLIB,bar) | grep TEXTREL; test $$? -eq 1 diff --git a/tests/run-make/libtest-padding/Makefile b/tests/run-make/libtest-padding/Makefile deleted file mode 100644 index c8e2fc01f677d..0000000000000 --- a/tests/run-make/libtest-padding/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# ignore-cross-compile because we run the compiled code -# needs-unwind because #[bench] and -Cpanic=abort requires -Zpanic-abort-tests -include ../tools.mk - -NORMALIZE=sed 's%[0-9,\.]\{1,\} ns/iter (+/- [0-9,\.]\{1,\})%?? ns/iter (+/- ??)%' | sed 's%finished in [0-9\.]\{1,\}%finished in ??%' - -all: - $(RUSTC) --test tests.rs - - $(call RUN,tests) --test-threads=1 | $(NORMALIZE) > "$(TMPDIR)"/test.stdout - $(RUSTC_TEST_OP) "$(TMPDIR)"/test.stdout test.stdout - - $(call RUN,tests) --test-threads=1 --bench | $(NORMALIZE) > "$(TMPDIR)"/bench.stdout - $(RUSTC_TEST_OP) "$(TMPDIR)"/bench.stdout bench.stdout diff --git a/tests/run-make/libtest-padding/rmake.rs b/tests/run-make/libtest-padding/rmake.rs new file mode 100644 index 0000000000000..4b17ba19bf7da --- /dev/null +++ b/tests/run-make/libtest-padding/rmake.rs @@ -0,0 +1,46 @@ +// Benchmarks, when ran as tests, would cause strange indentations +// to appear in the output. This was because padding formatting was +// applied before the conversion from bench to test, and not afterwards. +// Now that this bug has been fixed in #118548, this test checks that it +// does not make a resurgence by comparing the output of --bench with an +// example stdout file. +// See https://github.com/rust-lang/rust/issues/104092 + +//@ ignore-cross-compile +// Reason: the compiled code is ran +//@ needs-unwind +// Reason: #[bench] requires -Z panic-abort-tests + +use run_make_support::{diff, run_with_args, rustc}; + +fn main() { + rustc().arg("--test").input("tests.rs").run(); + let out = run_with_args("tests", &["--test-threads=1"]).stdout_utf8(); + diff() + .expected_file("test.stdout") + .actual_text("actual-test-stdout", out) + .normalize( + // Replace all instances of (arbitrary numbers) + // [1.2345 ns/iter (+/- 0.1234)] + // with + // [?? ns/iter (+/- ??)] + r#"(\d+(?:[.,]\d+)*)\s*ns/iter\s*\(\+/-\s*(\d+(?:[.,]\d+)*)\)"#, + "?? ns/iter (+/- ??)", + ) + // Replace all instances of (arbitrary numbers) + // finished in 8.0000 s + // with + // finished in ?? + .normalize(r#"finished\s+in\s+(\d+(?:\.\d+)*)"#, "finished in ??") + .run(); + let out = run_with_args("tests", &["--test-threads=1", "--bench"]).stdout_utf8(); + diff() + .expected_file("bench.stdout") + .actual_text("actual-bench-stdout", out) + .normalize( + r#"(\d+(?:[.,]\d+)*)\s*ns/iter\s*\(\+/-\s*(\d+(?:[.,]\d+)*)\)"#, + "?? ns/iter (+/- ??)", + ) + .normalize(r#"finished\s+in\s+(\d+(?:\.\d+)*)"#, "finished in ??") + .run(); +} diff --git a/tests/run-make/llvm-ident/Makefile b/tests/run-make/llvm-ident/Makefile deleted file mode 100644 index e583e6018e0bf..0000000000000 --- a/tests/run-make/llvm-ident/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -include ../tools.mk - -# only-linux - -all: - # `-Ccodegen-units=16 -Copt-level=2` is used here to trigger thin LTO - # across codegen units to test deduplication of the named metadata - # (see `LLVMRustPrepareThinLTOImport` for details). - echo 'fn main(){}' | $(RUSTC) - --emit=link,obj -Csave-temps -Ccodegen-units=16 -Copt-level=2 --target=$(TARGET) - - # `llvm-dis` is used here since `--emit=llvm-ir` does not emit LLVM IR - # for temporary outputs. - "$(LLVM_BIN_DIR)"/llvm-dis $(TMPDIR)/*.bc - - # Check LLVM IR files (including temporary outputs) have `!llvm.ident` - # named metadata, reusing the related codegen test. - set -e; for f in $(TMPDIR)/*.ll; do \ - $(LLVM_FILECHECK) --input-file $$f ../../codegen/llvm-ident.rs; \ - done diff --git a/tests/run-make/llvm-ident/rmake.rs b/tests/run-make/llvm-ident/rmake.rs new file mode 100644 index 0000000000000..f460829288e8c --- /dev/null +++ b/tests/run-make/llvm-ident/rmake.rs @@ -0,0 +1,41 @@ +//@ only-linux +//@ ignore-cross-compile + +use run_make_support::llvm::llvm_bin_dir; +use run_make_support::{cmd, env_var, llvm_filecheck, read_dir, rustc, source_root}; + +use std::ffi::OsStr; + +fn main() { + // `-Ccodegen-units=16 -Copt-level=2` is used here to trigger thin LTO + // across codegen units to test deduplication of the named metadata + // (see `LLVMRustPrepareThinLTOImport` for details). + rustc() + .emit("link,obj") + .arg("-") + .arg("-Csave-temps") + .codegen_units(16) + .opt_level("2") + .target(&env_var("TARGET")) + .stdin("fn main(){}") + .run(); + + // `llvm-dis` is used here since `--emit=llvm-ir` does not emit LLVM IR + // for temporary outputs. + let mut files = Vec::new(); + read_dir(".", |path| { + if path.is_file() && path.extension().is_some_and(|ext| ext == OsStr::new("bc")) { + files.push(path.to_path_buf()); + } + }); + cmd(llvm_bin_dir().join("llvm-dis")).args(&files).run(); + + // Check LLVM IR files (including temporary outputs) have `!llvm.ident` + // named metadata, reusing the related codegen test. + let llvm_ident_path = source_root().join("tests/codegen/llvm-ident.rs"); + read_dir(".", |path| { + if path.is_file() && path.extension().is_some_and(|ext| ext == OsStr::new("ll")) { + llvm_filecheck().input_file(path).arg(&llvm_ident_path).run(); + } + }); +} diff --git a/tests/run-make/mingw-export-call-convention/Makefile b/tests/run-make/mingw-export-call-convention/Makefile deleted file mode 100644 index 4a60059cc5441..0000000000000 --- a/tests/run-make/mingw-export-call-convention/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -include ../tools.mk - -# only-windows-gnu - -all: - $(RUSTC) foo.rs - # FIXME: we should make sure __stdcall calling convention is used here - # but that only works with LLD right now - nm -g "$(call IMPLIB,foo)" | $(CGREP) bar diff --git a/tests/run-make/mingw-export-call-convention/rmake.rs b/tests/run-make/mingw-export-call-convention/rmake.rs new file mode 100644 index 0000000000000..d1fb745a64de9 --- /dev/null +++ b/tests/run-make/mingw-export-call-convention/rmake.rs @@ -0,0 +1,13 @@ +// On windows-gnu, symbol exporting used to fail to export names +// with no_mangle. #72049 brought this feature up to par with msvc, +// and this test checks that the symbol "bar" is successfully exported. +// See https://github.com/rust-lang/rust/issues/50176 + +//@ only-x86_64-pc-windows-gnu + +use run_make_support::{llvm_readobj, rustc}; + +fn main() { + rustc().input("foo.rs").run(); + llvm_readobj().arg("--all").input("libfoo.dll.a").run().assert_stdout_contains("bar"); +} diff --git a/tests/run-make/mismatching-target-triples/Makefile b/tests/run-make/mismatching-target-triples/Makefile deleted file mode 100644 index 409388e041478..0000000000000 --- a/tests/run-make/mismatching-target-triples/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -include ../tools.mk - -# Issue #10814 -# -# these are no_std to avoid having to have the standard library or any -# linkers/assemblers for the relevant platform - -all: - $(RUSTC) foo.rs --target=i686-unknown-linux-gnu - $(RUSTC) bar.rs --target=x86_64-unknown-linux-gnu 2>&1 \ - | $(CGREP) 'couldn'"'"'t find crate `foo` with expected target triple x86_64-unknown-linux-gnu' diff --git a/tests/run-make/mismatching-target-triples/rmake.rs b/tests/run-make/mismatching-target-triples/rmake.rs new file mode 100644 index 0000000000000..6f41eac8cdaf4 --- /dev/null +++ b/tests/run-make/mismatching-target-triples/rmake.rs @@ -0,0 +1,15 @@ +// In this test, foo links against 32-bit architecture, and then, bar, which depends +// on foo, links against 64-bit architecture, causing a metadata mismatch due to the +// differences in target architectures. This used to cause an internal compiler error, +// now replaced by a clearer normal error message. This test checks that this aforementioned +// error message is used. +// See https://github.com/rust-lang/rust/issues/10814 + +use run_make_support::rustc; + +fn main() { + rustc().input("foo.rs").target("i686-unknown-linux-gnu").run(); + rustc().input("bar.rs").target("x86_64-unknown-linux-gnu").run_fail().assert_stderr_contains( + r#"couldn't find crate `foo` with expected target triple x86_64-unknown-linux-gnu"#, + ); +} diff --git a/tests/run-make/override-aliased-flags/Makefile b/tests/run-make/override-aliased-flags/Makefile deleted file mode 100644 index db1ff1ff98161..0000000000000 --- a/tests/run-make/override-aliased-flags/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -# FIXME: it would be good to check that it's actually the rightmost flags -# that are used when multiple flags are specified, but I can't think of a -# reliable way to check this. - -all: - # Test that `-O` and `-C opt-level` can be specified multiple times. - # The rightmost flag will be used over any previous flags. - $(RUSTC) -O -O main.rs - $(RUSTC) -O -C opt-level=0 main.rs - $(RUSTC) -C opt-level=0 -O main.rs - $(RUSTC) -C opt-level=0 -C opt-level=2 main.rs - $(RUSTC) -C opt-level=2 -C opt-level=0 main.rs - - # Test that `-g` and `-C debuginfo` can be specified multiple times. - # The rightmost flag will be used over any previous flags. - $(RUSTC) -g -g main.rs - $(RUSTC) -g -C debuginfo=0 main.rs - $(RUSTC) -C debuginfo=0 -g main.rs - $(RUSTC) -C debuginfo=0 -C debuginfo=2 main.rs - $(RUSTC) -C debuginfo=2 -C debuginfo=0 main.rs diff --git a/tests/run-make/override-aliased-flags/rmake.rs b/tests/run-make/override-aliased-flags/rmake.rs new file mode 100644 index 0000000000000..e610c04651e95 --- /dev/null +++ b/tests/run-make/override-aliased-flags/rmake.rs @@ -0,0 +1,24 @@ +//@ ignore-cross-compile + +use run_make_support::rustc; + +// FIXME: it would be good to check that it's actually the rightmost flags +// that are used when multiple flags are specified, but I can't think of a +// reliable way to check this. +fn main() { + // Test that `-O` and `-C opt-level` can be specified multiple times. + // The rightmost flag will be used over any previous flags. + rustc().arg("-O").arg("-O").input("main.rs").run(); + rustc().arg("-O").arg("-C").arg("opt-level=0").input("main.rs").run(); + rustc().arg("-C").arg("opt-level=0").arg("-O").input("main.rs").run(); + rustc().arg("-C").arg("opt-level=0").arg("-C").arg("opt-level=2").input("main.rs").run(); + rustc().arg("-C").arg("opt-level=2").arg("-C").arg("opt-level=0").input("main.rs").run(); + + // Test that `-g` and `-C debuginfo` can be specified multiple times. + // The rightmost flag will be used over any previous flags. + rustc().arg("-g").arg("-g").input("main.rs").run(); + rustc().arg("-g").arg("-C").arg("debuginfo=0").input("main.rs").run(); + rustc().arg("-C").arg("debuginfo=0").arg("-g").input("main.rs").run(); + rustc().arg("-C").arg("debuginfo=0").arg("-C").arg("debuginfo=2").input("main.rs").run(); + rustc().arg("-C").arg("debuginfo=2").arg("-C").arg("debuginfo=0").input("main.rs").run(); +} diff --git a/tests/run-make/pdb-alt-path/Makefile b/tests/run-make/pdb-alt-path/Makefile deleted file mode 100644 index 7a0ae3bf2ef0d..0000000000000 --- a/tests/run-make/pdb-alt-path/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -include ../tools.mk - -# only-windows-msvc - -all: - # Test that we don't have the full path to the PDB file in the binary - $(RUSTC) main.rs -g --crate-name my_crate_name --crate-type bin -Cforce-frame-pointers - $(CGREP) "my_crate_name.pdb" < $(TMPDIR)/my_crate_name.exe - $(CGREP) -v "\\my_crate_name.pdb" < $(TMPDIR)/my_crate_name.exe - - # Test that backtraces still can find debuginfo by checking that they contain symbol names and - # source locations. - $(TMPDIR)/my_crate_name.exe &> $(TMPDIR)/backtrace.txt - $(CGREP) "my_crate_name::fn_in_backtrace" < $(TMPDIR)/backtrace.txt - $(CGREP) "main.rs:15" < $(TMPDIR)/backtrace.txt - - # Test that explicitly passed `-Clink-arg=/PDBALTPATH:...` is respected - $(RUSTC) main.rs -g --crate-name my_crate_name --crate-type bin -Clink-arg=/PDBALTPATH:abcdefg.pdb -Cforce-frame-pointers - $(CGREP) "abcdefg.pdb" < $(TMPDIR)/my_crate_name.exe - $(CGREP) -v "my_crate_name.pdb" < $(TMPDIR)/my_crate_name.exe diff --git a/tests/run-make/pdb-alt-path/rmake.rs b/tests/run-make/pdb-alt-path/rmake.rs new file mode 100644 index 0000000000000..6311d6d9ed7d0 --- /dev/null +++ b/tests/run-make/pdb-alt-path/rmake.rs @@ -0,0 +1,39 @@ +// The information inside a .exe file contains a string of the PDB file name. +// This could be a security concern if the full path was exposed, as it could +// reveal information about the filesystem where the bin was first compiled. +// This should only be overridden by `-Clink-arg=/PDBALTPATH:...` - this test +// checks that no full file paths are exposed and that the override flag is respected. +// See https://github.com/rust-lang/rust/pull/121297 + +//@ only-x86_64-pc-windows-msvc + +use run_make_support::{bin_name, invalid_utf8_contains, invalid_utf8_not_contains, run, rustc}; + +fn main() { + // Test that we don't have the full path to the PDB file in the binary + rustc() + .input("main.rs") + .arg("-g") + .crate_name("my_crate_name") + .crate_type("bin") + .arg("-Cforce-frame-pointers") + .run(); + invalid_utf8_contains(&bin_name("my_crate_name"), "my_crate_name.pdb"); + invalid_utf8_not_contains(&bin_name("my_crate_name"), r#"\my_crate_name.pdb"#); + // Test that backtraces still can find debuginfo by checking that they contain symbol names and + // source locations. + let out = run(&bin_name("my_crate_name")); + out.assert_stdout_contains("my_crate_name::fn_in_backtrace"); + out.assert_stdout_contains("main.rs:15"); + // Test that explicitly passed `-Clink-arg=/PDBALTPATH:...` is respected + rustc() + .input("main.rs") + .arg("-g") + .crate_name("my_crate_name") + .crate_type("bin") + .link_arg("/PDBALTPATH:abcdefg.pdb") + .arg("-Cforce-frame-pointers") + .run(); + invalid_utf8_contains(&bin_name("my_crate_name"), "abcdefg.pdb"); + invalid_utf8_not_contains(&bin_name("my_crate_name"), "my_crate_name.pdb"); +} diff --git a/tests/run-make/pretty-print-to-file/Makefile b/tests/run-make/pretty-print-to-file/Makefile deleted file mode 100644 index ca11b8c47f06f..0000000000000 --- a/tests/run-make/pretty-print-to-file/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -include ../tools.mk - -all: - $(RUSTC) -o $(TMPDIR)/input.out -Zunpretty=normal input.rs - diff -u $(TMPDIR)/input.out input.pp diff --git a/tests/run-make/pretty-print-to-file/rmake.rs b/tests/run-make/pretty-print-to-file/rmake.rs new file mode 100644 index 0000000000000..c23514ae84960 --- /dev/null +++ b/tests/run-make/pretty-print-to-file/rmake.rs @@ -0,0 +1,12 @@ +// The "pretty-printer" of rustc translates source code into other formats, +// which is useful for debugging. This test checks the "normal" version of +// -Zunpretty, which should format the poorly formatted input.rs into a one-line +// function identical to the one in input.pp. +// See https://github.com/rust-lang/rust/commit/da25539c1ab295ec40261109557dd4526923928c + +use run_make_support::{diff, rustc}; + +fn main() { + rustc().output("input.out").arg("-Zunpretty=normal").input("input.rs").run(); + diff().expected_file("input.out").actual_file("input.pp").run(); +} diff --git a/tests/run-make/pretty-print-with-dep-file/Makefile b/tests/run-make/pretty-print-with-dep-file/Makefile deleted file mode 100644 index fa8089eb6a552..0000000000000 --- a/tests/run-make/pretty-print-with-dep-file/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -include ../tools.mk - -all: - $(RUSTC) --emit=dep-info -Zunpretty=expanded with-dep.rs - $(CGREP) "with-dep.rs" < $(TMPDIR)/with-dep.d - -rm $(TMPDIR)/with-dep.d - - $(RUSTC) --emit=dep-info -Zunpretty=normal with-dep.rs - ! test -f $(TMPDIR)/with-dep.d diff --git a/tests/run-make/pretty-print-with-dep-file/rmake.rs b/tests/run-make/pretty-print-with-dep-file/rmake.rs new file mode 100644 index 0000000000000..859a9781bb6e6 --- /dev/null +++ b/tests/run-make/pretty-print-with-dep-file/rmake.rs @@ -0,0 +1,17 @@ +// Passing --emit=dep-info to the Rust compiler should create a .d file... +// but it failed to do so in Rust 1.69.0 when combined with -Z unpretty=expanded +// due to a bug. This test checks that -Z unpretty=expanded does not prevent the +// generation of the dep-info file, and that its -Z unpretty=normal counterpart +// does not get an unexpected dep-info file. +// See https://github.com/rust-lang/rust/issues/112898 + +use run_make_support::{fs_wrapper, invalid_utf8_contains, rustc}; +use std::path::Path; + +fn main() { + rustc().emit("dep-info").arg("-Zunpretty=expanded").input("with-dep.rs").run(); + invalid_utf8_contains("with-dep.d", "with-dep.rs"); + fs_wrapper::remove_file("with-dep.d"); + rustc().emit("dep-info").arg("-Zunpretty=normal").input("with-dep.rs").run(); + assert!(!Path::new("with-dep.d").exists()); +} diff --git a/tests/run-make/print-check-cfg/rmake.rs b/tests/run-make/print-check-cfg/rmake.rs index f4b02b5e265be..4a79910c8e05e 100644 --- a/tests/run-make/print-check-cfg/rmake.rs +++ b/tests/run-make/print-check-cfg/rmake.rs @@ -86,12 +86,8 @@ fn main() { } fn check(CheckCfg { args, contains }: CheckCfg) { - let output = rustc() - .input("lib.rs") - .arg("-Zunstable-options") - .arg("--print=check-cfg") - .args(&*args) - .run(); + let output = + rustc().input("lib.rs").arg("-Zunstable-options").arg("--print=check-cfg").args(args).run(); let stdout = output.stdout_utf8(); diff --git a/tests/run-make/raw-dylib-cross-compilation/Makefile b/tests/run-make/raw-dylib-cross-compilation/Makefile deleted file mode 100644 index 2524f8500e154..0000000000000 --- a/tests/run-make/raw-dylib-cross-compilation/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Tests that raw-dylib cross compilation works correctly - -# needs-dlltool - -# i686 dlltool.exe can't product x64 binaries. -# ignore-i686-pc-windows-gnu - -include ../tools.mk - -all: - # Build as x86 and make sure that we have x86 objects only. - $(RUSTC) --crate-type lib --crate-name i686_raw_dylib_test --target i686-pc-windows-gnu lib.rs - "$(LLVM_BIN_DIR)"/llvm-objdump -a $(TMPDIR)/libi686_raw_dylib_test.rlib > $(TMPDIR)/i686.objdump.txt - $(CGREP) "file format coff-i386" < $(TMPDIR)/i686.objdump.txt - $(CGREP) -v "file format coff-x86-64" < $(TMPDIR)/i686.objdump.txt - # Build as x64 and make sure that we have x64 objects only. - $(RUSTC) --crate-type lib --crate-name x64_raw_dylib_test --target x86_64-pc-windows-gnu lib.rs - "$(LLVM_BIN_DIR)"/llvm-objdump -a $(TMPDIR)/libx64_raw_dylib_test.rlib > $(TMPDIR)/x64.objdump.txt - $(CGREP) "file format coff-x86-64" < $(TMPDIR)/x64.objdump.txt - $(CGREP) -v "file format coff-i386" < $(TMPDIR)/x64.objdump.txt diff --git a/tests/run-make/raw-dylib-cross-compilation/rmake.rs b/tests/run-make/raw-dylib-cross-compilation/rmake.rs new file mode 100644 index 0000000000000..3eb55546314df --- /dev/null +++ b/tests/run-make/raw-dylib-cross-compilation/rmake.rs @@ -0,0 +1,41 @@ +// When cross-compiling using `raw-dylib`, rustc would try to fetch some +// very specific `dlltool` to complete the cross-compilation (such as `i686-w64-mingw32-dlltool`) +// when Windows only calls it `dlltool`. This test performs some cross-compilation in a +// way that previously failed due to this bug, and checks that it succeeds. +// See https://github.com/rust-lang/rust/pull/108355 + +//@ ignore-i686-pc-windows-gnu +// Reason: dlltool on this distribution is unable to produce x64 binaries +//@ needs-dlltool +// Reason: this is the utility being checked by this test + +use run_make_support::{llvm_objdump, rust_lib_name, rustc}; + +fn main() { + // Build as x86 and make sure that we have x86 objects only. + rustc() + .crate_type("lib") + .crate_name("i686_raw_dylib_test") + .target("i686-pc-windows-gnu") + .input("lib.rs") + .run(); + llvm_objdump() + .arg("-a") + .input(rust_lib_name("i686_raw_dylib_test")) + .run() + .assert_stdout_contains("file format coff-i386") + .assert_stdout_not_contains("file format coff-x86-64"); + // Build as x64 and make sure that we have x64 objects only. + rustc() + .crate_type("lib") + .crate_name("x64_raw_dylib_test") + .target("x86_64-pc-windows-gnu") + .input("lib.rs") + .run(); + llvm_objdump() + .arg("-a") + .input(rust_lib_name("x64_raw_dylib_test")) + .run() + .assert_stdout_not_contains("file format coff-i386") + .assert_stdout_contains("file format coff-x86-64"); +} diff --git a/tests/run-make/remap-path-prefix/Makefile b/tests/run-make/remap-path-prefix/Makefile deleted file mode 100644 index 02423dea7d26c..0000000000000 --- a/tests/run-make/remap-path-prefix/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -include ../tools.mk - -# ignore-windows - -ifeq ($(UNAME),Darwin) - DEBUGINFOOPTS := -Csplit-debuginfo=off -else - DEBUGINFOOPTS := -endif - -all: remap remap-with-scope - -# Checks if remapping works if the remap-from string contains path to the working directory plus more -remap: - $(RUSTC) --remap-path-prefix $$PWD/auxiliary=/the/aux --crate-type=lib --emit=metadata auxiliary/lib.rs - grep "/the/aux/lib.rs" $(TMPDIR)/liblib.rmeta || exit 1 - ! grep "$$PWD/auxiliary" $(TMPDIR)/liblib.rmeta || exit 1 - -remap-with-scope: - $(RUSTC) --remap-path-prefix $$PWD/auxiliary=/the/aux -Zremap-path-scope=object $(DEBUGINFOOPTS) --crate-type=lib --emit=metadata auxiliary/lib.rs - grep "/the/aux/lib.rs" $(TMPDIR)/liblib.rmeta || exit 1 - ! grep "$$PWD/auxiliary" $(TMPDIR)/liblib.rmeta || exit 1 - - $(RUSTC) --remap-path-prefix $$PWD/auxiliary=/the/aux -Zremap-path-scope=macro $(DEBUGINFOOPTS) --crate-type=lib --emit=metadata auxiliary/lib.rs - grep "/the/aux/lib.rs" $(TMPDIR)/liblib.rmeta || exit 1 - ! grep "$$PWD/auxiliary" $(TMPDIR)/liblib.rmeta || exit 1 - - $(RUSTC) --remap-path-prefix $$PWD/auxiliary=/the/aux -Zremap-path-scope=diagnostics,object $(DEBUGINFOOPTS) --crate-type=lib --emit=metadata auxiliary/lib.rs - grep "/the/aux/lib.rs" $(TMPDIR)/liblib.rmeta || exit 1 - ! grep "$$PWD/auxiliary" $(TMPDIR)/liblib.rmeta || exit 1 diff --git a/tests/run-make/remap-path-prefix/rmake.rs b/tests/run-make/remap-path-prefix/rmake.rs new file mode 100644 index 0000000000000..62c0368e4b3a4 --- /dev/null +++ b/tests/run-make/remap-path-prefix/rmake.rs @@ -0,0 +1,87 @@ +// Generating metadata alongside remap-path-prefix would fail to actually remap the path +// in the metadata. After this was fixed in #85344, this test checks that "auxiliary" is being +// successfully remapped to "/the/aux" in the rmeta files. +// See https://github.com/rust-lang/rust/pull/85344 + +use run_make_support::bstr::ByteSlice; +use run_make_support::{bstr, fs_wrapper, is_darwin, rustc}; + +fn main() { + let mut out_simple = rustc(); + let mut out_object = rustc(); + let mut out_macro = rustc(); + let mut out_diagobj = rustc(); + out_simple + .remap_path_prefix("auxiliary", "/the/aux") + .crate_type("lib") + .emit("metadata") + .input("auxiliary/lib.rs"); + out_object + .remap_path_prefix("auxiliary", "/the/aux") + .crate_type("lib") + .emit("metadata") + .input("auxiliary/lib.rs"); + out_macro + .remap_path_prefix("auxiliary", "/the/aux") + .crate_type("lib") + .emit("metadata") + .input("auxiliary/lib.rs"); + out_diagobj + .remap_path_prefix("auxiliary", "/the/aux") + .crate_type("lib") + .emit("metadata") + .input("auxiliary/lib.rs"); + + out_simple.run(); + rmeta_contains("/the/aux/lib.rs"); + rmeta_not_contains("auxiliary"); + + out_object.arg("-Zremap-path-scope=object"); + out_macro.arg("-Zremap-path-scope=macro"); + out_diagobj.arg("-Zremap-path-scope=diagnostics,object"); + if is_darwin() { + out_object.arg("-Csplit-debuginfo=off"); + out_macro.arg("-Csplit-debuginfo=off"); + out_diagobj.arg("-Csplit-debuginfo=off"); + } + + out_object.run(); + rmeta_contains("/the/aux/lib.rs"); + rmeta_not_contains("auxiliary"); + out_macro.run(); + rmeta_contains("/the/aux/lib.rs"); + rmeta_not_contains("auxiliary"); + out_diagobj.run(); + rmeta_contains("/the/aux/lib.rs"); + rmeta_not_contains("auxiliary"); +} + +//FIXME(Oneirical): These could be generalized into run_make_support +// helper functions. +fn rmeta_contains(expected: &str) { + // Normalize to account for path differences in Windows. + if !bstr::BString::from(fs_wrapper::read("liblib.rmeta")) + .replace(b"\\", b"/") + .contains_str(expected) + { + eprintln!("=== FILE CONTENTS (LOSSY) ==="); + eprintln!("{}", String::from_utf8_lossy(&fs_wrapper::read("liblib.rmeta"))); + eprintln!("=== SPECIFIED TEXT ==="); + eprintln!("{}", expected); + panic!("specified text was not found in file"); + } +} + +fn rmeta_not_contains(expected: &str) { + // Normalize to account for path differences in Windows. + if bstr::BString::from(fs_wrapper::read("liblib.rmeta")) + .replace(b"\\", b"/") + .contains_str(expected) + { + eprintln!("=== FILE CONTENTS (LOSSY) ==="); + eprintln!("{}", String::from_utf8_lossy(&fs_wrapper::read("liblib.rmeta"))); + eprintln!("=== SPECIFIED TEXT ==="); + eprintln!("{}", expected); + panic!("specified text was not found in file"); + } +} diff --git a/tests/run-make/return-non-c-like-enum/Makefile b/tests/run-make/return-non-c-like-enum/Makefile deleted file mode 100644 index 0c8d8bf3acc60..0000000000000 --- a/tests/run-make/return-non-c-like-enum/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -all: - $(RUSTC) --crate-type=staticlib nonclike.rs - $(CC) test.c $(call STATICLIB,nonclike) $(call OUT_EXE,test) \ - $(EXTRACFLAGS) $(EXTRACXXFLAGS) - $(call RUN,test) diff --git a/tests/run-make/return-non-c-like-enum/rmake.rs b/tests/run-make/return-non-c-like-enum/rmake.rs new file mode 100644 index 0000000000000..ecdfbd8889941 --- /dev/null +++ b/tests/run-make/return-non-c-like-enum/rmake.rs @@ -0,0 +1,18 @@ +// Check that we treat enum variants like union members in call ABIs. +// Added in #68443. +// Original issue: #68190. + +//@ ignore-cross-compile + +use run_make_support::{cc, extra_c_flags, extra_cxx_flags, run, rustc, static_lib_name}; + +fn main() { + rustc().crate_type("staticlib").input("nonclike.rs").run(); + cc().input("test.c") + .arg(&static_lib_name("nonclike")) + .out_exe("test") + .args(extra_c_flags()) + .args(extra_cxx_flags()) + .run(); + run("test"); +} diff --git a/tests/run-make/rust-lld-by-default-beta-stable/main.rs b/tests/run-make/rust-lld-by-default-beta-stable/main.rs new file mode 100644 index 0000000000000..f328e4d9d04c3 --- /dev/null +++ b/tests/run-make/rust-lld-by-default-beta-stable/main.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/tests/run-make/rust-lld-by-default-beta-stable/rmake.rs b/tests/run-make/rust-lld-by-default-beta-stable/rmake.rs new file mode 100644 index 0000000000000..fc3dffdbaf42a --- /dev/null +++ b/tests/run-make/rust-lld-by-default-beta-stable/rmake.rs @@ -0,0 +1,29 @@ +// Ensure that rust-lld is *not* used as the default linker on `x86_64-unknown-linux-gnu` on stable +// or beta. + +//@ ignore-nightly +//@ only-x86_64-unknown-linux-gnu + +use run_make_support::regex::Regex; +use run_make_support::rustc; +use std::process::Output; + +fn main() { + // A regular compilation should not use rust-lld by default. We'll check that by asking the + // linker to display its version number with a link-arg. + let output = rustc() + .env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info") + .link_arg("-Wl,-v") + .input("main.rs") + .run(); + assert!( + !find_lld_version_in_logs(output.stderr_utf8()), + "the LLD version string should not be present in the output logs:\n{}", + output.stderr_utf8() + ); +} + +fn find_lld_version_in_logs(stderr: String) -> bool { + let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap(); + stderr.lines().any(|line| lld_version_re.is_match(line.trim())) +} diff --git a/tests/run-make/rust-lld-by-default/main.rs b/tests/run-make/rust-lld-by-default-nightly/main.rs similarity index 100% rename from tests/run-make/rust-lld-by-default/main.rs rename to tests/run-make/rust-lld-by-default-nightly/main.rs diff --git a/tests/run-make/rust-lld-by-default/rmake.rs b/tests/run-make/rust-lld-by-default-nightly/rmake.rs similarity index 93% rename from tests/run-make/rust-lld-by-default/rmake.rs rename to tests/run-make/rust-lld-by-default-nightly/rmake.rs index 94857a57dfb7c..f3ce9ada15709 100644 --- a/tests/run-make/rust-lld-by-default/rmake.rs +++ b/tests/run-make/rust-lld-by-default-nightly/rmake.rs @@ -1,5 +1,5 @@ -// Ensure that rust-lld is used as the default linker on `x86_64-unknown-linux-gnu`, and that it can -// also be turned off with a CLI flag. +// Ensure that rust-lld is used as the default linker on `x86_64-unknown-linux-gnu` on the nightly +// channel, and that it can also be turned off with a CLI flag. //@ needs-rust-lld //@ ignore-beta diff --git a/tests/run-make/static-pie/rmake.rs b/tests/run-make/static-pie/rmake.rs index 77c5e253bc03a..6a92f92328eec 100644 --- a/tests/run-make/static-pie/rmake.rs +++ b/tests/run-make/static-pie/rmake.rs @@ -51,7 +51,7 @@ fn test(compiler: &str) { rustc() .input("test-aslr.rs") - .target(&target()) + .target(target()) .linker(compiler) .arg("-Clinker-flavor=gcc") .arg("-Ctarget-feature=+crt-static") diff --git a/tests/run-make/issue-68794-textrel-on-minimal-lib/bar.c b/tests/run-make/textrel-on-minimal-lib/bar.c similarity index 100% rename from tests/run-make/issue-68794-textrel-on-minimal-lib/bar.c rename to tests/run-make/textrel-on-minimal-lib/bar.c diff --git a/tests/run-make/issue-68794-textrel-on-minimal-lib/foo.rs b/tests/run-make/textrel-on-minimal-lib/foo.rs similarity index 100% rename from tests/run-make/issue-68794-textrel-on-minimal-lib/foo.rs rename to tests/run-make/textrel-on-minimal-lib/foo.rs diff --git a/tests/run-make/textrel-on-minimal-lib/rmake.rs b/tests/run-make/textrel-on-minimal-lib/rmake.rs new file mode 100644 index 0000000000000..625ded70ad624 --- /dev/null +++ b/tests/run-make/textrel-on-minimal-lib/rmake.rs @@ -0,0 +1,31 @@ +// Verify that no text relocations are accidentally introduced by linking a +// minimal rust staticlib. +// The test links a rust static library into a shared library, and checks that +// the linker doesn't have to flag the resulting file as containing TEXTRELs. +// This bug otherwise breaks Android builds, which forbid TEXTRELs. +// See https://github.com/rust-lang/rust/issues/68794 + +//@ ignore-cross-compile +//@ ignore-windows +// Reason: There is no `bar.dll` produced by CC to run readobj on + +use run_make_support::{ + cc, dynamic_lib_name, extra_c_flags, extra_cxx_flags, llvm_readobj, rustc, static_lib_name, +}; + +fn main() { + rustc().input("foo.rs").run(); + cc().input("bar.c") + .input(static_lib_name("foo")) + .out_exe(&dynamic_lib_name("bar")) + .arg("-fPIC") + .arg("-shared") + .args(extra_c_flags()) + .args(extra_cxx_flags()) + .run(); + llvm_readobj() + .input(dynamic_lib_name("bar")) + .arg("--dynamic") + .run() + .assert_stdout_not_contains("TEXTREL"); +} diff --git a/tests/run-make/unknown-mod-stdin/Makefile b/tests/run-make/unknown-mod-stdin/Makefile deleted file mode 100644 index 313b0ba837e83..0000000000000 --- a/tests/run-make/unknown-mod-stdin/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# ignore-windows - -include ../tools.mk - -all: - echo 'mod unknown;' | $(RUSTC) --crate-type rlib - >$(TMPDIR)/unknown-mod.stdout 2>$(TMPDIR)/unknown-mod.stderr || echo "failed successfully" - $(RUSTC_TEST_OP) "$(TMPDIR)"/unknown-mod.stdout unknown-mod.stdout - $(RUSTC_TEST_OP) "$(TMPDIR)"/unknown-mod.stderr unknown-mod.stderr diff --git a/tests/run-make/unknown-mod-stdin/rmake.rs b/tests/run-make/unknown-mod-stdin/rmake.rs new file mode 100644 index 0000000000000..0fe5c78ed0ff0 --- /dev/null +++ b/tests/run-make/unknown-mod-stdin/rmake.rs @@ -0,0 +1,25 @@ +// Rustc displays a compilation error when it finds a `mod` (module) +// statement referencing a file that does not exist. However, a bug from 2019 +// caused invalid `mod` statements to silently insert empty inline modules +// instead of showing an error if the invalid `mod` statement had been passed +// through standard input. This test checks that this bug does not make a resurgence. +// See https://github.com/rust-lang/rust/issues/65601 + +// NOTE: This is not a UI test, because the bug which this test +// is checking for is specifically tied to passing +// `mod unknown;` through standard input. + +use run_make_support::{diff, rustc}; + +fn main() { + let out = rustc().crate_type("rlib").stdin(b"mod unknown;").arg("-").run_fail(); + diff() + .actual_text("actual-stdout", out.stdout_utf8()) + .expected_file("unknown-mod.stdout") + .run(); + diff() + .actual_text("actual-stderr", out.stderr_utf8()) + .expected_file("unknown-mod.stderr") + .normalize(r#"\\"#, "/") + .run(); +} diff --git a/tests/run-make/used-cdylib-macos/Makefile b/tests/run-make/used-cdylib-macos/Makefile deleted file mode 100644 index bdf914a1ca950..0000000000000 --- a/tests/run-make/used-cdylib-macos/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -include ../tools.mk - -# only-apple -# -# This checks that `#[used]` passes through to the linker on -# Apple targets. This is subject to change in the future, see -# https://github.com/rust-lang/rust/pull/93718 for discussion - -all: - $(RUSTC) -Copt-level=3 dylib_used.rs - nm $(TMPDIR)/libdylib_used.dylib | $(CGREP) VERY_IMPORTANT_SYMBOL diff --git a/tests/run-make/used-cdylib-macos/rmake.rs b/tests/run-make/used-cdylib-macos/rmake.rs new file mode 100644 index 0000000000000..ad95ad640f0c1 --- /dev/null +++ b/tests/run-make/used-cdylib-macos/rmake.rs @@ -0,0 +1,16 @@ +// This checks that `#[used]` passes through to the linker on +// Apple targets. This is subject to change in the future. +// See https://github.com/rust-lang/rust/pull/93718 + +//@ only-apple + +use run_make_support::{dynamic_lib_name, llvm_readobj, rustc}; + +fn main() { + rustc().opt_level("3").input("dylib_used.rs").run(); + llvm_readobj() + .input(dynamic_lib_name("dylib_used")) + .arg("--all") + .run() + .assert_stdout_contains("VERY_IMPORTANT_SYMBOL"); +} diff --git a/tests/run-make/volatile-intrinsics/Makefile b/tests/run-make/volatile-intrinsics/Makefile deleted file mode 100644 index 5672a045873dd..0000000000000 --- a/tests/run-make/volatile-intrinsics/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -all: - # The tests must pass... - $(RUSTC) main.rs - $(call RUN,main) - # ... and the loads/stores must not be optimized out. - $(RUSTC) main.rs --emit=llvm-ir - $(CGREP) "load volatile" "store volatile" < $(TMPDIR)/main.ll diff --git a/tests/run-make/volatile-intrinsics/rmake.rs b/tests/run-make/volatile-intrinsics/rmake.rs new file mode 100644 index 0000000000000..fb9be4bb9ba23 --- /dev/null +++ b/tests/run-make/volatile-intrinsics/rmake.rs @@ -0,0 +1,18 @@ +//@ ignore-cross-compile + +use run_make_support::fs_wrapper::read; +use run_make_support::{assert_contains, run, rustc}; + +fn main() { + // The tests must pass... + rustc().input("main.rs").run(); + run("main"); + + // ... and the loads/stores must not be optimized out. + rustc().input("main.rs").emit("llvm-ir").run(); + + let raw_llvm_ir = read("main.ll"); + let llvm_ir = String::from_utf8_lossy(&raw_llvm_ir); + assert_contains(&llvm_ir, "load volatile"); + assert_contains(&llvm_ir, "store volatile"); +} diff --git a/tests/run-make/wasm-abi/rmake.rs b/tests/run-make/wasm-abi/rmake.rs index 0fc326babd943..ff12bcd536e7f 100644 --- a/tests/run-make/wasm-abi/rmake.rs +++ b/tests/run-make/wasm-abi/rmake.rs @@ -1,9 +1,8 @@ //@ only-wasm32-wasip1 //@ needs-wasmtime -use run_make_support::rustc; +use run_make_support::{cmd, rustc}; use std::path::Path; -use std::process::Command; fn main() { rustc().input("foo.rs").target("wasm32-wasip1").run(); @@ -19,14 +18,12 @@ fn main() { } fn run(file: &Path, method: &str, expected_output: &str) { - let output = Command::new("wasmtime") + cmd("wasmtime") .arg("run") .arg("--preload=host=host.wat") .arg("--invoke") .arg(method) .arg(file) - .output() - .unwrap(); - assert!(output.status.success()); - assert_eq!(expected_output, String::from_utf8_lossy(&output.stdout)); + .run() + .assert_stdout_equals(expected_output); } diff --git a/tests/run-make/wasm-exceptions-nostd/Makefile b/tests/run-make/wasm-exceptions-nostd/Makefile deleted file mode 100644 index 34755ec14b745..0000000000000 --- a/tests/run-make/wasm-exceptions-nostd/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -include ../tools.mk - -# only-wasm32-bare - -# Add a few command line args to make exceptions work -RUSTC := $(RUSTC) -C llvm-args=-wasm-enable-eh -RUSTC := $(RUSTC) -C target-feature=+exception-handling -RUSTC := $(RUSTC) -C panic=unwind - -all: - $(RUSTC) src/lib.rs --target wasm32-unknown-unknown - $(NODE) verify.mjs $(TMPDIR)/lib.wasm diff --git a/tests/run-make/wasm-exceptions-nostd/rmake.rs b/tests/run-make/wasm-exceptions-nostd/rmake.rs new file mode 100644 index 0000000000000..720ee9909d2ab --- /dev/null +++ b/tests/run-make/wasm-exceptions-nostd/rmake.rs @@ -0,0 +1,18 @@ +//@ only-wasm32-bare + +use std::path::Path; + +use run_make_support::{cmd, env_var, rustc}; + +fn main() { + // Add a few command line args to make exceptions work + rustc() + .input(Path::new("src").join("lib.rs")) + .target("wasm32-unknown-unknown") + .panic("unwind") + .arg("-Cllvm-args=-wasm-enable-eh") + .arg("-Ctarget-feature=+exception-handling") + .run(); + + cmd(&env_var("NODE")).arg("verify.mjs").arg("lib.wasm").run(); +} diff --git a/tests/run-make/wasm-exceptions-nostd/src/lib.rs b/tests/run-make/wasm-exceptions-nostd/src/lib.rs index 3ea8797d3a6dd..ef2f117e01af9 100644 --- a/tests/run-make/wasm-exceptions-nostd/src/lib.rs +++ b/tests/run-make/wasm-exceptions-nostd/src/lib.rs @@ -5,7 +5,6 @@ #![feature(core_intrinsics)] #![feature(lang_items)] #![feature(link_llvm_intrinsics)] -#![feature(panic_info_message)] extern crate alloc; diff --git a/tests/run-make/wasm-exceptions-nostd/src/panicking.rs b/tests/run-make/wasm-exceptions-nostd/src/panicking.rs index 52a32f3cd3034..414c9f6a1650b 100644 --- a/tests/run-make/wasm-exceptions-nostd/src/panicking.rs +++ b/tests/run-make/wasm-exceptions-nostd/src/panicking.rs @@ -17,8 +17,8 @@ fn panic_handler(info: &core::panic::PanicInfo<'_>) -> ! { use alloc::boxed::Box; use alloc::string::ToString; - let msg = info.message().map(|msg| msg.to_string()).unwrap_or("(no message)".to_string()); - let exception = Box::new(msg.to_string()); + let msg = info.message().to_string(); + let exception = Box::new(msg); unsafe { let exception_raw = Box::into_raw(exception); wasm_throw(exception_raw as *mut u8); diff --git a/tests/run-make/wasm-override-linker/Makefile b/tests/run-make/wasm-override-linker/Makefile deleted file mode 100644 index 1a01a574dee28..0000000000000 --- a/tests/run-make/wasm-override-linker/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# needs-force-clang-based-tests - -# FIXME(#126180): This test doesn't actually run anywhere, because the only -# CI job that sets RUSTBUILD_FORCE_CLANG_BASED_TESTS runs very few tests. - -include ../tools.mk - -ifeq ($(TARGET),wasm32-unknown-unknown) -all: - $(RUSTC) foo.rs --crate-type cdylib --target $(TARGET) -C linker=$(CLANG) -else ifeq ($(TARGET),wasm64-unknown-unknown) -all: - $(RUSTC) foo.rs --crate-type cdylib --target $(TARGET) -C linker=$(CLANG) -else -all: -endif diff --git a/tests/run-make/wasm-override-linker/rmake.rs b/tests/run-make/wasm-override-linker/rmake.rs new file mode 100644 index 0000000000000..01bc08e990159 --- /dev/null +++ b/tests/run-make/wasm-override-linker/rmake.rs @@ -0,0 +1,17 @@ +// How to run this +// $ RUSTBUILD_FORCE_CLANG_BASED_TESTS=1 ./x.py test tests/run-make/wasm-override-linker/ + +//@ needs-force-clang-based-tests + +use run_make_support::{env_var, rustc, target}; + +fn main() { + if matches!(target().as_str(), "wasm32-unknown-unknown" | "wasm64-unknown-unknown") { + rustc() + .input("foo.rs") + .crate_type("cdylib") + .target(&target()) + .linker(&env_var("CLANG")) + .run(); + } +} diff --git a/tests/run-make/weird-output-filenames/Makefile b/tests/run-make/weird-output-filenames/Makefile deleted file mode 100644 index d3a34e3b46e89..0000000000000 --- a/tests/run-make/weird-output-filenames/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -include ../tools.mk - -all: - cp foo.rs $(TMPDIR)/.foo.rs - $(RUSTC) $(TMPDIR)/.foo.rs 2>&1 \ - | $(CGREP) -e "invalid character.*in crate name:" - cp foo.rs $(TMPDIR)/.foo.bar - $(RUSTC) $(TMPDIR)/.foo.bar 2>&1 \ - | $(CGREP) -e "invalid character.*in crate name:" - cp foo.rs $(TMPDIR)/+foo+bar.rs - $(RUSTC) $(TMPDIR)/+foo+bar.rs 2>&1 \ - | $(CGREP) -e "invalid character.*in crate name:" - cp foo.rs $(TMPDIR)/-foo.rs - $(RUSTC) $(TMPDIR)/-foo.rs 2>&1 \ - | $(CGREP) 'crate names cannot start with a `-`' diff --git a/tests/run-make/weird-output-filenames/rmake.rs b/tests/run-make/weird-output-filenames/rmake.rs new file mode 100644 index 0000000000000..ed331a0b8d4ea --- /dev/null +++ b/tests/run-make/weird-output-filenames/rmake.rs @@ -0,0 +1,19 @@ +use run_make_support::fs_wrapper::copy; +use run_make_support::regex::Regex; +use run_make_support::{cwd, rustc}; + +fn main() { + let invalid_characters = [".foo.rs", ".foo.bar", "+foo+bar.rs"]; + let re = Regex::new(r"invalid character.*in crate name:").unwrap(); + for f in invalid_characters { + copy("foo.rs", f); + let stderr = rustc().input(f).run_fail().stderr_utf8(); + assert!(re.is_match(&stderr)); + } + + copy("foo.rs", "-foo.rs"); + rustc() + .input(cwd().join("-foo.rs")) + .run_fail() + .assert_stderr_contains("crate names cannot start with a `-`"); +} diff --git a/tests/rustdoc-gui/help-page.goml b/tests/rustdoc-gui/help-page.goml new file mode 100644 index 0000000000000..f1a2675128ce4 --- /dev/null +++ b/tests/rustdoc-gui/help-page.goml @@ -0,0 +1,70 @@ +// This test ensures that opening the help page in its own tab works. +go-to: "file://" + |DOC_PATH| + "/help.html" +set-window-size: (1000, 1000) // Try desktop size first. +wait-for: "#help" +assert-css: ("#help", {"display": "block"}) +assert-css: ("#help dd", {"font-size": "16px"}) +click: "#help-button > a" +assert-css: ("#help", {"display": "block"}) +compare-elements-property: (".sub", "#help", ["offsetWidth"]) +compare-elements-position: (".sub", "#help", ["x"]) +set-window-size: (500, 1000) // Try mobile next. +assert-css: ("#help", {"display": "block"}) +compare-elements-property: (".sub", "#help", ["offsetWidth"]) +compare-elements-position: (".sub", "#help", ["x"]) + +// Checking the color of the elements of the help menu. +show-text: true +define-function: ( + "check-colors", + [theme, color, background, box_shadow], + block { + // FIXME: no clue why we can't call the `switch-theme` function here... + set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: + assert-css: ("#help kbd", { + "color": |color|, + "background-color": |background|, + "box-shadow": |box_shadow| + " 0px -1px 0px 0px inset", + }, ALL) + }, +) + +call-function: ("check-colors", { + "theme": "ayu", + "color": "#c5c5c5", + "background": "#314559", + "box_shadow": "#5c6773", +}) +call-function: ("check-colors", { + "theme": "dark", + "color": "#000", + "background": "#fafbfc", + "box_shadow": "#c6cbd1", +}) +call-function: ("check-colors", { + "theme": "light", + "color": "#000", + "background": "#fafbfc", + "box_shadow": "#c6cbd1", +}) + +// This test ensures that opening the help popover without switching pages works. +go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" +set-window-size: (1000, 1000) // Only supported on desktop. +assert-false: "#help" +click: "#help-button > a" +assert-css: ("#help", {"display": "block"}) +assert-css: ("#help dd", {"font-size": "16px"}) +click: "#help-button > a" +assert-css: ("#help", {"display": "none"}) +compare-elements-property-false: (".sub", "#help", ["offsetWidth"]) +compare-elements-position-false: (".sub", "#help", ["x"]) + +// This test ensures that the "the rustdoc book" anchor link within the help popover works. +go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" +set-window-size: (1000, 1000) // Popover only appears when the screen width is >700px. +assert-false: "#help" +click: "#help-button > a" +click: "//*[@id='help']//a[text()='the rustdoc book']" +wait-for-document-property: ({"URL": "https://doc.rust-lang.org/"}, STARTS_WITH) diff --git a/tests/rustdoc-ui/disambiguator-endswith-named-suffix.rs b/tests/rustdoc-ui/disambiguator-endswith-named-suffix.rs new file mode 100644 index 0000000000000..c3da1fdd7cc6d --- /dev/null +++ b/tests/rustdoc-ui/disambiguator-endswith-named-suffix.rs @@ -0,0 +1,111 @@ +//@ check-pass +//@ normalize-stderr-test: "nightly|beta|1\.[0-9][0-9]\.[0-9]" -> "$$CHANNEL" + +//! [struct@m!()] //~ WARN: unmatched disambiguator `struct` and suffix `!()` +//! [struct@m!{}] +//! [struct@m![]] +//! [struct@f()] //~ WARN: unmatched disambiguator `struct` and suffix `()` +//! [struct@m!] //~ WARN: unmatched disambiguator `struct` and suffix `!` +//! +//! [enum@m!()] //~ WARN: unmatched disambiguator `enum` and suffix `!()` +//! [enum@m!{}] +//! [enum@m![]] +//! [enum@f()] //~ WARN: unmatched disambiguator `enum` and suffix `()` +//! [enum@m!] //~ WARN: unmatched disambiguator `enum` and suffix `!` +//! +//! [trait@m!()] //~ WARN: unmatched disambiguator `trait` and suffix `!()` +//! [trait@m!{}] +//! [trait@m![]] +//! [trait@f()] //~ WARN: unmatched disambiguator `trait` and suffix `()` +//! [trait@m!] //~ WARN: unmatched disambiguator `trait` and suffix `!` +//! +//! [module@m!()] //~ WARN: unmatched disambiguator `module` and suffix `!()` +//! [module@m!{}] +//! [module@m![]] +//! [module@f()] //~ WARN: unmatched disambiguator `module` and suffix `()` +//! [module@m!] //~ WARN: unmatched disambiguator `module` and suffix `!` +//! +//! [mod@m!()] //~ WARN: unmatched disambiguator `mod` and suffix `!()` +//! [mod@m!{}] +//! [mod@m![]] +//! [mod@f()] //~ WARN: unmatched disambiguator `mod` and suffix `()` +//! [mod@m!] //~ WARN: unmatched disambiguator `mod` and suffix `!` +//! +//! [const@m!()] //~ WARN: unmatched disambiguator `const` and suffix `!()` +//! [const@m!{}] +//! [const@m![]] +//! [const@f()] //~ WARN: incompatible link kind for `f` +//! [const@m!] //~ WARN: unmatched disambiguator `const` and suffix `!` +//! +//! [constant@m!()] //~ WARN: unmatched disambiguator `constant` and suffix `!()` +//! [constant@m!{}] +//! [constant@m![]] +//! [constant@f()] //~ WARN: incompatible link kind for `f` +//! [constant@m!] //~ WARN: unmatched disambiguator `constant` and suffix `!` +//! +//! [static@m!()] //~ WARN: unmatched disambiguator `static` and suffix `!()` +//! [static@m!{}] +//! [static@m![]] +//! [static@f()] //~ WARN: incompatible link kind for `f` +//! [static@m!] //~ WARN: unmatched disambiguator `static` and suffix `!` +//! +//! [function@m!()] //~ WARN: unmatched disambiguator `function` and suffix `!()` +//! [function@m!{}] +//! [function@m![]] +//! [function@f()] +//! [function@m!] //~ WARN: unmatched disambiguator `function` and suffix `!` +//! +//! [fn@m!()] //~ WARN: unmatched disambiguator `fn` and suffix `!()` +//! [fn@m!{}] +//! [fn@m![]] +//! [fn@f()] +//! [fn@m!] //~ WARN: unmatched disambiguator `fn` and suffix `!` +//! +//! [method@m!()] //~ WARN: unmatched disambiguator `method` and suffix `!()` +//! [method@m!{}] +//! [method@m![]] +//! [method@f()] +//! [method@m!] //~ WARN: unmatched disambiguator `method` and suffix `!` +//! +//! [derive@m!()] //~ WARN: incompatible link kind for `m` +//! [derive@m!{}] //~ WARN: incompatible link kind for `m` +//! [derive@m![]] +//! [derive@f()] //~ WARN: unmatched disambiguator `derive` and suffix `()` +//! [derive@m!] //~ WARN: incompatible link kind for `m` +//! +//! [type@m!()] //~ WARN: unmatched disambiguator `type` and suffix `!()` +//! [type@m!{}] +//! [type@m![]] +//! [type@f()] //~ WARN: unmatched disambiguator `type` and suffix `()` +//! [type@m!] //~ WARN: unmatched disambiguator `type` and suffix `!` +//! +//! [value@m!()] //~ WARN: unmatched disambiguator `value` and suffix `!()` +//! [value@m!{}] +//! [value@m![]] +//! [value@f()] +//! [value@m!] //~ WARN: unmatched disambiguator `value` and suffix `!` +//! +//! [macro@m!()] +//! [macro@m!{}] +//! [macro@m![]] +//! [macro@f()] //~ WARN: unmatched disambiguator `macro` and suffix `()` +//! [macro@m!] +//! +//! [prim@m!()] //~ WARN: unmatched disambiguator `prim` and suffix `!()` +//! [prim@m!{}] +//! [prim@m![]] +//! [prim@f()] //~ WARN: unmatched disambiguator `prim` and suffix `()` +//! [prim@m!] //~ WARN: unmatched disambiguator `prim` and suffix `!` +//! +//! [primitive@m!()] //~ WARN: unmatched disambiguator `primitive` and suffix `!()` +//! [primitive@m!{}] +//! [primitive@m![]] +//! [primitive@f()] //~ WARN: unmatched disambiguator `primitive` and suffix `()` +//! [primitive@m!] //~ WARN: unmatched disambiguator `primitive` and suffix `!` + +#[macro_export] +macro_rules! m { + () => {}; +} + +pub fn f() {} diff --git a/tests/rustdoc-ui/disambiguator-endswith-named-suffix.stderr b/tests/rustdoc-ui/disambiguator-endswith-named-suffix.stderr new file mode 100644 index 0000000000000..f4e40a4887383 --- /dev/null +++ b/tests/rustdoc-ui/disambiguator-endswith-named-suffix.stderr @@ -0,0 +1,395 @@ +warning: unmatched disambiguator `struct` and suffix `!()` + --> $DIR/disambiguator-endswith-named-suffix.rs:4:6 + | +LL | //! [struct@m!()] + | ^^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default + +warning: unmatched disambiguator `struct` and suffix `()` + --> $DIR/disambiguator-endswith-named-suffix.rs:7:6 + | +LL | //! [struct@f()] + | ^^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `struct` and suffix `!` + --> $DIR/disambiguator-endswith-named-suffix.rs:8:6 + | +LL | //! [struct@m!] + | ^^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `enum` and suffix `!()` + --> $DIR/disambiguator-endswith-named-suffix.rs:10:6 + | +LL | //! [enum@m!()] + | ^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `enum` and suffix `()` + --> $DIR/disambiguator-endswith-named-suffix.rs:13:6 + | +LL | //! [enum@f()] + | ^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `enum` and suffix `!` + --> $DIR/disambiguator-endswith-named-suffix.rs:14:6 + | +LL | //! [enum@m!] + | ^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `trait` and suffix `!()` + --> $DIR/disambiguator-endswith-named-suffix.rs:16:6 + | +LL | //! [trait@m!()] + | ^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `trait` and suffix `()` + --> $DIR/disambiguator-endswith-named-suffix.rs:19:6 + | +LL | //! [trait@f()] + | ^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `trait` and suffix `!` + --> $DIR/disambiguator-endswith-named-suffix.rs:20:6 + | +LL | //! [trait@m!] + | ^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `module` and suffix `!()` + --> $DIR/disambiguator-endswith-named-suffix.rs:22:6 + | +LL | //! [module@m!()] + | ^^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `module` and suffix `()` + --> $DIR/disambiguator-endswith-named-suffix.rs:25:6 + | +LL | //! [module@f()] + | ^^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `module` and suffix `!` + --> $DIR/disambiguator-endswith-named-suffix.rs:26:6 + | +LL | //! [module@m!] + | ^^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `mod` and suffix `!()` + --> $DIR/disambiguator-endswith-named-suffix.rs:28:6 + | +LL | //! [mod@m!()] + | ^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `mod` and suffix `()` + --> $DIR/disambiguator-endswith-named-suffix.rs:31:6 + | +LL | //! [mod@f()] + | ^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `mod` and suffix `!` + --> $DIR/disambiguator-endswith-named-suffix.rs:32:6 + | +LL | //! [mod@m!] + | ^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `const` and suffix `!()` + --> $DIR/disambiguator-endswith-named-suffix.rs:34:6 + | +LL | //! [const@m!()] + | ^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: incompatible link kind for `f` + --> $DIR/disambiguator-endswith-named-suffix.rs:37:6 + | +LL | //! [const@f()] + | ^^^^^^^^^ this link resolved to a function, which is not a constant + | +help: to link to the function, add parentheses + | +LL - //! [const@f()] +LL + //! [f()] + | + +warning: unmatched disambiguator `const` and suffix `!` + --> $DIR/disambiguator-endswith-named-suffix.rs:38:6 + | +LL | //! [const@m!] + | ^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `constant` and suffix `!()` + --> $DIR/disambiguator-endswith-named-suffix.rs:40:6 + | +LL | //! [constant@m!()] + | ^^^^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: incompatible link kind for `f` + --> $DIR/disambiguator-endswith-named-suffix.rs:43:6 + | +LL | //! [constant@f()] + | ^^^^^^^^^^^^ this link resolved to a function, which is not a constant + | +help: to link to the function, add parentheses + | +LL - //! [constant@f()] +LL + //! [f()] + | + +warning: unmatched disambiguator `constant` and suffix `!` + --> $DIR/disambiguator-endswith-named-suffix.rs:44:6 + | +LL | //! [constant@m!] + | ^^^^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `static` and suffix `!()` + --> $DIR/disambiguator-endswith-named-suffix.rs:46:6 + | +LL | //! [static@m!()] + | ^^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: incompatible link kind for `f` + --> $DIR/disambiguator-endswith-named-suffix.rs:49:6 + | +LL | //! [static@f()] + | ^^^^^^^^^^ this link resolved to a function, which is not a static + | +help: to link to the function, add parentheses + | +LL - //! [static@f()] +LL + //! [f()] + | + +warning: unmatched disambiguator `static` and suffix `!` + --> $DIR/disambiguator-endswith-named-suffix.rs:50:6 + | +LL | //! [static@m!] + | ^^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `function` and suffix `!()` + --> $DIR/disambiguator-endswith-named-suffix.rs:52:6 + | +LL | //! [function@m!()] + | ^^^^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `function` and suffix `!` + --> $DIR/disambiguator-endswith-named-suffix.rs:56:6 + | +LL | //! [function@m!] + | ^^^^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `fn` and suffix `!()` + --> $DIR/disambiguator-endswith-named-suffix.rs:58:6 + | +LL | //! [fn@m!()] + | ^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `fn` and suffix `!` + --> $DIR/disambiguator-endswith-named-suffix.rs:62:6 + | +LL | //! [fn@m!] + | ^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `method` and suffix `!()` + --> $DIR/disambiguator-endswith-named-suffix.rs:64:6 + | +LL | //! [method@m!()] + | ^^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `method` and suffix `!` + --> $DIR/disambiguator-endswith-named-suffix.rs:68:6 + | +LL | //! [method@m!] + | ^^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: incompatible link kind for `m` + --> $DIR/disambiguator-endswith-named-suffix.rs:70:6 + | +LL | //! [derive@m!()] + | ^^^^^^^^^^^ this link resolved to a macro, which is not a derive macro + | +help: to link to the macro, add an exclamation mark + | +LL - //! [derive@m!()] +LL + //! [m!!()] + | + +warning: incompatible link kind for `m` + --> $DIR/disambiguator-endswith-named-suffix.rs:71:6 + | +LL | //! [derive@m!{}] + | ^^^^^^^^^^^ this link resolved to a macro, which is not a derive macro + | +help: to link to the macro, add an exclamation mark + | +LL - //! [derive@m!{}] +LL + //! [m!!{}] + | + +warning: unmatched disambiguator `derive` and suffix `()` + --> $DIR/disambiguator-endswith-named-suffix.rs:73:6 + | +LL | //! [derive@f()] + | ^^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: incompatible link kind for `m` + --> $DIR/disambiguator-endswith-named-suffix.rs:74:6 + | +LL | //! [derive@m!] + | ^^^^^^^^^ this link resolved to a macro, which is not a derive macro + | +help: to link to the macro, add an exclamation mark + | +LL - //! [derive@m!] +LL + //! [m!!] + | + +warning: unmatched disambiguator `type` and suffix `!()` + --> $DIR/disambiguator-endswith-named-suffix.rs:76:6 + | +LL | //! [type@m!()] + | ^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `type` and suffix `()` + --> $DIR/disambiguator-endswith-named-suffix.rs:79:6 + | +LL | //! [type@f()] + | ^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `type` and suffix `!` + --> $DIR/disambiguator-endswith-named-suffix.rs:80:6 + | +LL | //! [type@m!] + | ^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `value` and suffix `!()` + --> $DIR/disambiguator-endswith-named-suffix.rs:82:6 + | +LL | //! [value@m!()] + | ^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `value` and suffix `!` + --> $DIR/disambiguator-endswith-named-suffix.rs:86:6 + | +LL | //! [value@m!] + | ^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `macro` and suffix `()` + --> $DIR/disambiguator-endswith-named-suffix.rs:91:6 + | +LL | //! [macro@f()] + | ^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `prim` and suffix `!()` + --> $DIR/disambiguator-endswith-named-suffix.rs:94:6 + | +LL | //! [prim@m!()] + | ^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `prim` and suffix `()` + --> $DIR/disambiguator-endswith-named-suffix.rs:97:6 + | +LL | //! [prim@f()] + | ^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `prim` and suffix `!` + --> $DIR/disambiguator-endswith-named-suffix.rs:98:6 + | +LL | //! [prim@m!] + | ^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `primitive` and suffix `!()` + --> $DIR/disambiguator-endswith-named-suffix.rs:100:6 + | +LL | //! [primitive@m!()] + | ^^^^^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `primitive` and suffix `()` + --> $DIR/disambiguator-endswith-named-suffix.rs:103:6 + | +LL | //! [primitive@f()] + | ^^^^^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: unmatched disambiguator `primitive` and suffix `!` + --> $DIR/disambiguator-endswith-named-suffix.rs:104:6 + | +LL | //! [primitive@m!] + | ^^^^^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + +warning: 46 warnings emitted + diff --git a/tests/rustdoc-ui/disambiguator-macro-endswith-exclamatory.rs b/tests/rustdoc-ui/disambiguator-macro-endswith-exclamatory.rs new file mode 100644 index 0000000000000..b955090e8944c --- /dev/null +++ b/tests/rustdoc-ui/disambiguator-macro-endswith-exclamatory.rs @@ -0,0 +1,11 @@ +//@ check-pass + +//! [macro@m!] //~ WARN: unresolved link to `m` + +//issue#126986 + +macro_rules! m { + () => {}; +} + +fn main() {} diff --git a/tests/rustdoc-ui/disambiguator-macro-endswith-exclamatory.stderr b/tests/rustdoc-ui/disambiguator-macro-endswith-exclamatory.stderr new file mode 100644 index 0000000000000..2ada7f1a4be5d --- /dev/null +++ b/tests/rustdoc-ui/disambiguator-macro-endswith-exclamatory.stderr @@ -0,0 +1,11 @@ +warning: unresolved link to `m` + --> $DIR/disambiguator-macro-endswith-exclamatory.rs:3:6 + | +LL | //! [macro@m!] + | ^^^^^^^^ no item named `m` in scope + | + = note: `macro_rules` named `m` exists in this crate, but it is not in scope at this link's location + = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default + +warning: 1 warning emitted + diff --git a/tests/rustdoc-ui/doctest/non_local_defs.rs b/tests/rustdoc-ui/doctest/non_local_defs.rs index aa166c343b2b0..d8cfe5637ae02 100644 --- a/tests/rustdoc-ui/doctest/non_local_defs.rs +++ b/tests/rustdoc-ui/doctest/non_local_defs.rs @@ -4,6 +4,8 @@ //@ normalize-stderr-test: "tests/rustdoc-ui/doctest" -> "$$DIR" //@ normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" +#![doc(test(attr(warn(non_local_definitions))))] + //! ``` //! #[macro_export] //! macro_rules! a_macro { () => {} } diff --git a/tests/rustdoc-ui/doctest/non_local_defs.stderr b/tests/rustdoc-ui/doctest/non_local_defs.stderr index 2b47e6b5bc4d5..13cd2558793f8 100644 --- a/tests/rustdoc-ui/doctest/non_local_defs.stderr +++ b/tests/rustdoc-ui/doctest/non_local_defs.stderr @@ -1,5 +1,5 @@ warning: non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module - --> $DIR/non_local_defs.rs:9:1 + --> $DIR/non_local_defs.rs:11:1 | LL | macro_rules! a_macro { () => {} } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,11 @@ LL | macro_rules! a_macro { () => {} } = help: remove the `#[macro_export]` or make this doc-test a standalone test with its own `fn main() { ... }` = note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue - = note: `#[warn(non_local_definitions)]` on by default +note: the lint level is defined here + --> $DIR/non_local_defs.rs:8:9 + | +LL | #![warn(non_local_definitions)] + | ^^^^^^^^^^^^^^^^^^^^^ warning: 1 warning emitted diff --git a/tests/rustdoc-ui/doctest/non_local_defs.stdout b/tests/rustdoc-ui/doctest/non_local_defs.stdout index bee195fcdd772..61b4074886e4b 100644 --- a/tests/rustdoc-ui/doctest/non_local_defs.stdout +++ b/tests/rustdoc-ui/doctest/non_local_defs.stdout @@ -1,6 +1,6 @@ running 1 test -test $DIR/non_local_defs.rs - (line 7) ... ok +test $DIR/non_local_defs.rs - (line 9) ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME diff --git a/tests/rustdoc/inline_cross/auxiliary/const-effect-param.rs b/tests/rustdoc/inline_cross/auxiliary/const-effect-param.rs index b0c21ffaeb997..161d0c9d54e11 100644 --- a/tests/rustdoc/inline_cross/auxiliary/const-effect-param.rs +++ b/tests/rustdoc/inline_cross/auxiliary/const-effect-param.rs @@ -1,4 +1,6 @@ +//@ compile-flags: -Znext-solver #![feature(effects, const_trait_impl)] +#![allow(incomplete_features)] #[const_trait] pub trait Resource {} diff --git a/tests/rustdoc/rfc-2632-const-trait-impl.rs b/tests/rustdoc/rfc-2632-const-trait-impl.rs index f6a5555dbadd0..eb3e00af3b0b5 100644 --- a/tests/rustdoc/rfc-2632-const-trait-impl.rs +++ b/tests/rustdoc/rfc-2632-const-trait-impl.rs @@ -8,7 +8,8 @@ // // FIXME(effects) add `const_trait` to `Fn` so we use `~const` // FIXME(effects) restore `const_trait` to `Destruct` -#![feature(const_trait_impl)] +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] #![crate_name = "foo"] use std::marker::Destruct; diff --git a/tests/ui/argument-suggestions/suggest-better-removing-issue-126246.rs b/tests/ui/argument-suggestions/suggest-better-removing-issue-126246.rs new file mode 100644 index 0000000000000..fa1802283c39c --- /dev/null +++ b/tests/ui/argument-suggestions/suggest-better-removing-issue-126246.rs @@ -0,0 +1,21 @@ +fn add_one(x: i32) -> i32 { + x + 1 +} + +fn add_two(x: i32, y: i32) -> i32 { + x + y +} + +fn main() { + add_one(2, 2); //~ ERROR this function takes 1 argument but 2 arguments were supplied + add_one(no_such_local, 10); //~ ERROR cannot find value `no_such_local` in this scope + //~| ERROR this function takes 1 argument but 2 arguments were supplied + add_one(10, no_such_local); //~ ERROR cannot find value `no_such_local` in this scope + //~| ERROR this function takes 1 argument but 2 arguments were supplied + add_two(10, no_such_local, 10); //~ ERROR cannot find value `no_such_local` in this scope + //~| ERROR this function takes 2 arguments but 3 arguments were supplied + add_two(no_such_local, 10, 10); //~ ERROR cannot find value `no_such_local` in this scope + //~| ERROR this function takes 2 arguments but 3 arguments were supplied + add_two(10, 10, no_such_local); //~ ERROR cannot find value `no_such_local` in this scope + //~| ERROR this function takes 2 arguments but 3 arguments were supplied +} diff --git a/tests/ui/argument-suggestions/suggest-better-removing-issue-126246.stderr b/tests/ui/argument-suggestions/suggest-better-removing-issue-126246.stderr new file mode 100644 index 0000000000000..7c4daa3ffe95b --- /dev/null +++ b/tests/ui/argument-suggestions/suggest-better-removing-issue-126246.stderr @@ -0,0 +1,124 @@ +error[E0425]: cannot find value `no_such_local` in this scope + --> $DIR/suggest-better-removing-issue-126246.rs:11:13 + | +LL | add_one(no_such_local, 10); + | ^^^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find value `no_such_local` in this scope + --> $DIR/suggest-better-removing-issue-126246.rs:13:17 + | +LL | add_one(10, no_such_local); + | ^^^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find value `no_such_local` in this scope + --> $DIR/suggest-better-removing-issue-126246.rs:15:17 + | +LL | add_two(10, no_such_local, 10); + | ^^^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find value `no_such_local` in this scope + --> $DIR/suggest-better-removing-issue-126246.rs:17:13 + | +LL | add_two(no_such_local, 10, 10); + | ^^^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find value `no_such_local` in this scope + --> $DIR/suggest-better-removing-issue-126246.rs:19:21 + | +LL | add_two(10, 10, no_such_local); + | ^^^^^^^^^^^^^ not found in this scope + +error[E0061]: this function takes 1 argument but 2 arguments were supplied + --> $DIR/suggest-better-removing-issue-126246.rs:10:5 + | +LL | add_one(2, 2); + | ^^^^^^^ --- + | | | + | | unexpected argument of type `{integer}` + | help: remove the extra argument + | +note: function defined here + --> $DIR/suggest-better-removing-issue-126246.rs:1:4 + | +LL | fn add_one(x: i32) -> i32 { + | ^^^^^^^ ------ + +error[E0061]: this function takes 1 argument but 2 arguments were supplied + --> $DIR/suggest-better-removing-issue-126246.rs:11:5 + | +LL | add_one(no_such_local, 10); + | ^^^^^^^ --------------- + | | + | unexpected argument + | help: remove the extra argument + | +note: function defined here + --> $DIR/suggest-better-removing-issue-126246.rs:1:4 + | +LL | fn add_one(x: i32) -> i32 { + | ^^^^^^^ ------ + +error[E0061]: this function takes 1 argument but 2 arguments were supplied + --> $DIR/suggest-better-removing-issue-126246.rs:13:5 + | +LL | add_one(10, no_such_local); + | ^^^^^^^ --------------- + | | | + | | unexpected argument + | help: remove the extra argument + | +note: function defined here + --> $DIR/suggest-better-removing-issue-126246.rs:1:4 + | +LL | fn add_one(x: i32) -> i32 { + | ^^^^^^^ ------ + +error[E0061]: this function takes 2 arguments but 3 arguments were supplied + --> $DIR/suggest-better-removing-issue-126246.rs:15:5 + | +LL | add_two(10, no_such_local, 10); + | ^^^^^^^ --------------- + | | | + | | unexpected argument + | help: remove the extra argument + | +note: function defined here + --> $DIR/suggest-better-removing-issue-126246.rs:5:4 + | +LL | fn add_two(x: i32, y: i32) -> i32 { + | ^^^^^^^ ------ ------ + +error[E0061]: this function takes 2 arguments but 3 arguments were supplied + --> $DIR/suggest-better-removing-issue-126246.rs:17:5 + | +LL | add_two(no_such_local, 10, 10); + | ^^^^^^^ --------------- + | | + | unexpected argument + | help: remove the extra argument + | +note: function defined here + --> $DIR/suggest-better-removing-issue-126246.rs:5:4 + | +LL | fn add_two(x: i32, y: i32) -> i32 { + | ^^^^^^^ ------ ------ + +error[E0061]: this function takes 2 arguments but 3 arguments were supplied + --> $DIR/suggest-better-removing-issue-126246.rs:19:5 + | +LL | add_two(10, 10, no_such_local); + | ^^^^^^^ --------------- + | | | + | | unexpected argument + | help: remove the extra argument + | +note: function defined here + --> $DIR/suggest-better-removing-issue-126246.rs:5:4 + | +LL | fn add_two(x: i32, y: i32) -> i32 { + | ^^^^^^^ ------ ------ + +error: aborting due to 11 previous errors + +Some errors have detailed explanations: E0061, E0425. +For more information about an error, try `rustc --explain E0061`. diff --git a/tests/ui/asm/x86_64/type-check-2.rs b/tests/ui/asm/x86_64/type-check-2.rs index c866f9fd8cc4d..4b5d59fdbc785 100644 --- a/tests/ui/asm/x86_64/type-check-2.rs +++ b/tests/ui/asm/x86_64/type-check-2.rs @@ -13,13 +13,16 @@ fn main() { let x: u64; asm!("{}", in(reg) x); + //~^ ERROR isn't initialized let mut y: u64; asm!("{}", inout(reg) y); + //~^ ERROR isn't initialized let _ = y; // Outputs require mutable places let v: Vec = vec![0, 1, 2]; + //~^ ERROR is not declared as mutable asm!("{}", in(reg) v[0]); asm!("{}", out(reg) v[0]); asm!("{}", inout(reg) v[0]); diff --git a/tests/ui/asm/x86_64/type-check-2.stderr b/tests/ui/asm/x86_64/type-check-2.stderr index 4f3d5100af056..6ae118b16e766 100644 --- a/tests/ui/asm/x86_64/type-check-2.stderr +++ b/tests/ui/asm/x86_64/type-check-2.stderr @@ -1,5 +1,5 @@ error: invalid `sym` operand - --> $DIR/type-check-2.rs:35:24 + --> $DIR/type-check-2.rs:38:24 | LL | asm!("{}", sym x); | ^ is a local variable @@ -7,7 +7,7 @@ LL | asm!("{}", sym x); = help: `sym` operands must refer to either a function or a static error: invalid `sym` operand - --> $DIR/type-check-2.rs:86:19 + --> $DIR/type-check-2.rs:89:19 | LL | global_asm!("{}", sym C); | ^^^^^ is an `i32` @@ -15,7 +15,7 @@ LL | global_asm!("{}", sym C); = help: `sym` operands must refer to either a function or a static error: invalid `sym` operand - --> $DIR/type-check-2.rs:33:20 + --> $DIR/type-check-2.rs:36:20 | LL | asm!("{}", sym C); | ^^^^^ is an `i32` @@ -23,15 +23,15 @@ LL | asm!("{}", sym C); = help: `sym` operands must refer to either a function or a static error: arguments for inline assembly must be copyable - --> $DIR/type-check-2.rs:40:32 + --> $DIR/type-check-2.rs:43:32 | LL | asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `SimdNonCopy` does not implement the Copy trait -error: cannot use value of type `{closure@$DIR/type-check-2.rs:52:28: 52:36}` for inline assembly - --> $DIR/type-check-2.rs:52:28 +error: cannot use value of type `{closure@$DIR/type-check-2.rs:55:28: 55:36}` for inline assembly + --> $DIR/type-check-2.rs:55:28 | LL | asm!("{}", in(reg) |x: i32| x); | ^^^^^^^^^^ @@ -39,7 +39,7 @@ LL | asm!("{}", in(reg) |x: i32| x); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `Vec` for inline assembly - --> $DIR/type-check-2.rs:54:28 + --> $DIR/type-check-2.rs:57:28 | LL | asm!("{}", in(reg) vec![0]); | ^^^^^^^ @@ -48,7 +48,7 @@ LL | asm!("{}", in(reg) vec![0]); = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) error: cannot use value of type `(i32, i32, i32)` for inline assembly - --> $DIR/type-check-2.rs:56:28 + --> $DIR/type-check-2.rs:59:28 | LL | asm!("{}", in(reg) (1, 2, 3)); | ^^^^^^^^^ @@ -56,7 +56,7 @@ LL | asm!("{}", in(reg) (1, 2, 3)); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `[i32; 3]` for inline assembly - --> $DIR/type-check-2.rs:58:28 + --> $DIR/type-check-2.rs:61:28 | LL | asm!("{}", in(reg) [1, 2, 3]); | ^^^^^^^^^ @@ -64,7 +64,7 @@ LL | asm!("{}", in(reg) [1, 2, 3]); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `fn() {main}` for inline assembly - --> $DIR/type-check-2.rs:66:31 + --> $DIR/type-check-2.rs:69:31 | LL | asm!("{}", inout(reg) f); | ^ @@ -72,12 +72,56 @@ LL | asm!("{}", inout(reg) f); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `&mut i32` for inline assembly - --> $DIR/type-check-2.rs:69:31 + --> $DIR/type-check-2.rs:72:31 | LL | asm!("{}", inout(reg) r); | ^ | = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly -error: aborting due to 10 previous errors +error[E0381]: used binding `x` isn't initialized + --> $DIR/type-check-2.rs:15:28 + | +LL | let x: u64; + | - binding declared here but left uninitialized +LL | asm!("{}", in(reg) x); + | ^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: u64 = 42; + | ++++ + +error[E0381]: used binding `y` isn't initialized + --> $DIR/type-check-2.rs:18:9 + | +LL | let mut y: u64; + | ----- binding declared here but left uninitialized +LL | asm!("{}", inout(reg) y); + | ^^^^^^^^^^^^^^^^^^^^^^^^ `y` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let mut y: u64 = 42; + | ++++ + +error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable + --> $DIR/type-check-2.rs:24:13 + | +LL | let v: Vec = vec![0, 1, 2]; + | ^ not mutable +... +LL | asm!("{}", out(reg) v[0]); + | - cannot borrow as mutable +LL | asm!("{}", inout(reg) v[0]); + | - cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut v: Vec = vec![0, 1, 2]; + | +++ + +error: aborting due to 13 previous errors +Some errors have detailed explanations: E0381, E0596. +For more information about an error, try `rustc --explain E0381`. diff --git a/tests/ui/associated-types/associated-types-eq-expr-path.rs b/tests/ui/associated-types/associated-types-eq-expr-path.rs index 4561e596c6658..67831f913039a 100644 --- a/tests/ui/associated-types/associated-types-eq-expr-path.rs +++ b/tests/ui/associated-types/associated-types-eq-expr-path.rs @@ -13,4 +13,5 @@ impl Foo for isize { pub fn main() { let x: isize = Foo::::bar(); //~^ ERROR associated item constraints are not allowed here + //~| ERROR cannot call } diff --git a/tests/ui/associated-types/associated-types-eq-expr-path.stderr b/tests/ui/associated-types/associated-types-eq-expr-path.stderr index 3d0e3e61eca90..4f28b3cb2de33 100644 --- a/tests/ui/associated-types/associated-types-eq-expr-path.stderr +++ b/tests/ui/associated-types/associated-types-eq-expr-path.stderr @@ -4,6 +4,22 @@ error[E0229]: associated item constraints are not allowed here LL | let x: isize = Foo::::bar(); | ^^^^^^^^^ associated item constraint not allowed here -error: aborting due to 1 previous error +error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type + --> $DIR/associated-types-eq-expr-path.rs:14:20 + | +LL | fn bar() -> isize; + | ------------------ `Foo::bar` defined here +... +LL | let x: isize = Foo::::bar(); + | ^^^^^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait + | +help: use the fully-qualified path to the only available implementation + | +LL - let x: isize = Foo::::bar(); +LL + let x: isize = >::bar(); + | + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0229`. +Some errors have detailed explanations: E0229, E0790. +For more information about an error, try `rustc --explain E0229`. diff --git a/tests/ui/attributes/dump_def_parents.rs b/tests/ui/attributes/dump_def_parents.rs new file mode 100644 index 0000000000000..af1c210d2cd18 --- /dev/null +++ b/tests/ui/attributes/dump_def_parents.rs @@ -0,0 +1,34 @@ +//@ normalize-stderr-test "DefId\(.+?\)" -> "DefId(..)" +#![feature(rustc_attrs)] + +fn bar() { + fn foo() { + fn baz() { + #[rustc_dump_def_parents] + || { + //~^ ERROR: rustc_dump_def_parents: DefId + qux::< + { + //~^ ERROR: rustc_dump_def_parents: DefId + fn inhibits_dump() { + qux::< + { + "hi"; + 1 + }, + >(); + } + + qux::<{ 1 + 1 }>(); + //~^ ERROR: rustc_dump_def_parents: DefId + 1 + }, + >(); + }; + } + } +} + +const fn qux() {} + +fn main() {} diff --git a/tests/ui/attributes/dump_def_parents.stderr b/tests/ui/attributes/dump_def_parents.stderr new file mode 100644 index 0000000000000..b2cc32d09b07e --- /dev/null +++ b/tests/ui/attributes/dump_def_parents.stderr @@ -0,0 +1,128 @@ +error: rustc_dump_def_parents: DefId(..) + --> $DIR/dump_def_parents.rs:8:13 + | +LL | || { + | ^^ + | +note: DefId(..) + --> $DIR/dump_def_parents.rs:6:9 + | +LL | fn baz() { + | ^^^^^^^^ +note: DefId(..) + --> $DIR/dump_def_parents.rs:5:5 + | +LL | fn foo() { + | ^^^^^^^^ +note: DefId(..) + --> $DIR/dump_def_parents.rs:4:1 + | +LL | fn bar() { + | ^^^^^^^^ +note: DefId(..) + --> $DIR/dump_def_parents.rs:2:1 + | +LL | / #![feature(rustc_attrs)] +LL | | +LL | | fn bar() { +LL | | fn foo() { +... | +LL | | +LL | | fn main() {} + | |____________^ + +error: rustc_dump_def_parents: DefId(..) + --> $DIR/dump_def_parents.rs:11:21 + | +LL | / { +LL | | +LL | | fn inhibits_dump() { +LL | | qux::< +... | +LL | | 1 +LL | | }, + | |_____________________^ + | +note: DefId(..) + --> $DIR/dump_def_parents.rs:8:13 + | +LL | || { + | ^^ +note: DefId(..) + --> $DIR/dump_def_parents.rs:6:9 + | +LL | fn baz() { + | ^^^^^^^^ +note: DefId(..) + --> $DIR/dump_def_parents.rs:5:5 + | +LL | fn foo() { + | ^^^^^^^^ +note: DefId(..) + --> $DIR/dump_def_parents.rs:4:1 + | +LL | fn bar() { + | ^^^^^^^^ +note: DefId(..) + --> $DIR/dump_def_parents.rs:2:1 + | +LL | / #![feature(rustc_attrs)] +LL | | +LL | | fn bar() { +LL | | fn foo() { +... | +LL | | +LL | | fn main() {} + | |____________^ + +error: rustc_dump_def_parents: DefId(..) + --> $DIR/dump_def_parents.rs:22:31 + | +LL | qux::<{ 1 + 1 }>(); + | ^^^^^^^^^ + | +note: DefId(..) + --> $DIR/dump_def_parents.rs:11:21 + | +LL | / { +LL | | +LL | | fn inhibits_dump() { +LL | | qux::< +... | +LL | | 1 +LL | | }, + | |_____________________^ +note: DefId(..) + --> $DIR/dump_def_parents.rs:8:13 + | +LL | || { + | ^^ +note: DefId(..) + --> $DIR/dump_def_parents.rs:6:9 + | +LL | fn baz() { + | ^^^^^^^^ +note: DefId(..) + --> $DIR/dump_def_parents.rs:5:5 + | +LL | fn foo() { + | ^^^^^^^^ +note: DefId(..) + --> $DIR/dump_def_parents.rs:4:1 + | +LL | fn bar() { + | ^^^^^^^^ +note: DefId(..) + --> $DIR/dump_def_parents.rs:2:1 + | +LL | / #![feature(rustc_attrs)] +LL | | +LL | | fn bar() { +LL | | fn foo() { +... | +LL | | +LL | | fn main() {} + | |____________^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/attributes/used-issue-126789.rs b/tests/ui/attributes/used-issue-126789.rs new file mode 100644 index 0000000000000..90a1aa8d5cc3d --- /dev/null +++ b/tests/ui/attributes/used-issue-126789.rs @@ -0,0 +1,6 @@ +extern "C" { + #[used] //~ ERROR attribute must be applied to a `static` variable + static FOO: i32; +} + +fn main() {} diff --git a/tests/ui/attributes/used-issue-126789.stderr b/tests/ui/attributes/used-issue-126789.stderr new file mode 100644 index 0000000000000..6014f7af95c55 --- /dev/null +++ b/tests/ui/attributes/used-issue-126789.stderr @@ -0,0 +1,10 @@ +error: attribute must be applied to a `static` variable + --> $DIR/used-issue-126789.rs:2:5 + | +LL | #[used] + | ^^^^^^^ +LL | static FOO: i32; + | ---------------- but this is a foreign static item + +error: aborting due to 1 previous error + diff --git a/tests/ui/borrowck/borrowck-move-from-unsafe-ptr.stderr b/tests/ui/borrowck/borrowck-move-from-unsafe-ptr.stderr index ebc3b6ebcacda..79f18624c618b 100644 --- a/tests/ui/borrowck/borrowck-move-from-unsafe-ptr.stderr +++ b/tests/ui/borrowck/borrowck-move-from-unsafe-ptr.stderr @@ -4,16 +4,10 @@ error[E0507]: cannot move out of `*x` which is behind a raw pointer LL | let y = *x; | ^^ move occurs because `*x` has type `Box`, which does not implement the `Copy` trait | -help: consider removing the dereference here - | -LL - let y = *x; -LL + let y = x; - | help: consider cloning the value if the performance cost is acceptable | -LL - let y = *x; -LL + let y = x.clone(); - | +LL | let y = (*x).clone(); + | + +++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/issue-20801.stderr b/tests/ui/borrowck/issue-20801.stderr index 20a4bd4e42378..c1d06ac3e2196 100644 --- a/tests/ui/borrowck/issue-20801.stderr +++ b/tests/ui/borrowck/issue-20801.stderr @@ -67,11 +67,6 @@ LL | struct T(u8); ... LL | let c = unsafe { *mut_ptr() }; | ---------- you could clone this value -help: consider removing the dereference here - | -LL - let c = unsafe { *mut_ptr() }; -LL + let c = unsafe { mut_ptr() }; - | error[E0507]: cannot move out of a raw pointer --> $DIR/issue-20801.rs:36:22 @@ -87,11 +82,6 @@ LL | struct T(u8); ... LL | let d = unsafe { *const_ptr() }; | ------------ you could clone this value -help: consider removing the dereference here - | -LL - let d = unsafe { *const_ptr() }; -LL + let d = unsafe { const_ptr() }; - | error: aborting due to 4 previous errors; 1 warning emitted diff --git a/tests/ui/borrowck/move-from-union-field-issue-66500.stderr b/tests/ui/borrowck/move-from-union-field-issue-66500.stderr index c951ce8e3cd8f..7f4593eefcaf6 100644 --- a/tests/ui/borrowck/move-from-union-field-issue-66500.stderr +++ b/tests/ui/borrowck/move-from-union-field-issue-66500.stderr @@ -30,9 +30,8 @@ LL | *u.c | help: consider cloning the value if the performance cost is acceptable | -LL - *u.c -LL + u.c.clone() - | +LL | (*u.c).clone() + | + +++++++++ error[E0507]: cannot move out of `*u.d` which is behind a raw pointer --> $DIR/move-from-union-field-issue-66500.rs:24:5 @@ -42,9 +41,8 @@ LL | *u.d | help: consider cloning the value if the performance cost is acceptable | -LL - *u.d -LL + u.d.clone() - | +LL | (*u.d).clone() + | + +++++++++ error: aborting due to 4 previous errors diff --git a/tests/ui/const-generics/assoc_const_as_type_argument.rs b/tests/ui/const-generics/assoc_const_as_type_argument.rs index ffc7f116a94ef..bec6102417c5f 100644 --- a/tests/ui/const-generics/assoc_const_as_type_argument.rs +++ b/tests/ui/const-generics/assoc_const_as_type_argument.rs @@ -8,6 +8,7 @@ fn foo() { bar::<::ASSOC>(); //~^ ERROR: expected associated type, found associated constant `Trait::ASSOC` //~| ERROR: unresolved item provided when a constant was expected + //~| ERROR type annotations needed } fn main() {} diff --git a/tests/ui/const-generics/assoc_const_as_type_argument.stderr b/tests/ui/const-generics/assoc_const_as_type_argument.stderr index ac00954613506..53edc19b28ca2 100644 --- a/tests/ui/const-generics/assoc_const_as_type_argument.stderr +++ b/tests/ui/const-generics/assoc_const_as_type_argument.stderr @@ -15,7 +15,19 @@ help: if this generic argument was intended as a const parameter, surround it wi LL | bar::<{ ::ASSOC }>(); | + + -error: aborting due to 2 previous errors +error[E0284]: type annotations needed + --> $DIR/assoc_const_as_type_argument.rs:8:5 + | +LL | bar::<::ASSOC>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer the value of the const parameter `N` declared on the function `bar` + | +note: required by a const generic parameter in `bar` + --> $DIR/assoc_const_as_type_argument.rs:5:8 + | +LL | fn bar() {} + | ^^^^^^^^^^^^^^ required by this const generic parameter in `bar` + +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0575, E0747. -For more information about an error, try `rustc --explain E0575`. +Some errors have detailed explanations: E0284, E0575, E0747. +For more information about an error, try `rustc --explain E0284`. diff --git a/tests/ui/const-generics/const-arg-in-const-arg.min.stderr b/tests/ui/const-generics/const-arg-in-const-arg.min.stderr index ce7fce2599360..2ea9d6b35b451 100644 --- a/tests/ui/const-generics/const-arg-in-const-arg.min.stderr +++ b/tests/ui/const-generics/const-arg-in-const-arg.min.stderr @@ -17,7 +17,7 @@ LL | let _: [u8; bar::()]; = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:18:23 + --> $DIR/const-arg-in-const-arg.rs:19:23 | LL | let _: [u8; faz::<'a>(&())]; | ^^ cannot perform const operation using `'a` @@ -26,7 +26,7 @@ LL | let _: [u8; faz::<'a>(&())]; = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:20:23 + --> $DIR/const-arg-in-const-arg.rs:21:23 | LL | let _: [u8; baz::<'a>(&())]; | ^^ cannot perform const operation using `'a` @@ -35,7 +35,7 @@ LL | let _: [u8; baz::<'a>(&())]; = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:21:23 + --> $DIR/const-arg-in-const-arg.rs:22:23 | LL | let _: [u8; faz::<'b>(&())]; | ^^ cannot perform const operation using `'b` @@ -44,7 +44,7 @@ LL | let _: [u8; faz::<'b>(&())]; = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:23:23 + --> $DIR/const-arg-in-const-arg.rs:24:23 | LL | let _: [u8; baz::<'b>(&())]; | ^^ cannot perform const operation using `'b` @@ -53,7 +53,7 @@ LL | let _: [u8; baz::<'b>(&())]; = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:26:23 + --> $DIR/const-arg-in-const-arg.rs:27:23 | LL | let _ = [0; bar::()]; | ^ cannot perform const operation using `N` @@ -62,7 +62,7 @@ LL | let _ = [0; bar::()]; = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:28:23 + --> $DIR/const-arg-in-const-arg.rs:30:23 | LL | let _ = [0; faz::<'a>(&())]; | ^^ cannot perform const operation using `'a` @@ -71,7 +71,7 @@ LL | let _ = [0; faz::<'a>(&())]; = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:30:23 + --> $DIR/const-arg-in-const-arg.rs:32:23 | LL | let _ = [0; baz::<'a>(&())]; | ^^ cannot perform const operation using `'a` @@ -80,7 +80,7 @@ LL | let _ = [0; baz::<'a>(&())]; = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:31:23 + --> $DIR/const-arg-in-const-arg.rs:33:23 | LL | let _ = [0; faz::<'b>(&())]; | ^^ cannot perform const operation using `'b` @@ -89,7 +89,7 @@ LL | let _ = [0; faz::<'b>(&())]; = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:33:23 + --> $DIR/const-arg-in-const-arg.rs:35:23 | LL | let _ = [0; baz::<'b>(&())]; | ^^ cannot perform const operation using `'b` @@ -98,7 +98,7 @@ LL | let _ = [0; baz::<'b>(&())]; = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:34:24 + --> $DIR/const-arg-in-const-arg.rs:36:24 | LL | let _: Foo<{ foo::() }>; | ^ cannot perform const operation using `T` @@ -107,7 +107,7 @@ LL | let _: Foo<{ foo::() }>; = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:35:24 + --> $DIR/const-arg-in-const-arg.rs:37:24 | LL | let _: Foo<{ bar::() }>; | ^ cannot perform const operation using `N` @@ -116,7 +116,7 @@ LL | let _: Foo<{ bar::() }>; = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:37:24 + --> $DIR/const-arg-in-const-arg.rs:40:24 | LL | let _: Foo<{ faz::<'a>(&()) }>; | ^^ cannot perform const operation using `'a` @@ -125,7 +125,7 @@ LL | let _: Foo<{ faz::<'a>(&()) }>; = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:39:24 + --> $DIR/const-arg-in-const-arg.rs:42:24 | LL | let _: Foo<{ baz::<'a>(&()) }>; | ^^ cannot perform const operation using `'a` @@ -134,7 +134,7 @@ LL | let _: Foo<{ baz::<'a>(&()) }>; = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:40:24 + --> $DIR/const-arg-in-const-arg.rs:43:24 | LL | let _: Foo<{ faz::<'b>(&()) }>; | ^^ cannot perform const operation using `'b` @@ -143,7 +143,7 @@ LL | let _: Foo<{ faz::<'b>(&()) }>; = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:42:24 + --> $DIR/const-arg-in-const-arg.rs:45:24 | LL | let _: Foo<{ baz::<'b>(&()) }>; | ^^ cannot perform const operation using `'b` @@ -152,7 +152,7 @@ LL | let _: Foo<{ baz::<'b>(&()) }>; = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:43:27 + --> $DIR/const-arg-in-const-arg.rs:46:27 | LL | let _ = Foo::<{ foo::() }>; | ^ cannot perform const operation using `T` @@ -161,7 +161,7 @@ LL | let _ = Foo::<{ foo::() }>; = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:44:27 + --> $DIR/const-arg-in-const-arg.rs:47:27 | LL | let _ = Foo::<{ bar::() }>; | ^ cannot perform const operation using `N` @@ -170,7 +170,7 @@ LL | let _ = Foo::<{ bar::() }>; = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:46:27 + --> $DIR/const-arg-in-const-arg.rs:50:27 | LL | let _ = Foo::<{ faz::<'a>(&()) }>; | ^^ cannot perform const operation using `'a` @@ -179,7 +179,7 @@ LL | let _ = Foo::<{ faz::<'a>(&()) }>; = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:48:27 + --> $DIR/const-arg-in-const-arg.rs:52:27 | LL | let _ = Foo::<{ baz::<'a>(&()) }>; | ^^ cannot perform const operation using `'a` @@ -188,7 +188,7 @@ LL | let _ = Foo::<{ baz::<'a>(&()) }>; = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:49:27 + --> $DIR/const-arg-in-const-arg.rs:53:27 | LL | let _ = Foo::<{ faz::<'b>(&()) }>; | ^^ cannot perform const operation using `'b` @@ -197,7 +197,7 @@ LL | let _ = Foo::<{ faz::<'b>(&()) }>; = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:51:27 + --> $DIR/const-arg-in-const-arg.rs:55:27 | LL | let _ = Foo::<{ baz::<'b>(&()) }>; | ^^ cannot perform const operation using `'b` @@ -216,8 +216,20 @@ help: if this generic argument was intended as a const parameter, surround it wi LL | let _: [u8; bar::<{ N }>()]; | + + +error[E0284]: type annotations needed + --> $DIR/const-arg-in-const-arg.rs:16:17 + | +LL | let _: [u8; bar::()]; + | ^^^^^^^^ cannot infer the value of the const parameter `N` declared on the function `bar` + | +note: required by a const generic parameter in `bar` + --> $DIR/const-arg-in-const-arg.rs:9:14 + | +LL | const fn bar() -> usize { N } + | ^^^^^^^^^^^^^^ required by this const generic parameter in `bar` + error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present - --> $DIR/const-arg-in-const-arg.rs:18:23 + --> $DIR/const-arg-in-const-arg.rs:19:23 | LL | let _: [u8; faz::<'a>(&())]; | ^^ @@ -229,7 +241,7 @@ LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } | ^^ error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present - --> $DIR/const-arg-in-const-arg.rs:21:23 + --> $DIR/const-arg-in-const-arg.rs:22:23 | LL | let _: [u8; faz::<'b>(&())]; | ^^ @@ -241,7 +253,7 @@ LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } | ^^ error[E0747]: unresolved item provided when a constant was expected - --> $DIR/const-arg-in-const-arg.rs:35:24 + --> $DIR/const-arg-in-const-arg.rs:37:24 | LL | let _: Foo<{ bar::() }>; | ^ @@ -251,8 +263,20 @@ help: if this generic argument was intended as a const parameter, surround it wi LL | let _: Foo<{ bar::<{ N }>() }>; | + + +error[E0284]: type annotations needed + --> $DIR/const-arg-in-const-arg.rs:37:18 + | +LL | let _: Foo<{ bar::() }>; + | ^^^^^^^^ cannot infer the value of the const parameter `N` declared on the function `bar` + | +note: required by a const generic parameter in `bar` + --> $DIR/const-arg-in-const-arg.rs:9:14 + | +LL | const fn bar() -> usize { N } + | ^^^^^^^^^^^^^^ required by this const generic parameter in `bar` + error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present - --> $DIR/const-arg-in-const-arg.rs:37:24 + --> $DIR/const-arg-in-const-arg.rs:40:24 | LL | let _: Foo<{ faz::<'a>(&()) }>; | ^^ @@ -264,7 +288,7 @@ LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } | ^^ error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present - --> $DIR/const-arg-in-const-arg.rs:40:24 + --> $DIR/const-arg-in-const-arg.rs:43:24 | LL | let _: Foo<{ faz::<'b>(&()) }>; | ^^ @@ -276,7 +300,7 @@ LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } | ^^ error: constant expression depends on a generic parameter - --> $DIR/const-arg-in-const-arg.rs:25:17 + --> $DIR/const-arg-in-const-arg.rs:26:17 | LL | let _ = [0; foo::()]; | ^^^^^^^^^^ @@ -284,7 +308,7 @@ LL | let _ = [0; foo::()]; = note: this may fail depending on what value the parameter takes error[E0747]: unresolved item provided when a constant was expected - --> $DIR/const-arg-in-const-arg.rs:26:23 + --> $DIR/const-arg-in-const-arg.rs:27:23 | LL | let _ = [0; bar::()]; | ^ @@ -294,8 +318,20 @@ help: if this generic argument was intended as a const parameter, surround it wi LL | let _ = [0; bar::<{ N }>()]; | + + +error[E0284]: type annotations needed + --> $DIR/const-arg-in-const-arg.rs:27:17 + | +LL | let _ = [0; bar::()]; + | ^^^^^^^^ cannot infer the value of the const parameter `N` declared on the function `bar` + | +note: required by a const generic parameter in `bar` + --> $DIR/const-arg-in-const-arg.rs:9:14 + | +LL | const fn bar() -> usize { N } + | ^^^^^^^^^^^^^^ required by this const generic parameter in `bar` + error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present - --> $DIR/const-arg-in-const-arg.rs:28:23 + --> $DIR/const-arg-in-const-arg.rs:30:23 | LL | let _ = [0; faz::<'a>(&())]; | ^^ @@ -307,7 +343,7 @@ LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } | ^^ error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present - --> $DIR/const-arg-in-const-arg.rs:31:23 + --> $DIR/const-arg-in-const-arg.rs:33:23 | LL | let _ = [0; faz::<'b>(&())]; | ^^ @@ -319,7 +355,7 @@ LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } | ^^ error[E0747]: unresolved item provided when a constant was expected - --> $DIR/const-arg-in-const-arg.rs:44:27 + --> $DIR/const-arg-in-const-arg.rs:47:27 | LL | let _ = Foo::<{ bar::() }>; | ^ @@ -329,8 +365,20 @@ help: if this generic argument was intended as a const parameter, surround it wi LL | let _ = Foo::<{ bar::<{ N }>() }>; | + + +error[E0284]: type annotations needed + --> $DIR/const-arg-in-const-arg.rs:47:21 + | +LL | let _ = Foo::<{ bar::() }>; + | ^^^^^^^^ cannot infer the value of the const parameter `N` declared on the function `bar` + | +note: required by a const generic parameter in `bar` + --> $DIR/const-arg-in-const-arg.rs:9:14 + | +LL | const fn bar() -> usize { N } + | ^^^^^^^^^^^^^^ required by this const generic parameter in `bar` + error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present - --> $DIR/const-arg-in-const-arg.rs:46:27 + --> $DIR/const-arg-in-const-arg.rs:50:27 | LL | let _ = Foo::<{ faz::<'a>(&()) }>; | ^^ @@ -342,7 +390,7 @@ LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } | ^^ error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present - --> $DIR/const-arg-in-const-arg.rs:49:27 + --> $DIR/const-arg-in-const-arg.rs:53:27 | LL | let _ = Foo::<{ faz::<'b>(&()) }>; | ^^ @@ -353,7 +401,7 @@ note: the late bound lifetime parameter is introduced here LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } | ^^ -error: aborting due to 36 previous errors +error: aborting due to 40 previous errors -Some errors have detailed explanations: E0747, E0794. -For more information about an error, try `rustc --explain E0747`. +Some errors have detailed explanations: E0284, E0747, E0794. +For more information about an error, try `rustc --explain E0284`. diff --git a/tests/ui/const-generics/const-arg-in-const-arg.rs b/tests/ui/const-generics/const-arg-in-const-arg.rs index 27b74489fe8e0..b95c63309f782 100644 --- a/tests/ui/const-generics/const-arg-in-const-arg.rs +++ b/tests/ui/const-generics/const-arg-in-const-arg.rs @@ -15,6 +15,7 @@ fn test<'a, 'b, T, const N: usize>() where &'b (): Sized { let _: [u8; foo::()]; //[min]~ ERROR generic parameters may not let _: [u8; bar::()]; //[min]~ ERROR generic parameters may not //[min]~^ ERROR unresolved item provided when a constant was expected + //[min]~| ERROR type annotations needed let _: [u8; faz::<'a>(&())]; //[min]~ ERROR generic parameters may not //[min]~^ ERROR cannot specify lifetime arguments let _: [u8; baz::<'a>(&())]; //[min]~ ERROR generic parameters may not @@ -25,6 +26,7 @@ fn test<'a, 'b, T, const N: usize>() where &'b (): Sized { let _ = [0; foo::()]; //[min]~ ERROR constant expression depends on a generic parameter let _ = [0; bar::()]; //[min]~ ERROR generic parameters may not //[min]~^ ERROR unresolved item provided when a constant was expected + //[min]~| ERROR type annotations needed let _ = [0; faz::<'a>(&())]; //[min]~ ERROR generic parameters may not //[min]~^ ERROR cannot specify lifetime arguments let _ = [0; baz::<'a>(&())]; //[min]~ ERROR generic parameters may not @@ -34,6 +36,7 @@ fn test<'a, 'b, T, const N: usize>() where &'b (): Sized { let _: Foo<{ foo::() }>; //[min]~ ERROR generic parameters may not let _: Foo<{ bar::() }>; //[min]~ ERROR generic parameters may not //[min]~^ ERROR unresolved item provided when a constant was expected + //[min]~| ERROR type annotations needed let _: Foo<{ faz::<'a>(&()) }>; //[min]~ ERROR generic parameters may not //[min]~^ ERROR cannot specify lifetime arguments let _: Foo<{ baz::<'a>(&()) }>; //[min]~ ERROR generic parameters may not @@ -43,6 +46,7 @@ fn test<'a, 'b, T, const N: usize>() where &'b (): Sized { let _ = Foo::<{ foo::() }>; //[min]~ ERROR generic parameters may not let _ = Foo::<{ bar::() }>; //[min]~ ERROR generic parameters may not //[min]~^ ERROR unresolved item provided when a constant was expected + //[min]~| ERROR type annotations needed let _ = Foo::<{ faz::<'a>(&()) }>; //[min]~ ERROR generic parameters may not //[min]~^ ERROR cannot specify lifetime arguments let _ = Foo::<{ baz::<'a>(&()) }>; //[min]~ ERROR generic parameters may not diff --git a/tests/ui/const-generics/const_trait_fn-issue-88433.rs b/tests/ui/const-generics/const_trait_fn-issue-88433.rs index cd008aa2c9f2d..5e0ea6fc168ef 100644 --- a/tests/ui/const-generics/const_trait_fn-issue-88433.rs +++ b/tests/ui/const-generics/const_trait_fn-issue-88433.rs @@ -1,6 +1,8 @@ //@ build-pass +//@ compile-flags: -Znext-solver -#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] #[const_trait] trait Func { diff --git a/tests/ui/const-generics/const_trait_fn-issue-88433.stderr b/tests/ui/const-generics/const_trait_fn-issue-88433.stderr deleted file mode 100644 index 4e0d6370fbd50..0000000000000 --- a/tests/ui/const-generics/const_trait_fn-issue-88433.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/const_trait_fn-issue-88433.rs:3:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/const-generics/generic_const_exprs/opaque_type.rs b/tests/ui/const-generics/generic_const_exprs/opaque_type.rs index 56b8acbf88cde..7209290a36e0a 100644 --- a/tests/ui/const-generics/generic_const_exprs/opaque_type.rs +++ b/tests/ui/const-generics/generic_const_exprs/opaque_type.rs @@ -2,6 +2,7 @@ #![allow(incomplete_features)] type Foo = impl Sized; +//~^ ERROR: unconstrained opaque type fn with_bound() -> Foo where diff --git a/tests/ui/const-generics/generic_const_exprs/opaque_type.stderr b/tests/ui/const-generics/generic_const_exprs/opaque_type.stderr index e9fb8c0f403ae..c7a266205b4b5 100644 --- a/tests/ui/const-generics/generic_const_exprs/opaque_type.stderr +++ b/tests/ui/const-generics/generic_const_exprs/opaque_type.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/opaque_type.rs:10:17 + --> $DIR/opaque_type.rs:11:17 | LL | type Foo = impl Sized; | ---------- the found opaque type @@ -11,12 +11,20 @@ LL | let _: [u8; (N / 2) as Foo] = [0; (N / 2) as usize]; found opaque type `Foo` error[E0605]: non-primitive cast: `usize` as `Foo` - --> $DIR/opaque_type.rs:10:17 + --> $DIR/opaque_type.rs:11:17 | LL | let _: [u8; (N / 2) as Foo] = [0; (N / 2) as usize]; | ^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object -error: aborting due to 2 previous errors +error: unconstrained opaque type + --> $DIR/opaque_type.rs:4:12 + | +LL | type Foo = impl Sized; + | ^^^^^^^^^^ + | + = note: `Foo` must be used in combination with a concrete type within the same module + +error: aborting due to 3 previous errors Some errors have detailed explanations: E0308, E0605. For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs b/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs index 2f903ea419efa..818b5d6ca93ae 100644 --- a/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs +++ b/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs @@ -1,6 +1,6 @@ //@ known-bug: #110395 - -#![feature(generic_const_exprs, adt_const_params, const_trait_impl)] +//@ compile-flags: -Znext-solver +#![feature(generic_const_exprs, adt_const_params, const_trait_impl, effects)] #![allow(incomplete_features)] // test `N + N` unifies with explicit function calls for non-builtin-types diff --git a/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr b/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr index 335130c958f0e..db93bcca60fb3 100644 --- a/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr +++ b/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr @@ -1,3 +1,12 @@ +error: const `impl` for trait `Add` which is not marked with `#[const_trait]` + --> $DIR/unify-op-with-fn-call.rs:10:12 + | +LL | impl const std::ops::Add for Foo { + | ^^^^^^^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + error[E0741]: `Foo` must implement `ConstParamTy` to be used as the type of a const generic parameter --> $DIR/unify-op-with-fn-call.rs:18:29 | @@ -10,6 +19,12 @@ LL + #[derive(ConstParamTy)] LL | struct Foo(u8); | +error[E0284]: type annotations needed: cannot normalize `foo::{constant#0}` + --> $DIR/unify-op-with-fn-call.rs:20:25 + | +LL | fn foo(a: Evaluatable<{ N + N }>) { + | ^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `foo::{constant#0}` + error[E0741]: `Foo` must implement `ConstParamTy` to be used as the type of a const generic parameter --> $DIR/unify-op-with-fn-call.rs:20:17 | @@ -34,59 +49,25 @@ LL + #[derive(ConstParamTy)] LL | struct Foo(u8); | -error: unconstrained generic constant - --> $DIR/unify-op-with-fn-call.rs:30:12 - | -LL | bar2::<{ std::ops::Add::add(N, N) }>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: try adding a `where` bound - | -LL | fn foo2(a: Evaluatable2<{ N + N }>) where [(); { std::ops::Add::add(N, N) }]: { - | +++++++++++++++++++++++++++++++++++++++++ - -error[E0015]: cannot call non-const operator in constants - --> $DIR/unify-op-with-fn-call.rs:20:39 - | -LL | fn foo(a: Evaluatable<{ N + N }>) { - | ^^^^^ - | -note: impl defined here, but it is not `const` - --> $DIR/unify-op-with-fn-call.rs:10:1 - | -LL | impl const std::ops::Add for Foo { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] +error[E0284]: type annotations needed: cannot normalize `foo2::{constant#0}` + --> $DIR/unify-op-with-fn-call.rs:29:28 | +LL | fn foo2(a: Evaluatable2<{ N + N }>) { + | ^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `foo2::{constant#0}` -error[E0015]: cannot call non-const fn `::add` in constants - --> $DIR/unify-op-with-fn-call.rs:21:13 +error[E0284]: type annotations needed: cannot normalize `foo::{constant#0}` + --> $DIR/unify-op-with-fn-call.rs:21:11 | LL | bar::<{ std::ops::Add::add(N, N) }>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `foo::{constant#0}` -error[E0015]: cannot call non-const fn `::add` in constants - --> $DIR/unify-op-with-fn-call.rs:30:14 +error[E0284]: type annotations needed: cannot normalize `foo2::{constant#0}` + --> $DIR/unify-op-with-fn-call.rs:30:12 | LL | bar2::<{ std::ops::Add::add(N, N) }>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `foo2::{constant#0}` -error: aborting due to 7 previous errors +error: aborting due to 8 previous errors -Some errors have detailed explanations: E0015, E0741. -For more information about an error, try `rustc --explain E0015`. +Some errors have detailed explanations: E0284, E0741. +For more information about an error, try `rustc --explain E0284`. diff --git a/tests/ui/const-generics/issues/issue-62878.min.stderr b/tests/ui/const-generics/issues/issue-62878.min.stderr index 5205726d73845..3fd50bbe29803 100644 --- a/tests/ui/const-generics/issues/issue-62878.min.stderr +++ b/tests/ui/const-generics/issues/issue-62878.min.stderr @@ -30,7 +30,31 @@ help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable LL + #![feature(generic_arg_infer)] | -error: aborting due to 3 previous errors +error[E0284]: type annotations needed + --> $DIR/issue-62878.rs:10:5 + | +LL | foo::<_, { [1] }>(); + | ^^^^^^^^^^^^^^^^^ cannot infer the value of the const parameter `N` declared on the function `foo` + | +note: required by a const generic parameter in `foo` + --> $DIR/issue-62878.rs:5:8 + | +LL | fn foo() {} + | ^^^^^^^^^^^^^^ required by this const generic parameter in `foo` + +error[E0284]: type annotations needed + --> $DIR/issue-62878.rs:10:5 + | +LL | foo::<_, { [1] }>(); + | ^^^^^^^^^^^^^^^^^ cannot infer the value of the const parameter `A` declared on the function `foo` + | +note: required by a const generic parameter in `foo` + --> $DIR/issue-62878.rs:5:24 + | +LL | fn foo() {} + | ^^^^^^^^^^^^^^^^ required by this const generic parameter in `foo` + +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0747, E0770. -For more information about an error, try `rustc --explain E0747`. +Some errors have detailed explanations: E0284, E0747, E0770. +For more information about an error, try `rustc --explain E0284`. diff --git a/tests/ui/const-generics/issues/issue-62878.rs b/tests/ui/const-generics/issues/issue-62878.rs index 0b5269df85ee1..c784e95edd824 100644 --- a/tests/ui/const-generics/issues/issue-62878.rs +++ b/tests/ui/const-generics/issues/issue-62878.rs @@ -9,4 +9,6 @@ fn foo() {} fn main() { foo::<_, { [1] }>(); //[min]~^ ERROR: type provided when a constant was expected + //[min]~| ERROR type annotations needed + //[min]~| ERROR type annotations needed } diff --git a/tests/ui/const-generics/issues/issue-88119.rs b/tests/ui/const-generics/issues/issue-88119.rs index bcbb26f0d8e68..12cb7ee7f55cc 100644 --- a/tests/ui/const-generics/issues/issue-88119.rs +++ b/tests/ui/const-generics/issues/issue-88119.rs @@ -1,7 +1,7 @@ -//@ check-pass - +//@ known-bug: #110395 +//@ compile-flags: -Znext-solver #![allow(incomplete_features)] -#![feature(const_trait_impl, generic_const_exprs)] +#![feature(const_trait_impl, effects, generic_const_exprs)] #[const_trait] trait ConstName { diff --git a/tests/ui/const-generics/issues/issue-88119.stderr b/tests/ui/const-generics/issues/issue-88119.stderr new file mode 100644 index 0000000000000..c17a7d5d9fad0 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-88119.stderr @@ -0,0 +1,27 @@ +error[E0284]: type annotations needed: cannot satisfy `the constant `name_len::()` can be evaluated` + --> $DIR/issue-88119.rs:21:5 + | +LL | [(); name_len::()]:, + | ^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `name_len::()` can be evaluated` + | +note: required by a bound in `<&T as ConstName>` + --> $DIR/issue-88119.rs:21:10 + | +LL | [(); name_len::()]:, + | ^^^^^^^^^^^^^^^ required by this bound in `<&T as ConstName>` + +error[E0284]: type annotations needed: cannot satisfy `the constant `name_len::()` can be evaluated` + --> $DIR/issue-88119.rs:28:5 + | +LL | [(); name_len::()]:, + | ^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `name_len::()` can be evaluated` + | +note: required by a bound in `<&mut T as ConstName>` + --> $DIR/issue-88119.rs:28:10 + | +LL | [(); name_len::()]:, + | ^^^^^^^^^^^^^^^ required by this bound in `<&mut T as ConstName>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.rs b/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.rs index e12e07a28e763..497c020bde43e 100644 --- a/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.rs +++ b/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.rs @@ -12,6 +12,7 @@ fn b() { //~^ ERROR expected trait, found constant `BAR` //~| ERROR expected trait, found constant `BAR` //~| ERROR type provided when a constant was expected + //~| ERROR type annotations needed } fn c() { foo::<3 + 3>(); //~ ERROR expressions must be enclosed in braces diff --git a/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.stderr b/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.stderr index d9bcc523b1fc4..c2ba517f60960 100644 --- a/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.stderr +++ b/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.stderr @@ -10,7 +10,7 @@ LL | foo::<{ BAR + 3 }>(); | + + error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/const-expression-suggest-missing-braces.rs:17:11 + --> $DIR/const-expression-suggest-missing-braces.rs:18:11 | LL | foo::<3 + 3>(); | ^^^^^ @@ -21,7 +21,7 @@ LL | foo::<{ 3 + 3 }>(); | + + error: expected one of `,` or `>`, found `-` - --> $DIR/const-expression-suggest-missing-braces.rs:20:15 + --> $DIR/const-expression-suggest-missing-braces.rs:21:15 | LL | foo::(); | ^ expected one of `,` or `>` @@ -32,7 +32,7 @@ LL | foo::<{ BAR - 3 }>(); | + + error: expected one of `,` or `>`, found `-` - --> $DIR/const-expression-suggest-missing-braces.rs:23:15 + --> $DIR/const-expression-suggest-missing-braces.rs:24:15 | LL | foo::(); | ^ expected one of `,` or `>` @@ -43,7 +43,7 @@ LL | foo::<{ BAR - BAR }>(); | + + error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/const-expression-suggest-missing-braces.rs:26:11 + --> $DIR/const-expression-suggest-missing-braces.rs:27:11 | LL | foo::<100 - BAR>(); | ^^^^^^^^^ @@ -54,7 +54,7 @@ LL | foo::<{ 100 - BAR }>(); | + + error: expected one of `,` or `>`, found `(` - --> $DIR/const-expression-suggest-missing-braces.rs:29:19 + --> $DIR/const-expression-suggest-missing-braces.rs:30:19 | LL | foo::()>(); | ^ expected one of `,` or `>` @@ -65,7 +65,7 @@ LL | foo::<{ bar() }>(); | + + error: expected one of `,` or `>`, found `(` - --> $DIR/const-expression-suggest-missing-braces.rs:32:21 + --> $DIR/const-expression-suggest-missing-braces.rs:33:21 | LL | foo::()>(); | ^ expected one of `,` or `>` @@ -76,7 +76,7 @@ LL | foo::<{ bar::() }>(); | + + error: expected one of `,` or `>`, found `(` - --> $DIR/const-expression-suggest-missing-braces.rs:35:21 + --> $DIR/const-expression-suggest-missing-braces.rs:36:21 | LL | foo::() + BAR>(); | ^ expected one of `,` or `>` @@ -87,7 +87,7 @@ LL | foo::<{ bar::() + BAR }>(); | + + error: expected one of `,` or `>`, found `(` - --> $DIR/const-expression-suggest-missing-braces.rs:38:21 + --> $DIR/const-expression-suggest-missing-braces.rs:39:21 | LL | foo::() - BAR>(); | ^ expected one of `,` or `>` @@ -98,7 +98,7 @@ LL | foo::<{ bar::() - BAR }>(); | + + error: expected one of `,` or `>`, found `-` - --> $DIR/const-expression-suggest-missing-braces.rs:41:15 + --> $DIR/const-expression-suggest-missing-braces.rs:42:15 | LL | foo::()>(); | ^ expected one of `,` or `>` @@ -109,7 +109,7 @@ LL | foo::<{ BAR - bar::() }>(); | + + error: expected one of `,` or `>`, found `-` - --> $DIR/const-expression-suggest-missing-braces.rs:44:15 + --> $DIR/const-expression-suggest-missing-braces.rs:45:15 | LL | foo::()>(); | ^ expected one of `,` or `>` @@ -137,7 +137,19 @@ error[E0747]: type provided when a constant was expected LL | foo::(); | ^^^^^^^^^ -error: aborting due to 14 previous errors +error[E0284]: type annotations needed + --> $DIR/const-expression-suggest-missing-braces.rs:11:5 + | +LL | foo::(); + | ^^^^^^^^^^^^^^^^ cannot infer the value of the const parameter `C` declared on the function `foo` + | +note: required by a const generic parameter in `foo` + --> $DIR/const-expression-suggest-missing-braces.rs:1:8 + | +LL | fn foo() {} + | ^^^^^^^^^^^^^^ required by this const generic parameter in `foo` + +error: aborting due to 15 previous errors -Some errors have detailed explanations: E0404, E0747. -For more information about an error, try `rustc --explain E0404`. +Some errors have detailed explanations: E0284, E0404, E0747. +For more information about an error, try `rustc --explain E0284`. diff --git a/tests/ui/const-generics/min_const_generics/macro-fail.rs b/tests/ui/const-generics/min_const_generics/macro-fail.rs index 2f101ecfb1f7a..25726490c2cca 100644 --- a/tests/ui/const-generics/min_const_generics/macro-fail.rs +++ b/tests/ui/const-generics/min_const_generics/macro-fail.rs @@ -16,6 +16,7 @@ fn make_marker() -> impl Marker { //~| ERROR: type provided when a constant was expected Example:: //~^ ERROR: type provided when a constant was expected + //~| ERROR type annotations needed } fn from_marker(_: impl Marker<{ @@ -35,9 +36,11 @@ fn main() { }>; let _fail = Example::; - //~^ ERROR: type provided when a constant was expected + //~^ ERROR: type provided when a constant + //~| ERROR type annotations needed let _fail = Example::; //~^ ERROR unexpected end of macro invocation //~| ERROR: type provided when a constant was expected + //~| ERROR type annotations needed } diff --git a/tests/ui/const-generics/min_const_generics/macro-fail.stderr b/tests/ui/const-generics/min_const_generics/macro-fail.stderr index 34764982bb046..4e183fe5b1c55 100644 --- a/tests/ui/const-generics/min_const_generics/macro-fail.stderr +++ b/tests/ui/const-generics/min_const_generics/macro-fail.stderr @@ -1,5 +1,5 @@ error: expected type, found `{` - --> $DIR/macro-fail.rs:30:27 + --> $DIR/macro-fail.rs:31:27 | LL | fn make_marker() -> impl Marker { | ---------------------- @@ -13,7 +13,7 @@ LL | ($rusty: ident) => {{ let $rusty = 3; *&$rusty }} = note: this error originates in the macro `gimme_a_const` (in Nightly builds, run with -Z macro-backtrace for more info) error: expected type, found `{` - --> $DIR/macro-fail.rs:30:27 + --> $DIR/macro-fail.rs:31:27 | LL | Example:: | ---------------------- @@ -41,7 +41,7 @@ LL | let _fail = Example::; = note: this error originates in the macro `external_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: unexpected end of macro invocation - --> $DIR/macro-fail.rs:40:25 + --> $DIR/macro-fail.rs:42:25 | LL | macro_rules! gimme_a_const { | -------------------------- when calling this macro @@ -50,7 +50,7 @@ LL | let _fail = Example::; | ^^^^^^^^^^^^^^^^ missing tokens in macro arguments | note: while trying to match meta-variable `$rusty:ident` - --> $DIR/macro-fail.rs:30:8 + --> $DIR/macro-fail.rs:31:8 | LL | ($rusty: ident) => {{ let $rusty = 3; *&$rusty }} | ^^^^^^^^^^^^^ @@ -75,18 +75,63 @@ error[E0747]: type provided when a constant was expected LL | Example:: | ^^^^^^^^^^^^^^^^^^^^^^ +error[E0284]: type annotations needed + --> $DIR/macro-fail.rs:17:3 + | +LL | Example:: + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer the value of the const parameter `N` declared on the struct `Example` + | +note: required by a const generic parameter in `Example` + --> $DIR/macro-fail.rs:1:16 + | +LL | struct Example; + | ^^^^^^^^^^^^^^ required by this const generic parameter in `Example` + error[E0747]: type provided when a constant was expected - --> $DIR/macro-fail.rs:37:25 + --> $DIR/macro-fail.rs:38:25 | LL | let _fail = Example::; | ^^^^^^^^^^^^^^^^^ error[E0747]: type provided when a constant was expected - --> $DIR/macro-fail.rs:40:25 + --> $DIR/macro-fail.rs:42:25 | LL | let _fail = Example::; | ^^^^^^^^^^^^^^^^ -error: aborting due to 9 previous errors +error[E0284]: type annotations needed for `Example<_>` + --> $DIR/macro-fail.rs:38:7 + | +LL | let _fail = Example::; + | ^^^^^ ---------------------------- type must be known at this point + | +note: required by a const generic parameter in `Example` + --> $DIR/macro-fail.rs:1:16 + | +LL | struct Example; + | ^^^^^^^^^^^^^^ required by this const generic parameter in `Example` +help: consider giving `_fail` an explicit type, where the value of const parameter `N` is specified + | +LL | let _fail: Example = Example::; + | ++++++++++++ + +error[E0284]: type annotations needed for `Example<_>` + --> $DIR/macro-fail.rs:42:7 + | +LL | let _fail = Example::; + | ^^^^^ --------------------------- type must be known at this point + | +note: required by a const generic parameter in `Example` + --> $DIR/macro-fail.rs:1:16 + | +LL | struct Example; + | ^^^^^^^^^^^^^^ required by this const generic parameter in `Example` +help: consider giving `_fail` an explicit type, where the value of const parameter `N` is specified + | +LL | let _fail: Example = Example::; + | ++++++++++++ + +error: aborting due to 12 previous errors -For more information about this error, try `rustc --explain E0747`. +Some errors have detailed explanations: E0284, E0747. +For more information about an error, try `rustc --explain E0284`. diff --git a/tests/ui/const-generics/polymorphic-drop-shim.rs b/tests/ui/const-generics/polymorphic-drop-shim.rs new file mode 100644 index 0000000000000..4ca2e86cff915 --- /dev/null +++ b/tests/ui/const-generics/polymorphic-drop-shim.rs @@ -0,0 +1,18 @@ +//@ compile-flags: -Zinline-mir=yes --crate-type=lib +//@ build-pass + +use std::mem::ManuallyDrop; + +pub struct Foo([T; N]); + +pub struct Dorp {} + +impl Drop for Dorp { + fn drop(&mut self) {} +} + +#[inline] +// SAFETY: call this with a valid allocation idk +pub unsafe fn drop(x: *mut Foo) { + std::ptr::drop_in_place(x); +} diff --git a/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.rs b/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.rs index 899db191ae7d7..e7ae2ea1d5a6a 100644 --- a/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.rs +++ b/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.rs @@ -1,14 +1,18 @@ -// Given an anon const `a`: `{ N }` and some anon const `b` which references the -// first anon const: `{ [1; a] }`. `b` should not have any generics as it is not -// a simple `N` argument nor is it a repeat expr count. +// Given a const argument `a`: `{ N }` and some const argument `b` which references the +// first anon const like so: `{ [1; a] }`. The `b` anon const should not be allowed to use +// any generic parameters as: +// - The anon const is not a simple bare parameter, e.g. `N` +// - The anon const is not the *length* of an array repeat expression, e.g. the `N` in `[1; N]`. // -// On the other hand `b` *is* a repeat expr count and so it should inherit its -// parents generics as part of the `const_evaluatable_unchecked` fcw (#76200). +// On the other hand `a` *is* a const argument for the length of a repeat expression and +// so it *should* inherit the generics declared on its parent definition. (This hack is +// introduced for backwards compatibility and is tracked in #76200) // -// In this specific case however `b`'s parent should be `a` and so it should wind -// up not having any generics after all. If `a` were to inherit its generics from -// the enclosing item then the reference to `a` from `b` would contain generic -// parameters not usable by `b` which would cause us to ICE. +// In this specific case `a`'s parent should be `b` which does not have any generics. +// This means that even though `a` inherits generics from `b`, it still winds up not having +// access to any generic parameters. If `a` were to inherit its generics from the surrounding +// function `foo` then the reference to `a` from `b` would contain generic parameters not usable +// by `b` which would cause us to ICE. fn bar() {} diff --git a/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.stderr b/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.stderr index 64548cc5a301e..72a6e6977f583 100644 --- a/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.stderr +++ b/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/repeat_expr_hack_gives_right_generics.rs:16:17 + --> $DIR/repeat_expr_hack_gives_right_generics.rs:20:17 | LL | bar::<{ [1; N] }>(); | ^ cannot perform const operation using `N` diff --git a/tests/ui/const-generics/suggest_const_for_array.rs b/tests/ui/const-generics/suggest_const_for_array.rs index f3e5a3186cdd6..4d29d0693759f 100644 --- a/tests/ui/const-generics/suggest_const_for_array.rs +++ b/tests/ui/const-generics/suggest_const_for_array.rs @@ -3,8 +3,10 @@ fn example() {} fn other() { - example::<[usize; 3]>(); - //~^ ERROR type provided when a const - example::<[usize; 4+5]>(); - //~^ ERROR type provided when a const + example::<[usize; 3]>(); + //~^ ERROR type provided when a const + //~| ERROR type annotations needed + example::<[usize; 4 + 5]>(); + //~^ ERROR type provided when a const + //~| ERROR type annotations needed } diff --git a/tests/ui/const-generics/suggest_const_for_array.stderr b/tests/ui/const-generics/suggest_const_for_array.stderr index a617bf2bb0d96..c867914070bb7 100644 --- a/tests/ui/const-generics/suggest_const_for_array.stderr +++ b/tests/ui/const-generics/suggest_const_for_array.stderr @@ -1,15 +1,40 @@ error[E0747]: type provided when a constant was expected - --> $DIR/suggest_const_for_array.rs:6:13 + --> $DIR/suggest_const_for_array.rs:6:15 | -LL | example::<[usize; 3]>(); - | ^^^^^^^^^^ help: array type provided where a `usize` was expected, try: `{ 3 }` +LL | example::<[usize; 3]>(); + | ^^^^^^^^^^ help: array type provided where a `usize` was expected, try: `{ 3 }` error[E0747]: type provided when a constant was expected - --> $DIR/suggest_const_for_array.rs:8:13 + --> $DIR/suggest_const_for_array.rs:9:15 | -LL | example::<[usize; 4+5]>(); - | ^^^^^^^^^^^^ help: array type provided where a `usize` was expected, try: `{ 4+5 }` +LL | example::<[usize; 4 + 5]>(); + | ^^^^^^^^^^^^^^ help: array type provided where a `usize` was expected, try: `{ 4 + 5 }` -error: aborting due to 2 previous errors +error[E0284]: type annotations needed + --> $DIR/suggest_const_for_array.rs:6:5 + | +LL | example::<[usize; 3]>(); + | ^^^^^^^^^^^^^^^^^^^^^ cannot infer the value of the const parameter `N` declared on the function `example` + | +note: required by a const generic parameter in `example` + --> $DIR/suggest_const_for_array.rs:3:12 + | +LL | fn example() {} + | ^^^^^^^^^^^^^^ required by this const generic parameter in `example` + +error[E0284]: type annotations needed + --> $DIR/suggest_const_for_array.rs:9:5 + | +LL | example::<[usize; 4 + 5]>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer the value of the const parameter `N` declared on the function `example` + | +note: required by a const generic parameter in `example` + --> $DIR/suggest_const_for_array.rs:3:12 + | +LL | fn example() {} + | ^^^^^^^^^^^^^^ required by this const generic parameter in `example` + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0747`. +Some errors have detailed explanations: E0284, E0747. +For more information about an error, try `rustc --explain E0284`. diff --git a/tests/ui/consts/auxiliary/closure-in-foreign-crate.rs b/tests/ui/consts/auxiliary/closure-in-foreign-crate.rs index eb58233d1b1f8..a4dd3ee2e7e96 100644 --- a/tests/ui/consts/auxiliary/closure-in-foreign-crate.rs +++ b/tests/ui/consts/auxiliary/closure-in-foreign-crate.rs @@ -1,5 +1,7 @@ +//@ compile-flags: -Znext-solver #![crate_type = "lib"] -#![feature(const_closures, const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +#![feature(const_closures, const_trait_impl, effects)] +#![allow(incomplete_features)] pub const fn test() { let cl = const || {}; diff --git a/tests/ui/consts/const-float-classify.rs b/tests/ui/consts/const-float-classify.rs index ae094003c89e2..c64d31a5c60ae 100644 --- a/tests/ui/consts/const-float-classify.rs +++ b/tests/ui/consts/const-float-classify.rs @@ -1,10 +1,11 @@ -//@ compile-flags: -Zmir-opt-level=0 +//@ compile-flags: -Zmir-opt-level=0 -Znext-solver //@ known-bug: #110395 // FIXME(effects) run-pass #![feature(const_float_bits_conv)] #![feature(const_float_classify)] #![feature(const_trait_impl, effects)] +#![allow(incomplete_features)] // Don't promote const fn nop(x: T) -> T { x } diff --git a/tests/ui/consts/const-float-classify.stderr b/tests/ui/consts/const-float-classify.stderr index 1de27a072cf73..38acb8a228104 100644 --- a/tests/ui/consts/const-float-classify.stderr +++ b/tests/ui/consts/const-float-classify.stderr @@ -1,14 +1,5 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/const-float-classify.rs:7:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` - --> $DIR/const-float-classify.rs:12:12 + --> $DIR/const-float-classify.rs:13:12 | LL | impl const PartialEq for bool { | ^^^^^^^^^^^^^^^^^ @@ -16,208 +7,5 @@ LL | impl const PartialEq for bool { = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change -error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates - --> $DIR/const-float-classify.rs:12:6 - | -LL | impl const PartialEq for bool { - | ^^^^^ unconstrained const parameter - | - = note: expressions using a const parameter must map each value to a distinct output value - = note: proving the result of expressions other than the parameter are unique is not supported - -error[E0284]: type annotations needed - --> $DIR/const-float-classify.rs:21:35 - | -LL | const _: () = assert!($a == $b); - | ^^ cannot infer the value of the constant `_` -... -LL | / suite! { -LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] -LL | | -0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] -LL | | 0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] -... | -LL | | -1.0 / 0.0 => [ false, true, false, false, false, true] -LL | | } - | |_- in this macro invocation - | -note: required for `bool` to implement `PartialEq` - --> $DIR/const-float-classify.rs:12:12 - | -LL | impl const PartialEq for bool { - | ----- ^^^^^^^^^^^^^^^^^ ^^^^ - | | - | unsatisfied trait bound introduced here - = note: this error originates in the macro `const_assert` which comes from the expansion of the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0284]: type annotations needed - --> $DIR/const-float-classify.rs:21:35 - | -LL | const _: () = assert!($a == $b); - | ^^ cannot infer the value of the constant `_` -... -LL | / suite! { -LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] -LL | | -0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] -LL | | 0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] -... | -LL | | -1.0 / 0.0 => [ false, true, false, false, false, true] -LL | | } - | |_- in this macro invocation - | -note: required for `bool` to implement `PartialEq` - --> $DIR/const-float-classify.rs:12:12 - | -LL | impl const PartialEq for bool { - | ----- ^^^^^^^^^^^^^^^^^ ^^^^ - | | - | unsatisfied trait bound introduced here - = note: this error originates in the macro `const_assert` which comes from the expansion of the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0284]: type annotations needed - --> $DIR/const-float-classify.rs:21:35 - | -LL | const _: () = assert!($a == $b); - | ^^ cannot infer the value of the constant `_` -... -LL | / suite! { -LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] -LL | | -0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] -LL | | 0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] -... | -LL | | -1.0 / 0.0 => [ false, true, false, false, false, true] -LL | | } - | |_- in this macro invocation - | -note: required for `bool` to implement `PartialEq` - --> $DIR/const-float-classify.rs:12:12 - | -LL | impl const PartialEq for bool { - | ----- ^^^^^^^^^^^^^^^^^ ^^^^ - | | - | unsatisfied trait bound introduced here - = note: this error originates in the macro `const_assert` which comes from the expansion of the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0284]: type annotations needed - --> $DIR/const-float-classify.rs:21:35 - | -LL | const _: () = assert!($a == $b); - | ^^ cannot infer the value of the constant `_` -... -LL | / suite! { -LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] -LL | | -0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] -LL | | 0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] -... | -LL | | -1.0 / 0.0 => [ false, true, false, false, false, true] -LL | | } - | |_- in this macro invocation - | -note: required for `bool` to implement `PartialEq` - --> $DIR/const-float-classify.rs:12:12 - | -LL | impl const PartialEq for bool { - | ----- ^^^^^^^^^^^^^^^^^ ^^^^ - | | - | unsatisfied trait bound introduced here - = note: this error originates in the macro `const_assert` which comes from the expansion of the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0284]: type annotations needed - --> $DIR/const-float-classify.rs:21:35 - | -LL | const _: () = assert!($a == $b); - | ^^ cannot infer the value of the constant `_` -... -LL | / suite! { -LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] -LL | | -0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] -LL | | 0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] -... | -LL | | -1.0 / 0.0 => [ false, true, false, false, false, true] -LL | | } - | |_- in this macro invocation - | -note: required for `bool` to implement `PartialEq` - --> $DIR/const-float-classify.rs:12:12 - | -LL | impl const PartialEq for bool { - | ----- ^^^^^^^^^^^^^^^^^ ^^^^ - | | - | unsatisfied trait bound introduced here - = note: this error originates in the macro `const_assert` which comes from the expansion of the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0284]: type annotations needed - --> $DIR/const-float-classify.rs:21:35 - | -LL | const _: () = assert!($a == $b); - | ^^ cannot infer the value of the constant `_` -... -LL | / suite! { -LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] -LL | | -0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] -LL | | 0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] -... | -LL | | -1.0 / 0.0 => [ false, true, false, false, false, true] -LL | | } - | |_- in this macro invocation - | -note: required for `bool` to implement `PartialEq` - --> $DIR/const-float-classify.rs:12:12 - | -LL | impl const PartialEq for bool { - | ----- ^^^^^^^^^^^^^^^^^ ^^^^ - | | - | unsatisfied trait bound introduced here - = note: this error originates in the macro `const_assert` which comes from the expansion of the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0284]: type annotations needed - --> $DIR/const-float-classify.rs:21:35 - | -LL | const _: () = assert!($a == $b); - | ^^ cannot infer the value of the constant `_` -... -LL | / suite! { -LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] -LL | | -0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] -LL | | 0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] -... | -LL | | -1.0 / 0.0 => [ false, true, false, false, false, true] -LL | | } - | |_- in this macro invocation - | -note: required for `bool` to implement `PartialEq` - --> $DIR/const-float-classify.rs:12:12 - | -LL | impl const PartialEq for bool { - | ----- ^^^^^^^^^^^^^^^^^ ^^^^ - | | - | unsatisfied trait bound introduced here - = note: this error originates in the macro `const_assert` which comes from the expansion of the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0284]: type annotations needed - --> $DIR/const-float-classify.rs:21:35 - | -LL | const _: () = assert!($a == $b); - | ^^ cannot infer the value of the constant `_` -... -LL | / suite! { -LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] -LL | | -0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] -LL | | 0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] -... | -LL | | -1.0 / 0.0 => [ false, true, false, false, false, true] -LL | | } - | |_- in this macro invocation - | -note: required for `bool` to implement `PartialEq` - --> $DIR/const-float-classify.rs:12:12 - | -LL | impl const PartialEq for bool { - | ----- ^^^^^^^^^^^^^^^^^ ^^^^ - | | - | unsatisfied trait bound introduced here - = note: this error originates in the macro `const_assert` which comes from the expansion of the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 10 previous errors; 1 warning emitted +error: aborting due to 1 previous error -Some errors have detailed explanations: E0207, E0284. -For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/consts/const-try.rs b/tests/ui/consts/const-try.rs index f2d3db9be9c5b..9089dd70a26a6 100644 --- a/tests/ui/consts/const-try.rs +++ b/tests/ui/consts/const-try.rs @@ -4,8 +4,9 @@ #![crate_type = "lib"] #![feature(try_trait_v2)] -#![feature(const_trait_impl)] +#![feature(const_trait_impl, effects)] #![feature(const_try)] +#![allow(incomplete_features)] use std::ops::{ControlFlow, FromResidual, Try}; diff --git a/tests/ui/consts/const-try.stderr b/tests/ui/consts/const-try.stderr index 2d91424c8d320..8afdd4e0d61bf 100644 --- a/tests/ui/consts/const-try.stderr +++ b/tests/ui/consts/const-try.stderr @@ -1,37 +1,25 @@ -error[E0015]: `?` cannot determine the branch of `TryMe` in constant functions - --> $DIR/const-try.rs:33:5 - | -LL | TryMe?; - | ^^^^^^ - | -note: impl defined here, but it is not `const` - --> $DIR/const-try.rs:21:1 - | -LL | impl const Try for TryMe { - | ^^^^^^^^^^^^^^^^^^^^^^^^ - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] +error: using `#![feature(effects)]` without enabling next trait solver globally | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable -error[E0015]: `?` cannot convert from residual of `TryMe` in constant functions - --> $DIR/const-try.rs:33:5 - | -LL | TryMe?; - | ^^^^^^ - | -note: impl defined here, but it is not `const` - --> $DIR/const-try.rs:15:1 +error: const `impl` for trait `FromResidual` which is not marked with `#[const_trait]` + --> $DIR/const-try.rs:16:12 | LL | impl const FromResidual for TryMe { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable + | ^^^^^^^^^^^^^^^^^^^ | -LL + #![feature(effects)] + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: const `impl` for trait `Try` which is not marked with `#[const_trait]` + --> $DIR/const-try.rs:22:12 + | +LL | impl const Try for TryMe { + | ^^^ | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/const_cmp_type_id.rs b/tests/ui/consts/const_cmp_type_id.rs index f27271423232c..77482007be48a 100644 --- a/tests/ui/consts/const_cmp_type_id.rs +++ b/tests/ui/consts/const_cmp_type_id.rs @@ -1,12 +1,17 @@ -//@ known-bug: #110395 -#![feature(const_type_id)] -#![feature(const_trait_impl, effects)] +//@ check-pass +//@ compile-flags: -Znext-solver +#![feature(const_type_id, const_trait_impl, effects)] +#![allow(incomplete_features)] use std::any::TypeId; -const fn main() { - assert!(TypeId::of::() == TypeId::of::()); - assert!(TypeId::of::<()>() != TypeId::of::()); - const _A: bool = TypeId::of::() < TypeId::of::(); - // can't assert `_A` because it is not deterministic +fn main() { + const { + // FIXME(effects) this isn't supposed to pass (right now) but it did. + // revisit binops typeck please. + assert!(TypeId::of::() == TypeId::of::()); + assert!(TypeId::of::<()>() != TypeId::of::()); + let _a = TypeId::of::() < TypeId::of::(); + // can't assert `_a` because it is not deterministic + } } diff --git a/tests/ui/consts/const_cmp_type_id.stderr b/tests/ui/consts/const_cmp_type_id.stderr deleted file mode 100644 index e0e673d5fbdcf..0000000000000 --- a/tests/ui/consts/const_cmp_type_id.stderr +++ /dev/null @@ -1,25 +0,0 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/const_cmp_type_id.rs:3:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - -error[E0131]: `main` function is not allowed to have generic parameters - --> $DIR/const_cmp_type_id.rs:7:14 - | -LL | const fn main() { - | ^ `main` cannot have generic parameters - -error[E0080]: evaluation of constant value failed - --> $DIR/const_cmp_type_id.rs:10:22 - | -LL | const _A: bool = TypeId::of::() < TypeId::of::(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling non-const function `::lt` - -error: aborting due to 2 previous errors; 1 warning emitted - -Some errors have detailed explanations: E0080, E0131. -For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/constifconst-call-in-const-position.rs b/tests/ui/consts/constifconst-call-in-const-position.rs index 29c967f38a7d9..757e35bbab209 100644 --- a/tests/ui/consts/constifconst-call-in-const-position.rs +++ b/tests/ui/consts/constifconst-call-in-const-position.rs @@ -1,6 +1,7 @@ //@ known-bug: #102498 -#![feature(const_trait_impl, generic_const_exprs)] +#![feature(const_trait_impl, effects, generic_const_exprs)] +#![allow(incomplete_features)] #[const_trait] pub trait Tr { diff --git a/tests/ui/consts/constifconst-call-in-const-position.stderr b/tests/ui/consts/constifconst-call-in-const-position.stderr index 09827f29baf96..7de10f0287b4b 100644 --- a/tests/ui/consts/constifconst-call-in-const-position.stderr +++ b/tests/ui/consts/constifconst-call-in-const-position.stderr @@ -1,36 +1,26 @@ -warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/constifconst-call-in-const-position.rs:3:30 +error: using `#![feature(effects)]` without enabling next trait solver globally | -LL | #![feature(const_trait_impl, generic_const_exprs)] - | ^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #76560 for more information - = note: `#[warn(incomplete_features)]` on by default + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable -error[E0015]: cannot call non-const fn `::a` in constants - --> $DIR/constifconst-call-in-const-position.rs:17:9 - | -LL | [0; T::a()] - | ^^^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | - -error[E0015]: cannot call non-const fn `::a` in constants - --> $DIR/constifconst-call-in-const-position.rs:16:38 +error[E0308]: mismatched types + --> $DIR/constifconst-call-in-const-position.rs:17:38 | LL | const fn foo() -> [u8; T::a()] { - | ^^^^^^ + | ^^^^^^ expected `false`, found `host` | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable + = note: expected constant `false` + found constant `host` + +error[E0308]: mismatched types + --> $DIR/constifconst-call-in-const-position.rs:18:9 | -LL + #![feature(effects)] +LL | [0; T::a()] + | ^^^^^^ expected `false`, found `host` | + = note: expected constant `false` + found constant `host` -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/promoted-const-drop.rs b/tests/ui/consts/promoted-const-drop.rs index c896c011ab66a..b7d92d6523a81 100644 --- a/tests/ui/consts/promoted-const-drop.rs +++ b/tests/ui/consts/promoted-const-drop.rs @@ -4,6 +4,7 @@ struct A(); impl const Drop for A { + //~^ ERROR const `impl` for trait `Drop` which is not marked with `#[const_trait]` fn drop(&mut self) {} } diff --git a/tests/ui/consts/promoted-const-drop.stderr b/tests/ui/consts/promoted-const-drop.stderr index 4802834173fc5..1201f608232df 100644 --- a/tests/ui/consts/promoted-const-drop.stderr +++ b/tests/ui/consts/promoted-const-drop.stderr @@ -1,5 +1,14 @@ +error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` + --> $DIR/promoted-const-drop.rs:6:12 + | +LL | impl const Drop for A { + | ^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted-const-drop.rs:13:26 + --> $DIR/promoted-const-drop.rs:14:26 | LL | let _: &'static A = &A(); | ---------- ^^^ creates a temporary value which is freed while still in use @@ -10,7 +19,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted-const-drop.rs:14:28 + --> $DIR/promoted-const-drop.rs:15:28 | LL | let _: &'static [A] = &[C]; | ------------ ^^^ creates a temporary value which is freed while still in use @@ -19,6 +28,6 @@ LL | let _: &'static [A] = &[C]; LL | } | - temporary value is freed at the end of this statement -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/promoted_const_call.stderr b/tests/ui/consts/promoted_const_call.stderr index ace449fae9ce6..64bf6bd73b0a5 100644 --- a/tests/ui/consts/promoted_const_call.stderr +++ b/tests/ui/consts/promoted_const_call.stderr @@ -1,10 +1,31 @@ -error[E0493]: destructor of `Panic` cannot be evaluated at compile-time +error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` + --> $DIR/promoted_const_call.rs:7:12 + | +LL | impl const Drop for Panic { fn drop(&mut self) { panic!(); } } + | ^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call.rs:11:26 + | +LL | let _: &'static _ = &id(&Panic); + | ---------- ^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | }; + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed --> $DIR/promoted_const_call.rs:11:30 | LL | let _: &'static _ = &id(&Panic); - | ^^^^^ - value is dropped here - | | - | the destructor for this type cannot be evaluated in constants + | ---------- ^^^^^ - temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | type annotation requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed --> $DIR/promoted_const_call.rs:17:26 @@ -48,7 +69,6 @@ LL | let _: &'static _ = &&(Panic, 0).1; LL | } | - temporary value is freed at the end of this statement -error: aborting due to 5 previous errors +error: aborting due to 7 previous errors -Some errors have detailed explanations: E0493, E0716. -For more information about an error, try `rustc --explain E0493`. +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/rustc-impl-const-stability.rs b/tests/ui/consts/rustc-impl-const-stability.rs index 98c5c89713804..af3262ca57534 100644 --- a/tests/ui/consts/rustc-impl-const-stability.rs +++ b/tests/ui/consts/rustc-impl-const-stability.rs @@ -1,8 +1,9 @@ +//@ compile-flags: -Znext-solver //@ known-bug: #110395 #![crate_type = "lib"] -#![feature(staged_api)] -#![feature(const_trait_impl, effects)] +#![feature(staged_api, const_trait_impl, effects)] +#![allow(incomplete_features)] #![stable(feature = "foo", since = "1.0.0")] #[stable(feature = "potato", since = "1.27.0")] diff --git a/tests/ui/consts/rustc-impl-const-stability.stderr b/tests/ui/consts/rustc-impl-const-stability.stderr index 250d1c3fc0553..4a534b3ca1410 100644 --- a/tests/ui/consts/rustc-impl-const-stability.stderr +++ b/tests/ui/consts/rustc-impl-const-stability.stderr @@ -1,14 +1,5 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/rustc-impl-const-stability.rs:5:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - error: const `impl` for trait `Default` which is not marked with `#[const_trait]` - --> $DIR/rustc-impl-const-stability.rs:15:12 + --> $DIR/rustc-impl-const-stability.rs:16:12 | LL | impl const Default for Data { | ^^^^^^^ @@ -16,15 +7,5 @@ LL | impl const Default for Data { = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change -error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates - --> $DIR/rustc-impl-const-stability.rs:15:6 - | -LL | impl const Default for Data { - | ^^^^^ unconstrained const parameter - | - = note: expressions using a const parameter must map each value to a distinct output value - = note: proving the result of expressions other than the parameter are unique is not supported - -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr b/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr index 84f00827c6010..5653494630899 100644 --- a/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr +++ b/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr @@ -3,6 +3,10 @@ error: extern block cannot be declared unsafe | LL | unsafe extern "C" { | ^^^^^^ + | + = note: see issue #123743 for more information + = help: add `#![feature(unsafe_extern_blocks)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `unsafe extern {}` blocks and `safe` keyword are experimental --> $DIR/feature-gate-unsafe-extern-blocks.rs:9:5 diff --git a/tests/ui/generic-const-items/const-trait-impl.rs b/tests/ui/generic-const-items/const-trait-impl.rs index 34be9fe601400..51209121bd915 100644 --- a/tests/ui/generic-const-items/const-trait-impl.rs +++ b/tests/ui/generic-const-items/const-trait-impl.rs @@ -1,5 +1,5 @@ //@ check-pass - +//@ compile-flags: -Znext-solver // Test that we can call methods from const trait impls inside of generic const items. #![feature(generic_const_items, const_trait_impl, effects)] diff --git a/tests/ui/generics/generic-function-item-where-type.rs b/tests/ui/generics/generic-function-item-where-type.rs index e1b0578cadbe9..0e36018389e96 100644 --- a/tests/ui/generics/generic-function-item-where-type.rs +++ b/tests/ui/generics/generic-function-item-where-type.rs @@ -3,4 +3,5 @@ fn foo() {} fn main() { foo::
() //~^ ERROR constant provided when a type was expected + //~| ERROR type annotations needed } diff --git a/tests/ui/generics/generic-function-item-where-type.stderr b/tests/ui/generics/generic-function-item-where-type.stderr index 00e62843cb4b6..5b0c9a8ee6df5 100644 --- a/tests/ui/generics/generic-function-item-where-type.stderr +++ b/tests/ui/generics/generic-function-item-where-type.stderr @@ -7,6 +7,13 @@ LL | foo::
() = help: `main` is a function item, not a type = help: function item types cannot be named directly -error: aborting due to 1 previous error +error[E0282]: type annotations needed + --> $DIR/generic-function-item-where-type.rs:4:5 + | +LL | foo::
() + | ^^^^^^^^^^^ cannot infer type of the type parameter `U` declared on the function `foo` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0747`. +Some errors have detailed explanations: E0282, E0747. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/higher-ranked/erroneous-lifetime-bound.rs b/tests/ui/higher-ranked/erroneous-lifetime-bound.rs new file mode 100644 index 0000000000000..b1720087b5f6d --- /dev/null +++ b/tests/ui/higher-ranked/erroneous-lifetime-bound.rs @@ -0,0 +1,5 @@ +fn foo() where T: for<'a> 'a {} +//~^ ERROR `for<...>` may only modify trait bounds, not lifetime bounds +//~| ERROR use of undeclared lifetime name `'a` [E0261] + +fn main() {} diff --git a/tests/ui/higher-ranked/erroneous-lifetime-bound.stderr b/tests/ui/higher-ranked/erroneous-lifetime-bound.stderr new file mode 100644 index 0000000000000..5b104f45d2361 --- /dev/null +++ b/tests/ui/higher-ranked/erroneous-lifetime-bound.stderr @@ -0,0 +1,25 @@ +error: `for<...>` may only modify trait bounds, not lifetime bounds + --> $DIR/erroneous-lifetime-bound.rs:1:25 + | +LL | fn foo() where T: for<'a> 'a {} + | ^^^^ + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/erroneous-lifetime-bound.rs:1:30 + | +LL | fn foo() where T: for<'a> 'a {} + | ^^ undeclared lifetime + | + = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | fn foo() where for<'a> T: for<'a> 'a {} + | +++++++ +help: consider introducing lifetime `'a` here + | +LL | fn foo<'a, T>() where T: for<'a> 'a {} + | +++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0261`. diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs index 199cbbf4fcc9b..8aba3de530b8e 100644 --- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs +++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs @@ -2,6 +2,7 @@ use std::fmt::Debug; fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { + //~^ ERROR cannot resolve opaque type |x| x //~^ ERROR expected generic lifetime parameter, found `'_` } diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr index 6064b09ef0927..c2386e8c88be0 100644 --- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr +++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr @@ -1,11 +1,19 @@ error[E0792]: expected generic lifetime parameter, found `'_` - --> $DIR/impl-fn-predefined-lifetimes.rs:5:9 + --> $DIR/impl-fn-predefined-lifetimes.rs:6:9 | LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { | -- this generic parameter must be used with a generic lifetime parameter +LL | LL | |x| x | ^ -error: aborting due to 1 previous error +error[E0720]: cannot resolve opaque type + --> $DIR/impl-fn-predefined-lifetimes.rs:4:35 + | +LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { + | ^^^^^^^^^^^^^^^ cannot resolve opaque type + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0792`. +Some errors have detailed explanations: E0720, E0792. +For more information about an error, try `rustc --explain E0720`. diff --git a/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs b/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs new file mode 100644 index 0000000000000..15f2188262869 --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs @@ -0,0 +1,25 @@ +//@ edition: 2021 + +#![feature(precise_capturing)] + +fn polarity() -> impl Sized + ?use<> {} +//~^ ERROR expected identifier, found keyword `use` +//~| ERROR cannot find trait `r#use` in this scope +//~| WARN relaxing a default bound only does something for `?Sized` +//~| WARN relaxing a default bound only does something for `?Sized` + +fn asyncness() -> impl Sized + async use<> {} +//~^ ERROR expected identifier, found keyword `use` +//~| ERROR cannot find trait `r#use` in this scope +//~| ERROR async closures are unstable + +fn constness() -> impl Sized + const use<> {} +//~^ ERROR expected identifier, found keyword `use` +//~| ERROR cannot find trait `r#use` in this scope +//~| ERROR const trait impls are experimental + +fn binder() -> impl Sized + for<'a> use<> {} +//~^ ERROR expected identifier, found keyword `use` +//~| ERROR cannot find trait `r#use` in this scope + +fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr b/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr new file mode 100644 index 0000000000000..4602225e7b922 --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr @@ -0,0 +1,87 @@ +error: expected identifier, found keyword `use` + --> $DIR/bound-modifiers.rs:5:32 + | +LL | fn polarity() -> impl Sized + ?use<> {} + | ^^^ expected identifier, found keyword + +error: expected identifier, found keyword `use` + --> $DIR/bound-modifiers.rs:11:38 + | +LL | fn asyncness() -> impl Sized + async use<> {} + | ^^^ expected identifier, found keyword + +error: expected identifier, found keyword `use` + --> $DIR/bound-modifiers.rs:16:38 + | +LL | fn constness() -> impl Sized + const use<> {} + | ^^^ expected identifier, found keyword + +error: expected identifier, found keyword `use` + --> $DIR/bound-modifiers.rs:21:37 + | +LL | fn binder() -> impl Sized + for<'a> use<> {} + | ^^^ expected identifier, found keyword + +error[E0405]: cannot find trait `r#use` in this scope + --> $DIR/bound-modifiers.rs:5:32 + | +LL | fn polarity() -> impl Sized + ?use<> {} + | ^^^ not found in this scope + +error[E0405]: cannot find trait `r#use` in this scope + --> $DIR/bound-modifiers.rs:11:38 + | +LL | fn asyncness() -> impl Sized + async use<> {} + | ^^^ not found in this scope + +error[E0405]: cannot find trait `r#use` in this scope + --> $DIR/bound-modifiers.rs:16:38 + | +LL | fn constness() -> impl Sized + const use<> {} + | ^^^ not found in this scope + +error[E0405]: cannot find trait `r#use` in this scope + --> $DIR/bound-modifiers.rs:21:37 + | +LL | fn binder() -> impl Sized + for<'a> use<> {} + | ^^^ not found in this scope + +error[E0658]: async closures are unstable + --> $DIR/bound-modifiers.rs:11:32 + | +LL | fn asyncness() -> impl Sized + async use<> {} + | ^^^^^ + | + = note: see issue #62290 for more information + = help: add `#![feature(async_closure)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: to use an async block, remove the `||`: `async {` + +error[E0658]: const trait impls are experimental + --> $DIR/bound-modifiers.rs:16:32 + | +LL | fn constness() -> impl Sized + const use<> {} + | ^^^^^ + | + = note: see issue #67792 for more information + = help: add `#![feature(const_trait_impl)]` 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: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default + --> $DIR/bound-modifiers.rs:5:31 + | +LL | fn polarity() -> impl Sized + ?use<> {} + | ^^^^^^ + +warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default + --> $DIR/bound-modifiers.rs:5:31 + | +LL | fn polarity() -> impl Sized + ?use<> {} + | ^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 10 previous errors; 2 warnings emitted + +Some errors have detailed explanations: E0405, E0658. +For more information about an error, try `rustc --explain E0405`. diff --git a/tests/ui/impl-trait/transmute/in-defining-scope.rs b/tests/ui/impl-trait/transmute/in-defining-scope.rs index b0b77d60b245e..b9a9dbc10a5b4 100644 --- a/tests/ui/impl-trait/transmute/in-defining-scope.rs +++ b/tests/ui/impl-trait/transmute/in-defining-scope.rs @@ -5,6 +5,7 @@ use std::mem::transmute; fn foo() -> impl Sized { //~^ ERROR cycle detected when computing type of + //~| WARN function cannot return without recursing unsafe { transmute::<_, u8>(foo()); } diff --git a/tests/ui/impl-trait/transmute/in-defining-scope.stderr b/tests/ui/impl-trait/transmute/in-defining-scope.stderr index 69812f43072b0..7172bfdf0d7e2 100644 --- a/tests/ui/impl-trait/transmute/in-defining-scope.stderr +++ b/tests/ui/impl-trait/transmute/in-defining-scope.stderr @@ -24,6 +24,18 @@ LL | fn foo() -> impl Sized { | ^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to 1 previous error +warning: function cannot return without recursing + --> $DIR/in-defining-scope.rs:6:1 + | +LL | fn foo() -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +... +LL | transmute::<_, u8>(foo()); + | ----- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/infinite/infinite-struct.rs b/tests/ui/infinite/infinite-struct.rs index f08e10f6bdbc0..62f9702b9f411 100644 --- a/tests/ui/infinite/infinite-struct.rs +++ b/tests/ui/infinite/infinite-struct.rs @@ -1,5 +1,6 @@ struct Take(Take); //~^ ERROR has infinite size +//~| ERROR cycle // check that we don't hang trying to find the tail of a recursive struct (#79437) fn foo() -> Take { diff --git a/tests/ui/infinite/infinite-struct.stderr b/tests/ui/infinite/infinite-struct.stderr index 82d147b63cda0..5896aec399dc4 100644 --- a/tests/ui/infinite/infinite-struct.stderr +++ b/tests/ui/infinite/infinite-struct.stderr @@ -10,7 +10,7 @@ LL | struct Take(Box); | ++++ + error[E0072]: recursive type `Foo` has infinite size - --> $DIR/infinite-struct.rs:10:1 + --> $DIR/infinite-struct.rs:11:1 | LL | struct Foo { | ^^^^^^^^^^ @@ -26,6 +26,17 @@ error: reached the recursion limit finding the struct tail for `Take` | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` -error: aborting due to 3 previous errors +error[E0391]: cycle detected when computing when `Take` needs drop + --> $DIR/infinite-struct.rs:1:1 + | +LL | struct Take(Take); + | ^^^^^^^^^^^ + | + = note: ...which immediately requires computing when `Take` needs drop again + = note: cycle used when computing whether `Take` needs drop + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0072`. +Some errors have detailed explanations: E0072, E0391. +For more information about an error, try `rustc --explain E0072`. diff --git a/tests/ui/lint/lint-owned-heap-memory.rs b/tests/ui/lint/lint-owned-heap-memory.rs deleted file mode 100644 index af47d5c072005..0000000000000 --- a/tests/ui/lint/lint-owned-heap-memory.rs +++ /dev/null @@ -1,12 +0,0 @@ -#![allow(dead_code)] -#![forbid(box_pointers)] - - -struct Foo { - x: Box //~ ERROR type uses owned -} - -fn main() { - let _x: Foo = Foo { x : Box::new(10) }; - //~^ ERROR type uses owned -} diff --git a/tests/ui/lint/lint-owned-heap-memory.stderr b/tests/ui/lint/lint-owned-heap-memory.stderr deleted file mode 100644 index 5ba3969707571..0000000000000 --- a/tests/ui/lint/lint-owned-heap-memory.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: type uses owned (Box type) pointers: Box - --> $DIR/lint-owned-heap-memory.rs:6:5 - | -LL | x: Box - | ^^^^^^^^^^^^^ - | -note: the lint level is defined here - --> $DIR/lint-owned-heap-memory.rs:2:11 - | -LL | #![forbid(box_pointers)] - | ^^^^^^^^^^^^ - -error: type uses owned (Box type) pointers: Box - --> $DIR/lint-owned-heap-memory.rs:10:29 - | -LL | let _x: Foo = Foo { x : Box::new(10) }; - | ^^^^^^^^^^^^ - -error: aborting due to 2 previous errors - diff --git a/tests/ui/lint/non-local-defs/cargo-update.rs b/tests/ui/lint/non-local-defs/cargo-update.rs index 8b8c15795d376..3c62a655a9f61 100644 --- a/tests/ui/lint/non-local-defs/cargo-update.rs +++ b/tests/ui/lint/non-local-defs/cargo-update.rs @@ -10,6 +10,8 @@ // of the `cargo update` suggestion we assert it here. //@ error-pattern: `cargo update -p non_local_macro` +#![warn(non_local_definitions)] + extern crate non_local_macro; struct LocalStruct; diff --git a/tests/ui/lint/non-local-defs/cargo-update.stderr b/tests/ui/lint/non-local-defs/cargo-update.stderr index bccf8622bac66..4dd41519455c6 100644 --- a/tests/ui/lint/non-local-defs/cargo-update.stderr +++ b/tests/ui/lint/non-local-defs/cargo-update.stderr @@ -1,5 +1,5 @@ warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/cargo-update.rs:17:1 + --> $DIR/cargo-update.rs:19:1 | LL | non_local_macro::non_local_impl!(LocalStruct); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,7 +14,11 @@ LL | non_local_macro::non_local_impl!(LocalStruct); = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration for the purpose of this lint = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue - = note: `#[warn(non_local_definitions)]` on by default +note: the lint level is defined here + --> $DIR/cargo-update.rs:13:9 + | +LL | #![warn(non_local_definitions)] + | ^^^^^^^^^^^^^^^^^^^^^ = note: this warning originates in the macro `non_local_macro::non_local_impl` (in Nightly builds, run with -Z macro-backtrace for more info) warning: 1 warning emitted diff --git a/tests/ui/lint/non-local-defs/consts.rs b/tests/ui/lint/non-local-defs/consts.rs index d8a497e43e502..e7ee611529b96 100644 --- a/tests/ui/lint/non-local-defs/consts.rs +++ b/tests/ui/lint/non-local-defs/consts.rs @@ -2,6 +2,8 @@ //@ edition:2021 //@ rustc-env:CARGO_CRATE_NAME=non_local_def +#![warn(non_local_definitions)] + struct Test; trait Uto {} diff --git a/tests/ui/lint/non-local-defs/consts.stderr b/tests/ui/lint/non-local-defs/consts.stderr index 9f70119e0f8c9..ed7bd56fe4a54 100644 --- a/tests/ui/lint/non-local-defs/consts.stderr +++ b/tests/ui/lint/non-local-defs/consts.stderr @@ -1,5 +1,5 @@ warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/consts.rs:13:5 + --> $DIR/consts.rs:15:5 | LL | const Z: () = { | ----------- @@ -17,10 +17,14 @@ LL | impl Uto for &Test {} = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration for the purpose of this lint = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue - = note: `#[warn(non_local_definitions)]` on by default +note: the lint level is defined here + --> $DIR/consts.rs:5:9 + | +LL | #![warn(non_local_definitions)] + | ^^^^^^^^^^^^^^^^^^^^^ warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/consts.rs:24:5 + --> $DIR/consts.rs:26:5 | LL | static A: u32 = { | ------------- move the `impl` block outside of this static `A` @@ -36,7 +40,7 @@ LL | impl Uto2 for Test {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/consts.rs:32:5 + --> $DIR/consts.rs:34:5 | LL | const B: u32 = { | ------------ move the `impl` block outside of this constant `B` @@ -52,7 +56,7 @@ LL | impl Uto3 for Test {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/consts.rs:43:5 + --> $DIR/consts.rs:45:5 | LL | fn main() { | --------- move the `impl` block outside of this function `main` @@ -65,7 +69,7 @@ LL | impl Test { = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/consts.rs:50:9 + --> $DIR/consts.rs:52:9 | LL | const { | ___________- @@ -84,7 +88,7 @@ LL | | }; = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/consts.rs:59:9 + --> $DIR/consts.rs:61:9 | LL | const _: u32 = { | ------------ move the `impl` block outside of this constant `_` and up 2 bodies @@ -98,7 +102,7 @@ LL | impl Test { = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/consts.rs:72:9 + --> $DIR/consts.rs:74:9 | LL | let _a = || { | -- move the `impl` block outside of this closure `` and up 2 bodies @@ -113,7 +117,7 @@ LL | impl Uto9 for Test {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/consts.rs:79:9 + --> $DIR/consts.rs:81:9 | LL | type A = [u32; { | ____________________- diff --git a/tests/ui/lint/non-local-defs/exhaustive-trait.rs b/tests/ui/lint/non-local-defs/exhaustive-trait.rs index 40d2314460f86..79f8cc4620b97 100644 --- a/tests/ui/lint/non-local-defs/exhaustive-trait.rs +++ b/tests/ui/lint/non-local-defs/exhaustive-trait.rs @@ -1,6 +1,8 @@ //@ check-pass //@ edition:2021 +#![warn(non_local_definitions)] + struct Dog; fn main() { diff --git a/tests/ui/lint/non-local-defs/exhaustive-trait.stderr b/tests/ui/lint/non-local-defs/exhaustive-trait.stderr index 67df0e31d5bdf..24c9a6b4f01e2 100644 --- a/tests/ui/lint/non-local-defs/exhaustive-trait.stderr +++ b/tests/ui/lint/non-local-defs/exhaustive-trait.stderr @@ -1,5 +1,5 @@ warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/exhaustive-trait.rs:7:5 + --> $DIR/exhaustive-trait.rs:9:5 | LL | fn main() { | --------- move the `impl` block outside of this function `main` @@ -12,10 +12,14 @@ LL | impl PartialEq<()> for Dog { = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue - = note: `#[warn(non_local_definitions)]` on by default +note: the lint level is defined here + --> $DIR/exhaustive-trait.rs:4:9 + | +LL | #![warn(non_local_definitions)] + | ^^^^^^^^^^^^^^^^^^^^^ warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/exhaustive-trait.rs:14:5 + --> $DIR/exhaustive-trait.rs:16:5 | LL | fn main() { | --------- move the `impl` block outside of this function `main` @@ -31,7 +35,7 @@ LL | impl PartialEq<()> for &Dog { = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/exhaustive-trait.rs:21:5 + --> $DIR/exhaustive-trait.rs:23:5 | LL | fn main() { | --------- move the `impl` block outside of this function `main` @@ -47,7 +51,7 @@ LL | impl PartialEq for () { = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/exhaustive-trait.rs:28:5 + --> $DIR/exhaustive-trait.rs:30:5 | LL | fn main() { | --------- move the `impl` block outside of this function `main` @@ -63,7 +67,7 @@ LL | impl PartialEq<&Dog> for () { = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/exhaustive-trait.rs:35:5 + --> $DIR/exhaustive-trait.rs:37:5 | LL | fn main() { | --------- move the `impl` block outside of this function `main` @@ -79,7 +83,7 @@ LL | impl PartialEq for &Dog { = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/exhaustive-trait.rs:42:5 + --> $DIR/exhaustive-trait.rs:44:5 | LL | fn main() { | --------- move the `impl` block outside of this function `main` diff --git a/tests/ui/lint/non-local-defs/exhaustive.rs b/tests/ui/lint/non-local-defs/exhaustive.rs index 2fb30f4344abb..f59a85c7ed94f 100644 --- a/tests/ui/lint/non-local-defs/exhaustive.rs +++ b/tests/ui/lint/non-local-defs/exhaustive.rs @@ -1,6 +1,8 @@ //@ check-pass //@ edition:2021 +#![warn(non_local_definitions)] + use std::fmt::Display; trait Trait {} diff --git a/tests/ui/lint/non-local-defs/exhaustive.stderr b/tests/ui/lint/non-local-defs/exhaustive.stderr index 1e0d5caec3830..6d8c2ec0bc7cf 100644 --- a/tests/ui/lint/non-local-defs/exhaustive.stderr +++ b/tests/ui/lint/non-local-defs/exhaustive.stderr @@ -1,5 +1,5 @@ warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/exhaustive.rs:10:5 + --> $DIR/exhaustive.rs:12:5 | LL | fn main() { | --------- move the `impl` block outside of this function `main` @@ -10,10 +10,14 @@ LL | impl Test { | = note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue - = note: `#[warn(non_local_definitions)]` on by default +note: the lint level is defined here + --> $DIR/exhaustive.rs:4:9 + | +LL | #![warn(non_local_definitions)] + | ^^^^^^^^^^^^^^^^^^^^^ warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/exhaustive.rs:15:5 + --> $DIR/exhaustive.rs:17:5 | LL | fn main() { | --------- move the `impl` block outside of this function `main` @@ -29,7 +33,7 @@ LL | impl Display for Test { = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/exhaustive.rs:22:5 + --> $DIR/exhaustive.rs:24:5 | LL | fn main() { | --------- move the `impl` block outside of this function `main` @@ -43,7 +47,7 @@ LL | impl dyn Trait {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/exhaustive.rs:25:5 + --> $DIR/exhaustive.rs:27:5 | LL | fn main() { | --------- move the `impl` block outside of this function `main` @@ -59,7 +63,7 @@ LL | impl Trait for Vec { } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/exhaustive.rs:28:5 + --> $DIR/exhaustive.rs:30:5 | LL | fn main() { | --------- move the `impl` block outside of this function `main` @@ -75,7 +79,7 @@ LL | impl Trait for &dyn Trait {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/exhaustive.rs:31:5 + --> $DIR/exhaustive.rs:33:5 | LL | fn main() { | --------- move the `impl` block outside of this function `main` @@ -91,7 +95,7 @@ LL | impl Trait for *mut Test {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/exhaustive.rs:34:5 + --> $DIR/exhaustive.rs:36:5 | LL | fn main() { | --------- move the `impl` block outside of this function `main` @@ -107,7 +111,7 @@ LL | impl Trait for *mut [Test] {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/exhaustive.rs:37:5 + --> $DIR/exhaustive.rs:39:5 | LL | fn main() { | --------- move the `impl` block outside of this function `main` @@ -123,7 +127,7 @@ LL | impl Trait for [Test; 8] {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/exhaustive.rs:40:5 + --> $DIR/exhaustive.rs:42:5 | LL | fn main() { | --------- move the `impl` block outside of this function `main` @@ -139,7 +143,7 @@ LL | impl Trait for (Test,) {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/exhaustive.rs:43:5 + --> $DIR/exhaustive.rs:45:5 | LL | fn main() { | --------- move the `impl` block outside of this function `main` @@ -155,7 +159,7 @@ LL | impl Trait for fn(Test) -> () {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/exhaustive.rs:46:5 + --> $DIR/exhaustive.rs:48:5 | LL | fn main() { | --------- move the `impl` block outside of this function `main` @@ -171,7 +175,7 @@ LL | impl Trait for fn() -> Test {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/exhaustive.rs:50:9 + --> $DIR/exhaustive.rs:52:9 | LL | let _a = || { | -- move the `impl` block outside of this closure `` and up 2 bodies @@ -186,7 +190,7 @@ LL | impl Trait for Test {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/exhaustive.rs:58:5 + --> $DIR/exhaustive.rs:60:5 | LL | impl Trait for *mut InsideMain {} | ^^^^^-----^^^^^--------------- @@ -198,7 +202,7 @@ LL | impl Trait for *mut InsideMain {} = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` help: move the `impl` block outside of this function `main` - --> $DIR/exhaustive.rs:9:1 + --> $DIR/exhaustive.rs:11:1 | LL | fn main() { | ^^^^^^^^^ @@ -208,7 +212,7 @@ LL | struct InsideMain; = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/exhaustive.rs:60:5 + --> $DIR/exhaustive.rs:62:5 | LL | impl Trait for *mut [InsideMain] {} | ^^^^^-----^^^^^----------------- @@ -219,7 +223,7 @@ LL | impl Trait for *mut [InsideMain] {} = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` help: move the `impl` block outside of this function `main` - --> $DIR/exhaustive.rs:9:1 + --> $DIR/exhaustive.rs:11:1 | LL | fn main() { | ^^^^^^^^^ @@ -229,7 +233,7 @@ LL | struct InsideMain; = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/exhaustive.rs:62:5 + --> $DIR/exhaustive.rs:64:5 | LL | impl Trait for [InsideMain; 8] {} | ^^^^^-----^^^^^--------------- @@ -240,7 +244,7 @@ LL | impl Trait for [InsideMain; 8] {} = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` help: move the `impl` block outside of this function `main` - --> $DIR/exhaustive.rs:9:1 + --> $DIR/exhaustive.rs:11:1 | LL | fn main() { | ^^^^^^^^^ @@ -250,7 +254,7 @@ LL | struct InsideMain; = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/exhaustive.rs:64:5 + --> $DIR/exhaustive.rs:66:5 | LL | impl Trait for (InsideMain,) {} | ^^^^^-----^^^^^------------- @@ -261,7 +265,7 @@ LL | impl Trait for (InsideMain,) {} = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` help: move the `impl` block outside of this function `main` - --> $DIR/exhaustive.rs:9:1 + --> $DIR/exhaustive.rs:11:1 | LL | fn main() { | ^^^^^^^^^ @@ -271,7 +275,7 @@ LL | struct InsideMain; = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/exhaustive.rs:66:5 + --> $DIR/exhaustive.rs:68:5 | LL | impl Trait for fn(InsideMain) -> () {} | ^^^^^-----^^^^^-------------------- @@ -282,7 +286,7 @@ LL | impl Trait for fn(InsideMain) -> () {} = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` help: move the `impl` block outside of this function `main` - --> $DIR/exhaustive.rs:9:1 + --> $DIR/exhaustive.rs:11:1 | LL | fn main() { | ^^^^^^^^^ @@ -292,7 +296,7 @@ LL | struct InsideMain; = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/exhaustive.rs:68:5 + --> $DIR/exhaustive.rs:70:5 | LL | impl Trait for fn() -> InsideMain {} | ^^^^^-----^^^^^------------------ @@ -303,7 +307,7 @@ LL | impl Trait for fn() -> InsideMain {} = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` help: move the `impl` block outside of this function `main` - --> $DIR/exhaustive.rs:9:1 + --> $DIR/exhaustive.rs:11:1 | LL | fn main() { | ^^^^^^^^^ @@ -313,7 +317,7 @@ LL | struct InsideMain; = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/exhaustive.rs:72:9 + --> $DIR/exhaustive.rs:74:9 | LL | fn inside_inside() { | ------------------ move the `impl` block outside of this function `inside_inside` and up 2 bodies @@ -328,7 +332,7 @@ LL | impl Display for InsideMain { = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/exhaustive.rs:79:9 + --> $DIR/exhaustive.rs:81:9 | LL | fn inside_inside() { | ------------------ move the `impl` block outside of this function `inside_inside` and up 2 bodies diff --git a/tests/ui/lint/non-local-defs/from-local-for-global.rs b/tests/ui/lint/non-local-defs/from-local-for-global.rs index fea9679d7375d..1d8f4845c2860 100644 --- a/tests/ui/lint/non-local-defs/from-local-for-global.rs +++ b/tests/ui/lint/non-local-defs/from-local-for-global.rs @@ -1,6 +1,8 @@ //@ check-pass //@ edition:2021 +#![warn(non_local_definitions)] + struct Cat; struct Wrap(T); diff --git a/tests/ui/lint/non-local-defs/from-local-for-global.stderr b/tests/ui/lint/non-local-defs/from-local-for-global.stderr index 67fd937d134cc..04eba8435fc04 100644 --- a/tests/ui/lint/non-local-defs/from-local-for-global.stderr +++ b/tests/ui/lint/non-local-defs/from-local-for-global.stderr @@ -1,5 +1,5 @@ warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/from-local-for-global.rs:8:5 + --> $DIR/from-local-for-global.rs:10:5 | LL | fn main() { | --------- move the `impl` block outside of this function `main` @@ -12,10 +12,14 @@ LL | impl From for () { = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue - = note: `#[warn(non_local_definitions)]` on by default +note: the lint level is defined here + --> $DIR/from-local-for-global.rs:4:9 + | +LL | #![warn(non_local_definitions)] + | ^^^^^^^^^^^^^^^^^^^^^ warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/from-local-for-global.rs:18:5 + --> $DIR/from-local-for-global.rs:20:5 | LL | impl From>> for () { | ^^^^^----^^^^^^^^^^^^^^^^^^^^^^^^^^^-- @@ -25,7 +29,7 @@ LL | impl From>> for () { = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` help: move the `impl` block outside of this function `main` - --> $DIR/from-local-for-global.rs:7:1 + --> $DIR/from-local-for-global.rs:9:1 | LL | fn main() { | ^^^^^^^^^ @@ -35,7 +39,7 @@ LL | struct Elephant; = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/from-local-for-global.rs:32:5 + --> $DIR/from-local-for-global.rs:34:5 | LL | impl StillNonLocal for &Foo {} | ^^^^^-------------^^^^^---- @@ -47,7 +51,7 @@ LL | impl StillNonLocal for &Foo {} = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` help: move the `impl` block outside of this function `only_global` - --> $DIR/from-local-for-global.rs:30:1 + --> $DIR/from-local-for-global.rs:32:1 | LL | fn only_global() { | ^^^^^^^^^^^^^^^^ @@ -56,7 +60,7 @@ LL | struct Foo; = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/from-local-for-global.rs:40:5 + --> $DIR/from-local-for-global.rs:42:5 | LL | impl From for GlobalSameFunction { | ^^^^^----^^^^^^^^^^^^^------------------ @@ -67,7 +71,7 @@ LL | impl From for GlobalSameFunction { = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` help: move the `impl` block outside of this function `same_function` - --> $DIR/from-local-for-global.rs:38:1 + --> $DIR/from-local-for-global.rs:40:1 | LL | fn same_function() { | ^^^^^^^^^^^^^^^^^^ @@ -76,7 +80,7 @@ LL | struct Local1(GlobalSameFunction); = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/from-local-for-global.rs:48:5 + --> $DIR/from-local-for-global.rs:50:5 | LL | impl From for GlobalSameFunction { | ^^^^^----^^^^^^^^^^^^^------------------ @@ -87,7 +91,7 @@ LL | impl From for GlobalSameFunction { = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` help: move the `impl` block outside of this function `same_function` - --> $DIR/from-local-for-global.rs:38:1 + --> $DIR/from-local-for-global.rs:40:1 | LL | fn same_function() { | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/non-local-defs/generics.rs b/tests/ui/lint/non-local-defs/generics.rs index 0f526526dba21..13e392c510c64 100644 --- a/tests/ui/lint/non-local-defs/generics.rs +++ b/tests/ui/lint/non-local-defs/generics.rs @@ -1,6 +1,8 @@ //@ check-pass //@ edition:2021 +#![warn(non_local_definitions)] + trait Global {} fn main() { diff --git a/tests/ui/lint/non-local-defs/generics.stderr b/tests/ui/lint/non-local-defs/generics.stderr index ed2f87a4ed2d2..35366ed8ecf94 100644 --- a/tests/ui/lint/non-local-defs/generics.stderr +++ b/tests/ui/lint/non-local-defs/generics.stderr @@ -1,5 +1,5 @@ warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/generics.rs:9:5 + --> $DIR/generics.rs:11:5 | LL | impl Global for Vec { } | ^^^^^^^^^^^^^^^------^^^^^---^^^ @@ -10,17 +10,21 @@ LL | impl Global for Vec { } = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` help: move the `impl` block outside of this function `main` - --> $DIR/generics.rs:6:1 + --> $DIR/generics.rs:8:1 | LL | fn main() { | ^^^^^^^^^ LL | trait Local {}; | ----------- may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue - = note: `#[warn(non_local_definitions)]` on by default +note: the lint level is defined here + --> $DIR/generics.rs:4:9 + | +LL | #![warn(non_local_definitions)] + | ^^^^^^^^^^^^^^^^^^^^^ warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/generics.rs:20:5 + --> $DIR/generics.rs:22:5 | LL | impl Uto7 for Test where Local: std::any::Any {} | ^^^^^----^^^^^---- @@ -31,7 +35,7 @@ LL | impl Uto7 for Test where Local: std::any::Any {} = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` help: move the `impl` block outside of this function `bad` - --> $DIR/generics.rs:18:1 + --> $DIR/generics.rs:20:1 | LL | fn bad() { | ^^^^^^^^ @@ -40,7 +44,7 @@ LL | struct Local; = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/generics.rs:23:5 + --> $DIR/generics.rs:25:5 | LL | fn bad() { | -------- move the `impl` block outside of this function `bad` @@ -56,7 +60,7 @@ LL | impl Uto8 for T {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/generics.rs:32:5 + --> $DIR/generics.rs:34:5 | LL | impl Default for UwU { | ^^^^^-------^^^^^---^^^^^ @@ -67,7 +71,7 @@ LL | impl Default for UwU { = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` help: move the `impl` block outside of this function `fun` - --> $DIR/generics.rs:29:1 + --> $DIR/generics.rs:31:1 | LL | fn fun() { | ^^^^^^^^ @@ -77,7 +81,7 @@ LL | struct OwO; = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/generics.rs:43:5 + --> $DIR/generics.rs:45:5 | LL | impl AsRef for () { | ^^^^^-----^^^^^^^^^^-- @@ -88,7 +92,7 @@ LL | impl AsRef for () { = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` help: move the `impl` block outside of this function `meow` - --> $DIR/generics.rs:40:1 + --> $DIR/generics.rs:42:1 | LL | fn meow() { | ^^^^^^^^^ @@ -98,7 +102,7 @@ LL | struct Cat; = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/generics.rs:54:5 + --> $DIR/generics.rs:56:5 | LL | impl PartialEq for G { | ^^^^^---------^^^^^^^^- @@ -109,7 +113,7 @@ LL | impl PartialEq for G { = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` help: move the `impl` block outside of this function `fun2` - --> $DIR/generics.rs:51:1 + --> $DIR/generics.rs:53:1 | LL | fn fun2() { | ^^^^^^^^^ @@ -119,7 +123,7 @@ LL | struct B; = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/generics.rs:69:5 + --> $DIR/generics.rs:71:5 | LL | impl From>> for () { | ^^^^^----^^^^^^^^^^^^^^^^^^^^^^^-- @@ -129,7 +133,7 @@ LL | impl From>> for () { = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` help: move the `impl` block outside of this function `rawr` - --> $DIR/generics.rs:66:1 + --> $DIR/generics.rs:68:1 | LL | fn rawr() { | ^^^^^^^^^ @@ -138,7 +142,7 @@ LL | struct Lion; = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/generics.rs:76:5 + --> $DIR/generics.rs:78:5 | LL | impl From<()> for Wrap { | ^^^^^----^^^^^^^^^----^^^^^^ @@ -149,7 +153,7 @@ LL | impl From<()> for Wrap { = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` help: move the `impl` block outside of this function `rawr` - --> $DIR/generics.rs:66:1 + --> $DIR/generics.rs:68:1 | LL | fn rawr() { | ^^^^^^^^^ diff --git a/tests/ui/lint/non-local-defs/inside-macro_rules.rs b/tests/ui/lint/non-local-defs/inside-macro_rules.rs index 9f21cc89852e2..744a1f7a6f1ab 100644 --- a/tests/ui/lint/non-local-defs/inside-macro_rules.rs +++ b/tests/ui/lint/non-local-defs/inside-macro_rules.rs @@ -1,6 +1,8 @@ //@ check-pass //@ edition:2021 +#![warn(non_local_definitions)] + macro_rules! m { () => { trait MacroTrait {} diff --git a/tests/ui/lint/non-local-defs/inside-macro_rules.stderr b/tests/ui/lint/non-local-defs/inside-macro_rules.stderr index fa9ba2cb785d9..89835372c8a53 100644 --- a/tests/ui/lint/non-local-defs/inside-macro_rules.stderr +++ b/tests/ui/lint/non-local-defs/inside-macro_rules.stderr @@ -1,5 +1,5 @@ warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/inside-macro_rules.rs:9:13 + --> $DIR/inside-macro_rules.rs:11:13 | LL | fn my_func() { | ------------ move the `impl` block outside of this function `my_func` @@ -16,7 +16,11 @@ LL | m!(); = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue - = note: `#[warn(non_local_definitions)]` on by default +note: the lint level is defined here + --> $DIR/inside-macro_rules.rs:4:9 + | +LL | #![warn(non_local_definitions)] + | ^^^^^^^^^^^^^^^^^^^^^ = note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) warning: 1 warning emitted diff --git a/tests/ui/lint/non-local-defs/local.rs b/tests/ui/lint/non-local-defs/local.rs index 166ee88c0210c..e9dbff1300f28 100644 --- a/tests/ui/lint/non-local-defs/local.rs +++ b/tests/ui/lint/non-local-defs/local.rs @@ -1,6 +1,8 @@ //@ check-pass //@ edition:2021 +#![warn(non_local_definitions)] + use std::fmt::Debug; trait GlobalTrait {} diff --git a/tests/ui/lint/non-local-defs/macro_rules.rs b/tests/ui/lint/non-local-defs/macro_rules.rs index ed30a24903d01..20672cf0a3225 100644 --- a/tests/ui/lint/non-local-defs/macro_rules.rs +++ b/tests/ui/lint/non-local-defs/macro_rules.rs @@ -3,6 +3,8 @@ //@ aux-build:non_local_macro.rs //@ rustc-env:CARGO_CRATE_NAME=non_local_def +#![warn(non_local_definitions)] + extern crate non_local_macro; const B: u32 = { diff --git a/tests/ui/lint/non-local-defs/macro_rules.stderr b/tests/ui/lint/non-local-defs/macro_rules.stderr index 4e86fc7b987e6..f9995bf82183c 100644 --- a/tests/ui/lint/non-local-defs/macro_rules.stderr +++ b/tests/ui/lint/non-local-defs/macro_rules.stderr @@ -1,5 +1,5 @@ warning: non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module - --> $DIR/macro_rules.rs:10:5 + --> $DIR/macro_rules.rs:12:5 | LL | macro_rules! m0 { () => { } }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,10 +7,14 @@ LL | macro_rules! m0 { () => { } }; = help: remove the `#[macro_export]` or move this `macro_rules!` outside the of the current constant `B` = note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue - = note: `#[warn(non_local_definitions)]` on by default +note: the lint level is defined here + --> $DIR/macro_rules.rs:6:9 + | +LL | #![warn(non_local_definitions)] + | ^^^^^^^^^^^^^^^^^^^^^ warning: non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module - --> $DIR/macro_rules.rs:16:1 + --> $DIR/macro_rules.rs:18:1 | LL | non_local_macro::non_local_macro_rules!(my_macro); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -22,7 +26,7 @@ LL | non_local_macro::non_local_macro_rules!(my_macro); = note: this warning originates in the macro `non_local_macro::non_local_macro_rules` (in Nightly builds, run with -Z macro-backtrace for more info) warning: non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module - --> $DIR/macro_rules.rs:21:5 + --> $DIR/macro_rules.rs:23:5 | LL | macro_rules! m { () => { } }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -32,7 +36,7 @@ LL | macro_rules! m { () => { } }; = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module - --> $DIR/macro_rules.rs:29:13 + --> $DIR/macro_rules.rs:31:13 | LL | macro_rules! m2 { () => { } }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/non-local-defs/suggest-moving-inner.rs b/tests/ui/lint/non-local-defs/suggest-moving-inner.rs index 61b32e5bad9fe..9360ace4d805b 100644 --- a/tests/ui/lint/non-local-defs/suggest-moving-inner.rs +++ b/tests/ui/lint/non-local-defs/suggest-moving-inner.rs @@ -1,5 +1,7 @@ //@ check-pass +#![warn(non_local_definitions)] + trait Trait {} fn main() { diff --git a/tests/ui/lint/non-local-defs/suggest-moving-inner.stderr b/tests/ui/lint/non-local-defs/suggest-moving-inner.stderr index f0de0f72e74f6..a214415316f84 100644 --- a/tests/ui/lint/non-local-defs/suggest-moving-inner.stderr +++ b/tests/ui/lint/non-local-defs/suggest-moving-inner.stderr @@ -1,5 +1,5 @@ warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/suggest-moving-inner.rs:12:5 + --> $DIR/suggest-moving-inner.rs:14:5 | LL | impl Trait for &Vec> | ^^^^^^^^-----^^^^^^^^^^^^^^^^^---------------------------------- @@ -10,7 +10,7 @@ LL | impl Trait for &Vec> = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` help: move the `impl` block outside of this function `main` - --> $DIR/suggest-moving-inner.rs:5:1 + --> $DIR/suggest-moving-inner.rs:7:1 | LL | fn main() { | ^^^^^^^^^ @@ -23,7 +23,11 @@ LL | struct InsideMain; LL | trait HasFoo {} | ------------ may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue - = note: `#[warn(non_local_definitions)]` on by default +note: the lint level is defined here + --> $DIR/suggest-moving-inner.rs:3:9 + | +LL | #![warn(non_local_definitions)] + | ^^^^^^^^^^^^^^^^^^^^^ warning: 1 warning emitted diff --git a/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.rs b/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.rs index 4291426e046a8..b726398bf9c9a 100644 --- a/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.rs +++ b/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.rs @@ -3,6 +3,8 @@ // https://github.com/rust-lang/rust/issues/123573#issue-2229428739 +#![warn(non_local_definitions)] + pub trait Test {} impl<'a, T: 'a> Test for &[T] where &'a T: Test {} diff --git a/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr b/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr index 80930ce1bcdf3..2eb71cecacaaf 100644 --- a/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr +++ b/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr @@ -1,5 +1,5 @@ warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/trait-solver-overflow-123573.rs:12:5 + --> $DIR/trait-solver-overflow-123573.rs:14:5 | LL | impl Test for &Local {} | ^^^^^----^^^^^------ @@ -11,14 +11,18 @@ LL | impl Test for &Local {} = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` help: move the `impl` block outside of this function `main` - --> $DIR/trait-solver-overflow-123573.rs:10:1 + --> $DIR/trait-solver-overflow-123573.rs:12:1 | LL | fn main() { | ^^^^^^^^^ LL | struct Local {} | ------------ may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue - = note: `#[warn(non_local_definitions)]` on by default +note: the lint level is defined here + --> $DIR/trait-solver-overflow-123573.rs:6:9 + | +LL | #![warn(non_local_definitions)] + | ^^^^^^^^^^^^^^^^^^^^^ warning: 1 warning emitted diff --git a/tests/ui/lint/non-local-defs/weird-exprs.rs b/tests/ui/lint/non-local-defs/weird-exprs.rs index 1d9cecea0c971..fbf1fd941eecb 100644 --- a/tests/ui/lint/non-local-defs/weird-exprs.rs +++ b/tests/ui/lint/non-local-defs/weird-exprs.rs @@ -1,6 +1,8 @@ //@ check-pass //@ edition:2021 +#![warn(non_local_definitions)] + trait Uto {} struct Test; diff --git a/tests/ui/lint/non-local-defs/weird-exprs.stderr b/tests/ui/lint/non-local-defs/weird-exprs.stderr index cd414d636d34b..49aba904ebb0e 100644 --- a/tests/ui/lint/non-local-defs/weird-exprs.stderr +++ b/tests/ui/lint/non-local-defs/weird-exprs.stderr @@ -1,5 +1,5 @@ warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/weird-exprs.rs:8:5 + --> $DIR/weird-exprs.rs:10:5 | LL | type A = [u32; { | ________________- @@ -16,10 +16,14 @@ LL | | }]; = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue - = note: `#[warn(non_local_definitions)]` on by default +note: the lint level is defined here + --> $DIR/weird-exprs.rs:4:9 + | +LL | #![warn(non_local_definitions)] + | ^^^^^^^^^^^^^^^^^^^^^ warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/weird-exprs.rs:16:9 + --> $DIR/weird-exprs.rs:18:9 | LL | Discr = { | _____________- @@ -38,7 +42,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/weird-exprs.rs:25:9 + --> $DIR/weird-exprs.rs:27:9 | LL | let _array = [0i32; { | _________________________- @@ -57,7 +61,7 @@ LL | | }]; = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/weird-exprs.rs:34:9 + --> $DIR/weird-exprs.rs:36:9 | LL | type A = [u32; { | ____________________- @@ -76,7 +80,7 @@ LL | | }]; = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/weird-exprs.rs:41:9 + --> $DIR/weird-exprs.rs:43:9 | LL | fn a(_: [u32; { | ___________________- @@ -95,7 +99,7 @@ LL | | }]) {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/weird-exprs.rs:48:9 + --> $DIR/weird-exprs.rs:50:9 | LL | fn b() -> [u32; { | _____________________- diff --git a/tests/ui/lint/reasons-erroneous.rs b/tests/ui/lint/reasons-erroneous.rs index 244b376b60d88..0aa46953bf1ac 100644 --- a/tests/ui/lint/reasons-erroneous.rs +++ b/tests/ui/lint/reasons-erroneous.rs @@ -9,7 +9,7 @@ #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] //~^ ERROR malformed lint attribute //~| NOTE bad attribute argument -#![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")] +#![warn(unsafe_code, blerp = "or in league with robbers have reversed the signposts")] //~^ ERROR malformed lint attribute //~| NOTE bad attribute argument #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] diff --git a/tests/ui/lint/reasons-erroneous.stderr b/tests/ui/lint/reasons-erroneous.stderr index adc97174b99cd..fcff88d8e0fa7 100644 --- a/tests/ui/lint/reasons-erroneous.stderr +++ b/tests/ui/lint/reasons-erroneous.stderr @@ -17,10 +17,10 @@ LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides thei | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:12:23 + --> $DIR/reasons-erroneous.rs:12:22 | -LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument +LL | #![warn(unsafe_code, blerp = "or in league with robbers have reversed the signposts")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument error[E0452]: malformed lint attribute input --> $DIR/reasons-erroneous.rs:15:36 diff --git a/tests/ui/macros/out-of-scope-macro-calls-lint-registered.rs b/tests/ui/macros/out-of-scope-macro-calls-lint-registered.rs new file mode 100644 index 0000000000000..0736c373d576e --- /dev/null +++ b/tests/ui/macros/out-of-scope-macro-calls-lint-registered.rs @@ -0,0 +1,6 @@ +//@ check-pass + +#![deny(unknown_lints)] +#![allow(out_of_scope_macro_calls)] + +fn main() {} diff --git a/tests/ui/mir/auxiliary/static_fnptr.rs b/tests/ui/mir/auxiliary/static_fnptr.rs new file mode 100644 index 0000000000000..8c7347175f4b8 --- /dev/null +++ b/tests/ui/mir/auxiliary/static_fnptr.rs @@ -0,0 +1,11 @@ +//@ compile-flags:-O + +#[inline] +fn foo() {} + +pub static ADDR: fn() = foo; + +#[inline(always)] +pub fn bar(x: fn()) -> bool { + x == ADDR +} diff --git a/tests/crashes/116721.rs b/tests/ui/mir/sized-slice-predicate-116721.rs similarity index 82% rename from tests/crashes/116721.rs rename to tests/ui/mir/sized-slice-predicate-116721.rs index fc1a6530bc82b..c6a0aca2da80d 100644 --- a/tests/crashes/116721.rs +++ b/tests/ui/mir/sized-slice-predicate-116721.rs @@ -1,5 +1,6 @@ -//@ known-bug: #116721 +//@ build-pass //@ compile-flags: -Zmir-opt-level=3 --emit=mir + fn hey(it: &[T]) where [T]: Clone, diff --git a/tests/ui/mir/static_fnptr.rs b/tests/ui/mir/static_fnptr.rs new file mode 100644 index 0000000000000..6b1ec021629b8 --- /dev/null +++ b/tests/ui/mir/static_fnptr.rs @@ -0,0 +1,21 @@ +//! Verify that we correctly handle fn pointer provenance in MIR optimizations. +//! By asking to inline `static_fnptr::bar`, we have two copies of `static_fnptr::foo`, one in the +//! auxiliary crate and one in the local crate CGU. +//! `baz` must only consider the versions from upstream crate, and not try to compare with the +//! address of the CGU-local copy. +//! Related issue: #123670 + +//@ run-pass +//@ compile-flags:-Cno-prepopulate-passes -Copt-level=0 +//@ aux-build:static_fnptr.rs + +extern crate static_fnptr; +use static_fnptr::{ADDR, bar}; + +fn baz() -> bool { + bar(ADDR) +} + +fn main() { + assert!(baz()) +} diff --git a/tests/ui/parser/impls-nested-within-fns-semantic-1.rs b/tests/ui/parser/impls-nested-within-fns-semantic-1.rs index 0e95fc757f3e8..92823b05af840 100644 --- a/tests/ui/parser/impls-nested-within-fns-semantic-1.rs +++ b/tests/ui/parser/impls-nested-within-fns-semantic-1.rs @@ -1,7 +1,9 @@ // Regression test for part of issue #119924. //@ check-pass +//@ compile-flags: -Znext-solver -#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] #[const_trait] trait Trait { diff --git a/tests/ui/parser/impls-nested-within-fns-semantic-1.stderr b/tests/ui/parser/impls-nested-within-fns-semantic-1.stderr deleted file mode 100644 index 6670b3772db12..0000000000000 --- a/tests/ui/parser/impls-nested-within-fns-semantic-1.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/impls-nested-within-fns-semantic-1.rs:4:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/parser/unsafe-foreign-mod-2.stderr b/tests/ui/parser/unsafe-foreign-mod-2.stderr index 77a383d5efa26..8bd592b5d4311 100644 --- a/tests/ui/parser/unsafe-foreign-mod-2.stderr +++ b/tests/ui/parser/unsafe-foreign-mod-2.stderr @@ -9,17 +9,16 @@ error: extern block cannot be declared unsafe | LL | extern "C" unsafe { | ^^^^^^ + | + = note: see issue #123743 for more information + = help: add `#![feature(unsafe_extern_blocks)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: items in unadorned `extern` blocks cannot have safety qualifiers --> $DIR/unsafe-foreign-mod-2.rs:4:5 | LL | unsafe fn foo(); | ^^^^^^^^^^^^^^^^ - | -help: add unsafe to this `extern` block - | -LL | unsafe extern "C" unsafe { - | ++++++ error: aborting due to 3 previous errors diff --git a/tests/ui/parser/unsafe-foreign-mod.stderr b/tests/ui/parser/unsafe-foreign-mod.stderr index 77f6e93be10bb..60b918a89b34d 100644 --- a/tests/ui/parser/unsafe-foreign-mod.stderr +++ b/tests/ui/parser/unsafe-foreign-mod.stderr @@ -3,6 +3,10 @@ error: extern block cannot be declared unsafe | LL | unsafe extern "C" { | ^^^^^^ + | + = note: see issue #123743 for more information + = help: add `#![feature(unsafe_extern_blocks)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 1 previous error diff --git a/tests/ui/return/infer-return-ty-for-fn-sig-issue-125488.fixed b/tests/ui/return/infer-return-ty-for-fn-sig-issue-125488.fixed new file mode 100644 index 0000000000000..442ade6abf16d --- /dev/null +++ b/tests/ui/return/infer-return-ty-for-fn-sig-issue-125488.fixed @@ -0,0 +1,33 @@ +//@ run-rustfix + +#[allow(dead_code)] + +fn main() { + struct S<'a>(&'a ()); + + fn f1(s: S<'_>) -> S<'_> { + //~^ ERROR the placeholder `_` is not allowed + s + } + + fn f2(s: S<'_>) -> S<'_> { + //~^ ERROR the placeholder `_` is not allowed + let x = true; + if x { + s + } else { + s + } + } + + fn f3(s: S<'_>) -> S<'_> { + //~^ ERROR the placeholder `_` is not allowed + return s; + } + + fn f4(s: S<'_>) -> S<'_> { + //~^ ERROR the placeholder `_` is not allowed + let _x = 1; + return s; + } +} diff --git a/tests/ui/return/infer-return-ty-for-fn-sig-issue-125488.rs b/tests/ui/return/infer-return-ty-for-fn-sig-issue-125488.rs new file mode 100644 index 0000000000000..04ea3a28addfb --- /dev/null +++ b/tests/ui/return/infer-return-ty-for-fn-sig-issue-125488.rs @@ -0,0 +1,33 @@ +//@ run-rustfix + +#[allow(dead_code)] + +fn main() { + struct S<'a>(&'a ()); + + fn f1(s: S<'_>) -> _ { + //~^ ERROR the placeholder `_` is not allowed + s + } + + fn f2(s: S<'_>) -> _ { + //~^ ERROR the placeholder `_` is not allowed + let x = true; + if x { + s + } else { + s + } + } + + fn f3(s: S<'_>) -> _ { + //~^ ERROR the placeholder `_` is not allowed + return s; + } + + fn f4(s: S<'_>) -> _ { + //~^ ERROR the placeholder `_` is not allowed + let _x = 1; + return s; + } +} diff --git a/tests/ui/return/infer-return-ty-for-fn-sig-issue-125488.stderr b/tests/ui/return/infer-return-ty-for-fn-sig-issue-125488.stderr new file mode 100644 index 0000000000000..8b7c5e1681ad1 --- /dev/null +++ b/tests/ui/return/infer-return-ty-for-fn-sig-issue-125488.stderr @@ -0,0 +1,39 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/infer-return-ty-for-fn-sig-issue-125488.rs:8:24 + | +LL | fn f1(s: S<'_>) -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with the correct return type: `S<'_>` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/infer-return-ty-for-fn-sig-issue-125488.rs:13:24 + | +LL | fn f2(s: S<'_>) -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with the correct return type: `S<'_>` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/infer-return-ty-for-fn-sig-issue-125488.rs:23:24 + | +LL | fn f3(s: S<'_>) -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with the correct return type: `S<'_>` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/infer-return-ty-for-fn-sig-issue-125488.rs:28:24 + | +LL | fn f4(s: S<'_>) -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with the correct return type: `S<'_>` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/return/tail-expr-as-potential-return.rs b/tests/ui/return/tail-expr-as-potential-return.rs index 37dee1c19db8c..11ecddb049b57 100644 --- a/tests/ui/return/tail-expr-as-potential-return.rs +++ b/tests/ui/return/tail-expr-as-potential-return.rs @@ -1,3 +1,5 @@ +//@ edition:2018 + // > Suggest returning tail expressions that match return type // > // > Some newcomers are confused by the behavior of tail expressions, @@ -8,24 +10,24 @@ // // This test was amended to also serve as a regression test for #92308, where // this suggestion would not trigger with async functions. -// -//@ edition:2018 fn main() { } fn foo(x: bool) -> Result { if x { - Err(42) //~ ERROR mismatched types - //| HELP you might have meant to return this value + Err(42) + //~^ ERROR mismatched types + //~| HELP you might have meant to return this value } Ok(42.0) } async fn bar(x: bool) -> Result { if x { - Err(42) //~ ERROR mismatched types - //| HELP you might have meant to return this value + Err(42) + //~^ ERROR mismatched types + //~| HELP you might have meant to return this value } Ok(42.0) } @@ -40,8 +42,26 @@ impl Identity for T { async fn foo2() -> i32 { if true { - 1i32 //~ ERROR mismatched types - //| HELP you might have meant to return this value + 1i32 + //~^ ERROR mismatched types + //~| HELP you might have meant to return this value } 0 } + +struct Receiver; +impl Receiver { + fn generic(self) -> Option { + None + } +} +fn method() -> Option { + if true { + Receiver.generic(); + //~^ ERROR type annotations needed + //~| HELP consider specifying the generic argument + //~| HELP you might have meant to return this to infer its type parameters + } + + None +} diff --git a/tests/ui/return/tail-expr-as-potential-return.stderr b/tests/ui/return/tail-expr-as-potential-return.stderr index ccb208fc6c4ae..635a9e06633ff 100644 --- a/tests/ui/return/tail-expr-as-potential-return.stderr +++ b/tests/ui/return/tail-expr-as-potential-return.stderr @@ -1,10 +1,11 @@ error[E0308]: mismatched types - --> $DIR/tail-expr-as-potential-return.rs:27:9 + --> $DIR/tail-expr-as-potential-return.rs:28:9 | LL | / if x { LL | | Err(42) | | ^^^^^^^ expected `()`, found `Result<_, {integer}>` -LL | | //| HELP you might have meant to return this value +LL | | +LL | | LL | | } | |_____- expected this to be `()` | @@ -16,12 +17,13 @@ LL | return Err(42); | ++++++ + error[E0308]: mismatched types - --> $DIR/tail-expr-as-potential-return.rs:43:9 + --> $DIR/tail-expr-as-potential-return.rs:45:9 | LL | / if true { LL | | 1i32 | | ^^^^ expected `()`, found `i32` -LL | | //| HELP you might have meant to return this value +LL | | +LL | | LL | | } | |_____- expected this to be `()` | @@ -36,7 +38,8 @@ error[E0308]: mismatched types LL | / if x { LL | | Err(42) | | ^^^^^^^ expected `()`, found `Result<_, {integer}>` -LL | | //| HELP you might have meant to return this value +LL | | +LL | | LL | | } | |_____- expected this to be `()` | @@ -47,6 +50,22 @@ help: you might have meant to return this value LL | return Err(42); | ++++++ + -error: aborting due to 3 previous errors +error[E0282]: type annotations needed + --> $DIR/tail-expr-as-potential-return.rs:60:18 + | +LL | Receiver.generic(); + | ^^^^^^^ cannot infer type of the type parameter `T` declared on the method `generic` + | +help: consider specifying the generic argument + | +LL | Receiver.generic::(); + | +++++ +help: you might have meant to return this to infer its type parameters + | +LL | return Receiver.generic(); + | ++++++ + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0282, E0308. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.qualified.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.qualified.stderr deleted file mode 100644 index 3aec4383eab3a..0000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.qualified.stderr +++ /dev/null @@ -1,23 +0,0 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/assoc-type-const-bound-usage-0.rs:6:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - -error[E0277]: the trait bound `T: Trait` is not satisfied - --> $DIR/assoc-type-const-bound-usage-0.rs:21:6 - | -LL | ::Assoc::func() - | ^ the trait `Trait` is not implemented for `T` - | -help: consider further restricting this bound - | -LL | const fn qualified() -> i32 { - | +++++++ - -error: aborting due to 1 previous error; 1 warning emitted - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.rs index eecd6e6109c1e..4399ae2d1be32 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.rs @@ -1,9 +1,7 @@ -// FIXME(effects): Collapse the revisions into one once we support `::Proj`. -//@ revisions: unqualified qualified -//@[unqualified] check-pass -//@[qualified] known-bug: unknown +//@ known-bug: unknown -#![feature(const_trait_impl, effects)] //[unqualified]~ WARN the feature `effects` is incomplete +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] #[const_trait] trait Trait { @@ -11,14 +9,12 @@ trait Trait { fn func() -> i32; } -#[cfg(unqualified)] const fn unqualified() -> i32 { T::Assoc::func() } -#[cfg(qualified)] const fn qualified() -> i32 { - ::Assoc::func() + ::Assoc::func() } fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.stderr new file mode 100644 index 0000000000000..fb491453b379b --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.stderr @@ -0,0 +1,38 @@ +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error[E0277]: the trait bound `Trait::{synthetic#0}: Compat` is not satisfied + --> $DIR/assoc-type-const-bound-usage-0.rs:13:5 + | +LL | T::Assoc::func() + | ^^^^^^^^ the trait `Compat` is not implemented for `Trait::{synthetic#0}` + | +note: required by a bound in `Trait::func` + --> $DIR/assoc-type-const-bound-usage-0.rs:6:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ required by this bound in `Trait::func` +... +LL | fn func() -> i32; + | ---- required by a bound in this associated function + +error[E0277]: the trait bound `Trait::{synthetic#0}: Compat` is not satisfied + --> $DIR/assoc-type-const-bound-usage-0.rs:17:5 + | +LL | ::Assoc::func() + | ^^^^^^^^^^^^^^^^^^^ the trait `Compat` is not implemented for `Trait::{synthetic#0}` + | +note: required by a bound in `Trait::func` + --> $DIR/assoc-type-const-bound-usage-0.rs:6:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ required by this bound in `Trait::func` +... +LL | fn func() -> i32; + | ---- required by a bound in this associated function + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.unqualified.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.unqualified.stderr deleted file mode 100644 index 3d592834600e0..0000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.unqualified.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/assoc-type-const-bound-usage-0.rs:6:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-1.qualified.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-1.qualified.stderr deleted file mode 100644 index 10e467da9521a..0000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-1.qualified.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0277]: the trait bound `T: Trait` is not satisfied - --> $DIR/assoc-type-const-bound-usage-1.rs:23:43 - | -LL | fn qualified() -> Type<{ ::Assoc::func() }> { - | ^ the trait `Trait` is not implemented for `T` - | -help: consider further restricting this bound - | -LL | fn qualified() -> Type<{ ::Assoc::func() }> { - | +++++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-1.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-1.rs index 8213dae136959..8a1bf75f87e1a 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-1.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-1.rs @@ -1,7 +1,5 @@ -// FIXME(effects): Collapse the revisions into one once we support `::Proj`. -//@ revisions: unqualified qualified -//@[unqualified] check-pass -//@[qualified] known-bug: unknown +//@ known-bug: unknown +// FIXME(effects) #![feature(const_trait_impl, effects, generic_const_exprs)] #![allow(incomplete_features)] @@ -14,13 +12,11 @@ trait Trait { struct Type; -#[cfg(unqualified)] fn unqualified() -> Type<{ T::Assoc::func() }> { Type } -#[cfg(qualified)] -fn qualified() -> Type<{ ::Assoc::func() }> { +fn qualified() -> Type<{ ::Assoc::func() }> { Type } diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-1.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-1.stderr new file mode 100644 index 0000000000000..392b310a4c99e --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-1.stderr @@ -0,0 +1,38 @@ +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error[E0277]: the trait bound `Trait::{synthetic#0}: Compat` is not satisfied + --> $DIR/assoc-type-const-bound-usage-1.rs:15:44 + | +LL | fn unqualified() -> Type<{ T::Assoc::func() }> { + | ^^^^^^^^ the trait `Compat` is not implemented for `Trait::{synthetic#0}` + | +note: required by a bound in `Trait::func` + --> $DIR/assoc-type-const-bound-usage-1.rs:7:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ required by this bound in `Trait::func` +... +LL | fn func() -> i32; + | ---- required by a bound in this associated function + +error[E0277]: the trait bound `Trait::{synthetic#0}: Compat` is not satisfied + --> $DIR/assoc-type-const-bound-usage-1.rs:19:42 + | +LL | fn qualified() -> Type<{ ::Assoc::func() }> { + | ^^^^^^^^^^^^^^^^^^^ the trait `Compat` is not implemented for `Trait::{synthetic#0}` + | +note: required by a bound in `Trait::func` + --> $DIR/assoc-type-const-bound-usage-1.rs:7:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ required by this bound in `Trait::func` +... +LL | fn func() -> i32; + | ---- required by a bound in this associated function + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs index 645fff4e01471..348bf839b6995 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs @@ -32,12 +32,14 @@ trait Foo { } impl const Foo for NonConstAdd { - type Bar = NonConstAdd; //~ ERROR the trait bound `NonConstAdd: ~const Add` is not satisfied + type Bar = NonConstAdd; + // FIXME(effects) ERROR the trait bound `NonConstAdd: ~const Add` is not satisfied } #[const_trait] trait Baz { type Qux: Add; + //~^ ERROR the trait bound } impl const Baz for NonConstAdd { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr index cc3abea25eb56..405212b52c7c7 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr @@ -7,19 +7,22 @@ LL | #![feature(const_trait_impl, effects)] = note: see issue #102090 for more information = note: `#[warn(incomplete_features)]` on by default -error[E0277]: the trait bound `NonConstAdd: ~const Add` is not satisfied - --> $DIR/assoc-type.rs:35:16 +error: using `#![feature(effects)]` without enabling next trait solver globally | -LL | type Bar = NonConstAdd; - | ^^^^^^^^^^^ the trait `~const Add` is not implemented for `NonConstAdd` + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error[E0277]: the trait bound `Add::{synthetic#0}: Compat` is not satisfied + --> $DIR/assoc-type.rs:41:15 + | +LL | type Qux: Add; + | ^^^ the trait `Compat` is not implemented for `Add::{synthetic#0}` | - = help: the trait `Add` is implemented for `NonConstAdd` -note: required by a bound in `Foo::Bar` - --> $DIR/assoc-type.rs:31:15 +help: consider further restricting the associated type | -LL | type Bar: ~const Add; - | ^^^^^^^^^^ required by this bound in `Foo::Bar` +LL | trait Baz where Add::{synthetic#0}: Compat { + | ++++++++++++++++++++++++++++++++ -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 2 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs index 62609384cff08..8f63cd1d521ed 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs @@ -1,4 +1,6 @@ -#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] #[const_trait] pub trait MyTrait { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/auxiliary/staged-api.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/auxiliary/staged-api.rs index fd4e1ff803da6..986165ef91e6c 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/auxiliary/staged-api.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/auxiliary/staged-api.rs @@ -1,4 +1,6 @@ -#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] #![feature(staged_api)] #![stable(feature = "rust1", since = "1.0.0")] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr index 0e4dcf0f3026a..73ea1422bf9d7 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr @@ -7,14 +7,27 @@ LL | #![feature(const_trait_impl, effects)] = note: see issue #102090 for more information = note: `#[warn(incomplete_features)]` on by default -error[E0277]: the trait bound `u32: ~const Plus` is not satisfied +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error[E0277]: the trait bound `Runtime: ~const Compat` is not satisfied --> $DIR/call-const-trait-method-fail.rs:25:5 | LL | a.plus(b) - | ^ the trait `~const Plus` is not implemented for `u32` + | ^ the trait `~const Compat` is not implemented for `Runtime` + | + = help: the trait `Compat` is implemented for `Runtime` +note: required by a bound in `Plus::plus` + --> $DIR/call-const-trait-method-fail.rs:3:1 | - = help: the trait `Plus` is implemented for `u32` +LL | #[const_trait] + | ^^^^^^^^^^^^^^ required by this bound in `Plus::plus` +LL | pub trait Plus { +LL | fn plus(self, rhs: Self) -> Self; + | ---- required by a bound in this associated function -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 2 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-pass.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-pass.stderr index 22e8e692752cc..bf455a714a343 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-pass.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-pass.stderr @@ -1,20 +1,66 @@ +error: const `impl` for trait `Add` which is not marked with `#[const_trait]` + --> $DIR/call-const-trait-method-pass.rs:7:12 + | +LL | impl const std::ops::Add for Int { + | ^^^^^^^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` + --> $DIR/call-const-trait-method-pass.rs:15:12 + | +LL | impl const PartialEq for Int { + | ^^^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error[E0049]: method `plus` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/call-const-trait-method-pass.rs:24:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | pub trait Plus { +LL | fn plus(self, rhs: Self) -> Self; + | - expected 0 const parameters + error[E0015]: cannot call non-const operator in constants --> $DIR/call-const-trait-method-pass.rs:39:22 | LL | const ADD_INT: Int = Int(1i32) + Int(2i32); | ^^^^^^^^^^^^^^^^^^^^^ | -note: impl defined here, but it is not `const` - --> $DIR/call-const-trait-method-pass.rs:7:1 - | -LL | impl const std::ops::Add for Int { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: calls in constants are limited to constant functions, tuple structs and tuple variants help: add `#![feature(effects)]` to the crate attributes to enable | LL + #![feature(effects)] | +error[E0015]: cannot call non-const fn `::plus` in constant functions + --> $DIR/call-const-trait-method-pass.rs:11:20 + | +LL | Int(self.0.plus(rhs.0)) + | ^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + +error[E0015]: cannot call non-const fn `::eq` in constant functions + --> $DIR/call-const-trait-method-pass.rs:20:15 + | +LL | !self.eq(other) + | ^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + error[E0015]: cannot call non-const fn `::plus` in constant functions --> $DIR/call-const-trait-method-pass.rs:36:7 | @@ -27,6 +73,7 @@ help: add `#![feature(effects)]` to the crate attributes to enable LL + #![feature(effects)] | -error: aborting due to 2 previous errors +error: aborting due to 7 previous errors -For more information about this error, try `rustc --explain E0015`. +Some errors have detailed explanations: E0015, E0049. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.stderr index 12027c4d71362..5cd274c6c5a22 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.stderr @@ -4,5 +4,28 @@ error: `~const` can only be applied to `#[const_trait]` traits LL | impl const MyPartialEq for T { | ^^^^^^^^^ -error: aborting due to 1 previous error +error[E0049]: method `eq` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/call-generic-in-impl.rs:5:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait MyPartialEq { +LL | fn eq(&self, other: &Self) -> bool; + | - expected 0 const parameters + +error[E0015]: cannot call non-const fn `::eq` in constant functions + --> $DIR/call-generic-in-impl.rs:12:9 + | +LL | PartialEq::eq(self, other) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + +error: aborting due to 3 previous errors +Some errors have detailed explanations: E0015, E0049. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-chain.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-chain.stderr index 36c7a6544305b..57d57dfd5b935 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-chain.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-chain.stderr @@ -7,6 +7,11 @@ LL | #![feature(const_trait_impl, effects)] = note: see issue #102090 for more information = note: `#[warn(incomplete_features)]` on by default +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` --> $DIR/call-generic-method-chain.rs:10:12 | @@ -16,15 +21,6 @@ LL | impl const PartialEq for S { = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change -error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates - --> $DIR/call-generic-method-chain.rs:10:6 - | -LL | impl const PartialEq for S { - | ^^^^^ unconstrained const parameter - | - = note: expressions using a const parameter must map each value to a distinct output value - = note: proving the result of expressions other than the parameter are unique is not supported - error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/call-generic-method-chain.rs:19:32 | @@ -37,35 +33,5 @@ error: `~const` can only be applied to `#[const_trait]` traits LL | const fn equals_self_wrapper(t: &T) -> bool { | ^^^^^^^^^ -error[E0284]: type annotations needed - --> $DIR/call-generic-method-chain.rs:27:22 - | -LL | pub const EQ: bool = equals_self_wrapper(&S); - | ^^^^^^^^^^^^^^^^^^^^^^^ cannot infer the value of the constant `_` - | -note: required for `S` to implement `PartialEq` - --> $DIR/call-generic-method-chain.rs:10:12 - | -LL | impl const PartialEq for S { - | ----- ^^^^^^^^^ ^ - | | - | unsatisfied trait bound introduced here - -error[E0284]: type annotations needed - --> $DIR/call-generic-method-chain.rs:15:10 - | -LL | !self.eq(other) - | ^^^^^^^^^^^^^^ cannot infer the value of the constant `_` - | -note: required for `S` to implement `PartialEq` - --> $DIR/call-generic-method-chain.rs:10:12 - | -LL | impl const PartialEq for S { - | ----- ^^^^^^^^^ ^ - | | - | unsatisfied trait bound introduced here - -error: aborting due to 6 previous errors; 1 warning emitted +error: aborting due to 4 previous errors; 1 warning emitted -Some errors have detailed explanations: E0207, E0284. -For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-dup-bound.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-dup-bound.stderr index 320e420b80a30..0088ed2eb13db 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-dup-bound.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-dup-bound.stderr @@ -7,6 +7,11 @@ LL | #![feature(const_trait_impl, effects)] = note: see issue #102090 for more information = note: `#[warn(incomplete_features)]` on by default +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` --> $DIR/call-generic-method-dup-bound.rs:8:12 | @@ -16,15 +21,6 @@ LL | impl const PartialEq for S { = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change -error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates - --> $DIR/call-generic-method-dup-bound.rs:8:6 - | -LL | impl const PartialEq for S { - | ^^^^^ unconstrained const parameter - | - = note: expressions using a const parameter must map each value to a distinct output value - = note: proving the result of expressions other than the parameter are unique is not supported - error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/call-generic-method-dup-bound.rs:19:44 | @@ -37,49 +33,5 @@ error: `~const` can only be applied to `#[const_trait]` traits LL | const fn equals_self2(t: &T) -> bool { | ^^^^^^^^^ -error[E0284]: type annotations needed - --> $DIR/call-generic-method-dup-bound.rs:30:22 - | -LL | pub const EQ: bool = equals_self(&S) && equals_self2(&S); - | ^^^^^^^^^^^^^^^ cannot infer the value of the constant `_` - | -note: required for `S` to implement `PartialEq` - --> $DIR/call-generic-method-dup-bound.rs:8:12 - | -LL | impl const PartialEq for S { - | ----- ^^^^^^^^^ ^ - | | - | unsatisfied trait bound introduced here - -error[E0284]: type annotations needed - --> $DIR/call-generic-method-dup-bound.rs:30:41 - | -LL | pub const EQ: bool = equals_self(&S) && equals_self2(&S); - | ^^^^^^^^^^^^^^^^ cannot infer the value of the constant `_` - | -note: required for `S` to implement `PartialEq` - --> $DIR/call-generic-method-dup-bound.rs:8:12 - | -LL | impl const PartialEq for S { - | ----- ^^^^^^^^^ ^ - | | - | unsatisfied trait bound introduced here - -error[E0284]: type annotations needed - --> $DIR/call-generic-method-dup-bound.rs:13:10 - | -LL | !self.eq(other) - | ^^^^^^^^^^^^^^ cannot infer the value of the constant `_` - | -note: required for `S` to implement `PartialEq` - --> $DIR/call-generic-method-dup-bound.rs:8:12 - | -LL | impl const PartialEq for S { - | ----- ^^^^^^^^^ ^ - | | - | unsatisfied trait bound introduced here - -error: aborting due to 7 previous errors; 1 warning emitted +error: aborting due to 4 previous errors; 1 warning emitted -Some errors have detailed explanations: E0207, E0284. -For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.rs index a9ed5a639d73a..86e0eae61c9ce 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.rs @@ -1,6 +1,7 @@ //@ check-pass - -#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] pub const fn equals_self(t: &T) -> bool { *t == *t diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.stderr deleted file mode 100644 index 74b74052da079..0000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/call-generic-method-fail.rs:3:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs index 222bff2db8807..74e33ca72fffc 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs @@ -21,6 +21,7 @@ const fn equals_self(t: &T) -> bool { // it not using the impl. pub const EQ: bool = equals_self(&S); -//~^ ERROR: the trait bound `S: const Foo` is not satisfied +//~^ ERROR: the trait bound `Runtime: const Compat` is not satisfied +// FIXME(effects) diagnostic fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr index fa59e5ee03dd0..b2a98041c1cdf 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr @@ -7,21 +7,26 @@ LL | #![feature(const_trait_impl, effects)] = note: see issue #102090 for more information = note: `#[warn(incomplete_features)]` on by default -error[E0277]: the trait bound `S: const Foo` is not satisfied +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error[E0277]: the trait bound `Runtime: const Compat` is not satisfied --> $DIR/call-generic-method-nonconst.rs:23:34 | LL | pub const EQ: bool = equals_self(&S); - | ----------- ^^ the trait `const Foo` is not implemented for `S` + | ----------- ^^ the trait `const Compat` is not implemented for `Runtime` | | | required by a bound introduced by this call | - = help: the trait `Foo` is implemented for `S` + = help: the trait `Compat` is implemented for `Runtime` note: required by a bound in `equals_self` --> $DIR/call-generic-method-nonconst.rs:16:25 | LL | const fn equals_self(t: &T) -> bool { | ^^^^^^^^^^ required by this bound in `equals_self` -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 2 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-pass.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-pass.stderr index 6b9d290839e5f..4a6100c3c1aac 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-pass.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-pass.stderr @@ -7,6 +7,11 @@ LL | #![feature(const_trait_impl, effects)] = note: see issue #102090 for more information = note: `#[warn(incomplete_features)]` on by default +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` --> $DIR/call-generic-method-pass.rs:10:12 | @@ -16,50 +21,11 @@ LL | impl const PartialEq for S { = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change -error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates - --> $DIR/call-generic-method-pass.rs:10:6 - | -LL | impl const PartialEq for S { - | ^^^^^ unconstrained const parameter - | - = note: expressions using a const parameter must map each value to a distinct output value - = note: proving the result of expressions other than the parameter are unique is not supported - error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/call-generic-method-pass.rs:19:32 | LL | const fn equals_self(t: &T) -> bool { | ^^^^^^^^^ -error[E0284]: type annotations needed - --> $DIR/call-generic-method-pass.rs:23:22 - | -LL | pub const EQ: bool = equals_self(&S); - | ^^^^^^^^^^^^^^^ cannot infer the value of the constant `_` - | -note: required for `S` to implement `PartialEq` - --> $DIR/call-generic-method-pass.rs:10:12 - | -LL | impl const PartialEq for S { - | ----- ^^^^^^^^^ ^ - | | - | unsatisfied trait bound introduced here - -error[E0284]: type annotations needed - --> $DIR/call-generic-method-pass.rs:15:10 - | -LL | !self.eq(other) - | ^^^^^^^^^^^^^^ cannot infer the value of the constant `_` - | -note: required for `S` to implement `PartialEq` - --> $DIR/call-generic-method-pass.rs:10:12 - | -LL | impl const PartialEq for S { - | ----- ^^^^^^^^^ ^ - | | - | unsatisfied trait bound introduced here - -error: aborting due to 5 previous errors; 1 warning emitted +error: aborting due to 3 previous errors; 1 warning emitted -Some errors have detailed explanations: E0207, E0284. -For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call.rs index 1150d7e1059f1..af2f7caf88c75 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call.rs @@ -1,5 +1,5 @@ //@ check-pass - +//@ compile-flags: -Znext-solver #![feature(const_closures, const_trait_impl, effects)] #![allow(incomplete_features)] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr index 8916450df2d4b..9c1c8df8da459 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr @@ -1,3 +1,21 @@ +error: const `impl` for trait `Add` which is not marked with `#[const_trait]` + --> $DIR/const-and-non-const-impl.rs:7:12 + | +LL | impl const std::ops::Add for i32 { + | ^^^^^^^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: const `impl` for trait `Add` which is not marked with `#[const_trait]` + --> $DIR/const-and-non-const-impl.rs:23:12 + | +LL | impl const std::ops::Add for Int { + | ^^^^^^^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + error[E0119]: conflicting implementations of trait `Add` for type `Int` --> $DIR/const-and-non-const-impl.rs:23:1 | @@ -19,7 +37,7 @@ LL | impl const std::ops::Add for i32 { | = note: define and implement a trait or new type instead -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0117, E0119. For more information about an error, try `rustc --explain E0117`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.rs index 0025449c4921f..099cf0b00d3f7 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.rs @@ -1,4 +1,5 @@ -#![feature(const_trait_impl)] +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] #[const_trait] trait MyTrait { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.stderr index db48c170d1c02..b5d9b1fff8a1c 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.stderr @@ -1,26 +1,31 @@ error: `~const` is not allowed here - --> $DIR/const-bound-on-not-const-associated-fn.rs:9:40 + --> $DIR/const-bound-on-not-const-associated-fn.rs:10:40 | LL | fn do_something_else() where Self: ~const MyTrait; | ^^^^^^ | note: this function is not `const`, so it cannot have `~const` trait bounds - --> $DIR/const-bound-on-not-const-associated-fn.rs:9:8 + --> $DIR/const-bound-on-not-const-associated-fn.rs:10:8 | LL | fn do_something_else() where Self: ~const MyTrait; | ^^^^^^^^^^^^^^^^^ error: `~const` is not allowed here - --> $DIR/const-bound-on-not-const-associated-fn.rs:20:32 + --> $DIR/const-bound-on-not-const-associated-fn.rs:21:32 | LL | pub fn foo(&self) where T: ~const MyTrait { | ^^^^^^ | note: this function is not `const`, so it cannot have `~const` trait bounds - --> $DIR/const-bound-on-not-const-associated-fn.rs:20:12 + --> $DIR/const-bound-on-not-const-associated-fn.rs:21:12 | LL | pub fn foo(&self) where T: ~const MyTrait { | ^^^ -error: aborting due to 2 previous errors +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: aborting due to 3 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bounds-non-const-trait.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bounds-non-const-trait.stderr index d04e5490b7639..e1a85fc54144b 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bounds-non-const-trait.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bounds-non-const-trait.stderr @@ -7,6 +7,11 @@ LL | #![feature(const_trait_impl, effects)] = note: see issue #102090 for more information = note: `#[warn(incomplete_features)]` on by default +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/const-bounds-non-const-trait.rs:6:28 | @@ -19,5 +24,5 @@ error: `const` can only be applied to `#[const_trait]` traits LL | fn operate() {} | ^^^^^^^^ -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 3 previous errors; 1 warning emitted diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr index d93327cea1b2c..49cd1725c8cf3 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr @@ -7,6 +7,11 @@ LL | #![feature(const_trait_impl, effects)] = note: see issue #102090 for more information = note: `#[warn(incomplete_features)]` on by default +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + error[E0015]: cannot call non-const fn `non_const` in constant functions --> $DIR/const-check-fns-in-const-impl.rs:12:16 | @@ -15,6 +20,6 @@ LL | fn foo() { non_const() } | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 2 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr index fb2e66db1d488..507ceaae2eab3 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr @@ -1,3 +1,12 @@ +error[E0049]: method `a` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/const-closure-trait-method-fail.rs:5:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Tr { +LL | fn a(self) -> i32; + | - expected 0 const parameters + error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/const-closure-trait-method-fail.rs:14:39 | @@ -20,6 +29,7 @@ help: add `#![feature(effects)]` to the crate attributes to enable LL + #![feature(effects)] | -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0015`. +Some errors have detailed explanations: E0015, E0049. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr index dede411e69c73..2a54cd5d7f6e5 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr @@ -1,3 +1,12 @@ +error[E0049]: method `a` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/const-closure-trait-method.rs:5:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Tr { +LL | fn a(self) -> i32; + | - expected 0 const parameters + error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/const-closure-trait-method.rs:14:39 | @@ -20,6 +29,7 @@ help: add `#![feature(effects)]` to the crate attributes to enable LL + #![feature(effects)] | -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0015`. +Some errors have detailed explanations: E0015, E0049. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.stderr index 8e04d0bd20da0..02f9dffba3239 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.stderr @@ -7,14 +7,27 @@ LL | #![feature(const_trait_impl, effects)] = note: see issue #102090 for more information = note: `#[warn(incomplete_features)]` on by default -error[E0277]: the trait bound `NonConstImpl: ~const ConstDefaultFn` is not satisfied +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error[E0277]: the trait bound `Runtime: ~const Compat` is not satisfied --> $DIR/const-default-method-bodies.rs:24:18 | LL | NonConstImpl.a(); - | ^ the trait `~const ConstDefaultFn` is not implemented for `NonConstImpl` + | ^ the trait `~const Compat` is not implemented for `Runtime` + | + = help: the trait `Compat` is implemented for `Runtime` +note: required by a bound in `ConstDefaultFn::a` + --> $DIR/const-default-method-bodies.rs:3:1 | - = help: the trait `ConstDefaultFn` is implemented for `NonConstImpl` +LL | #[const_trait] + | ^^^^^^^^^^^^^^ required by this bound in `ConstDefaultFn::a` +... +LL | fn a(self) { + | - required by a bound in this associated function -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 2 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stderr index 085d9e710125a..1d56d015dfc15 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stderr @@ -1,3 +1,12 @@ +error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` + --> $DIR/const-drop-fail-2.rs:40:25 + | +LL | impl const Drop for ConstDropImplWithNonConstBounds { + | ^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/const-drop-fail-2.rs:21:26 | @@ -12,6 +21,19 @@ LL | const fn check(_: T) {} | | | the destructor for this type cannot be evaluated in constant functions -error: aborting due to 2 previous errors +error[E0015]: cannot call non-const fn `::a` in constant functions + --> $DIR/const-drop-fail-2.rs:42:9 + | +LL | T::a(); + | ^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0493`. +Some errors have detailed explanations: E0015, E0493. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr index e95215d471566..b251d84a9670e 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr @@ -1,3 +1,12 @@ +error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` + --> $DIR/const-drop-fail.rs:20:12 + | +LL | impl const Drop for ConstImplWithDropGlue { + | ^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/const-drop-fail.rs:24:26 | @@ -38,8 +47,10 @@ LL | | } error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL | - = note: calling non-const function `::drop` + = note: calling non-const function `::drop` | +note: inside `std::ptr::drop_in_place:: - shim(Some(NonTrivialDrop))` + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL note: inside `std::ptr::drop_in_place:: - shim(Some(ConstImplWithDropGlue))` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL note: inside `check::` @@ -60,7 +71,7 @@ LL | | } | |_- in this macro invocation = note: this error originates in the macro `check_all` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0080, E0493. For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr index f9bd9953fcfd3..912700f2a8345 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr @@ -1,3 +1,12 @@ +error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` + --> $DIR/const-drop-fail.rs:20:12 + | +LL | impl const Drop for ConstImplWithDropGlue { + | ^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/const-drop-fail.rs:24:26 | @@ -12,6 +21,6 @@ LL | const fn check(_: T) {} | | | the destructor for this type cannot be evaluated in constant functions -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr index 6aace10589605..9d1ca5dbf2c03 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr @@ -1,32 +1,64 @@ +error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` + --> $DIR/const-drop.rs:13:16 + | +LL | impl<'a> const Drop for S<'a> { + | ^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` + --> $DIR/const-drop.rs:47:16 + | +LL | impl const Drop for ConstDrop { + | ^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` + --> $DIR/const-drop.rs:68:37 + | +LL | impl const Drop for ConstDropWithBound { + | ^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` + --> $DIR/const-drop.rs:76:30 + | +LL | impl const Drop for ConstDropWithNonconstBound { + | ^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/const-drop.rs:19:22 | LL | const fn a(_: T) {} | ^^^^^^^^ -error[E0493]: destructor of `S<'_>` cannot be evaluated at compile-time - --> $DIR/const-drop.rs:24:13 +error[E0049]: method `foo` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/const-drop.rs:54:5 | -LL | let _ = S(&mut c); - | ^^^^^^^^^ the destructor for this type cannot be evaluated in constant functions +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | pub trait SomeTrait { +LL | fn foo(); + | - expected 0 const parameters -error[E0080]: evaluation of constant value failed - --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL - | - = note: calling non-const function ` as Drop>::drop` +error[E0049]: method `foo` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/const-drop.rs:54:5 | -note: inside `std::ptr::drop_in_place::> - shim(Some(S<'_>))` - --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL -note: inside `b` - --> $DIR/const-drop.rs:24:22 +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | pub trait SomeTrait { +LL | fn foo(); + | - expected 0 const parameters | -LL | let _ = S(&mut c); - | ^ -note: inside `C` - --> $DIR/const-drop.rs:30:15 - | -LL | const C: u8 = b(); - | ^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0493]: destructor of `T` cannot be evaluated at compile-time --> $DIR/const-drop.rs:19:32 @@ -34,65 +66,19 @@ error[E0493]: destructor of `T` cannot be evaluated at compile-time LL | const fn a(_: T) {} | ^ the destructor for this type cannot be evaluated in constant functions -error[E0080]: evaluation of constant value failed - --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL +error[E0015]: cannot call non-const fn `::foo` in constant functions + --> $DIR/const-drop.rs:70:13 | - = note: calling non-const function `::drop` +LL | T::foo(); + | ^^^^^^^^ | -note: inside `std::ptr::drop_in_place:: - shim(Some(t::ConstDrop))` - --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL -note: inside `a::` - --> $DIR/const-drop.rs:19:39 + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(effects)]` to the crate attributes to enable | -LL | const fn a(_: T) {} - | ^ -note: inside `_` - --> $DIR/const-drop.rs:35:27 - | -LL | const _: () = a($exp); - | ^^^^^^^ -... -LL | / implements_const_drop! { -LL | | 1u8, -LL | | 2, -LL | | 3.0, -... | -LL | | Result::::Ok(1), -LL | | } - | |_- in this macro invocation - = note: this error originates in the macro `implements_const_drop` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0080]: evaluation of constant value failed - --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL - | - = note: calling non-const function `::drop` +LL + #![feature(effects)] | -note: inside `std::ptr::drop_in_place:: - shim(Some(t::ConstDrop))` - --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL -note: inside `std::ptr::drop_in_place:: - shim(Some(t::HasConstDrop))` - --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL -note: inside `a::` - --> $DIR/const-drop.rs:19:39 - | -LL | const fn a(_: T) {} - | ^ -note: inside `_` - --> $DIR/const-drop.rs:35:27 - | -LL | const _: () = a($exp); - | ^^^^^^^ -... -LL | / implements_const_drop! { -LL | | 1u8, -LL | | 2, -LL | | 3.0, -... | -LL | | Result::::Ok(1), -LL | | } - | |_- in this macro invocation - = note: this error originates in the macro `implements_const_drop` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 6 previous errors +error: aborting due to 9 previous errors -Some errors have detailed explanations: E0080, E0493. -For more information about an error, try `rustc --explain E0080`. +Some errors have detailed explanations: E0015, E0049, E0493. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr index 18dd4543c3d39..2f93f9a6743b8 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr @@ -1,16 +1,64 @@ +error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` + --> $DIR/const-drop.rs:13:16 + | +LL | impl<'a> const Drop for S<'a> { + | ^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` + --> $DIR/const-drop.rs:47:16 + | +LL | impl const Drop for ConstDrop { + | ^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` + --> $DIR/const-drop.rs:68:37 + | +LL | impl const Drop for ConstDropWithBound { + | ^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` + --> $DIR/const-drop.rs:76:30 + | +LL | impl const Drop for ConstDropWithNonconstBound { + | ^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/const-drop.rs:19:22 | LL | const fn a(_: T) {} | ^^^^^^^^ -error[E0493]: destructor of `S<'_>` cannot be evaluated at compile-time - --> $DIR/const-drop.rs:24:13 +error[E0049]: method `foo` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/const-drop.rs:54:5 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | pub trait SomeTrait { +LL | fn foo(); + | - expected 0 const parameters + +error[E0049]: method `foo` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/const-drop.rs:54:5 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | pub trait SomeTrait { +LL | fn foo(); + | - expected 0 const parameters | -LL | let _ = S(&mut c); - | ^^^^^^^^^- value is dropped here - | | - | the destructor for this type cannot be evaluated in constant functions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0493]: destructor of `T` cannot be evaluated at compile-time --> $DIR/const-drop.rs:19:32 @@ -20,6 +68,19 @@ LL | const fn a(_: T) {} | | | the destructor for this type cannot be evaluated in constant functions -error: aborting due to 3 previous errors +error[E0015]: cannot call non-const fn `::foo` in constant functions + --> $DIR/const-drop.rs:70:13 + | +LL | T::foo(); + | ^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + +error: aborting due to 9 previous errors -For more information about this error, try `rustc --explain E0493`. +Some errors have detailed explanations: E0015, E0049, E0493. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-fns-are-early-bound.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-fns-are-early-bound.rs index faa913c759884..b3087349e4d3c 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-fns-are-early-bound.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-fns-are-early-bound.rs @@ -1,17 +1,21 @@ -//@ check-pass +//@ known-bug: #110395 +// FIXME(effects) check-pass +//@ compile-flags: -Znext-solver #![crate_type = "lib"] -#![allow(internal_features)] +#![allow(internal_features, incomplete_features)] #![no_std] #![no_core] #![feature( auto_traits, const_trait_impl, - effects, //~ WARN the feature `effects` is incomplete + effects, lang_items, no_core, staged_api, - unboxed_closures + unboxed_closures, + rustc_attrs, + marker_trait_attr, )] #![stable(feature = "minicore", since = "1.0.0")] @@ -84,3 +88,49 @@ trait Receiver {} impl Receiver for &T {} impl Receiver for &mut T {} + +#[stable(feature = "minicore", since = "1.0.0")] +pub mod effects { + use super::Sized; + + #[lang = "EffectsNoRuntime"] + #[stable(feature = "minicore", since = "1.0.0")] + pub struct NoRuntime; + #[lang = "EffectsMaybe"] + #[stable(feature = "minicore", since = "1.0.0")] + pub struct Maybe; + #[lang = "EffectsRuntime"] + #[stable(feature = "minicore", since = "1.0.0")] + pub struct Runtime; + + #[lang = "EffectsCompat"] + #[stable(feature = "minicore", since = "1.0.0")] + pub trait Compat<#[rustc_runtime] const RUNTIME: bool> {} + + #[stable(feature = "minicore", since = "1.0.0")] + impl Compat for NoRuntime {} + #[stable(feature = "minicore", since = "1.0.0")] + impl Compat for Runtime {} + #[stable(feature = "minicore", since = "1.0.0")] + impl<#[rustc_runtime] const RUNTIME: bool> Compat for Maybe {} + + #[lang = "EffectsTyCompat"] + #[marker] + #[stable(feature = "minicore", since = "1.0.0")] + pub trait TyCompat {} + + #[stable(feature = "minicore", since = "1.0.0")] + impl TyCompat for T {} + #[stable(feature = "minicore", since = "1.0.0")] + impl TyCompat for Maybe {} + #[stable(feature = "minicore", since = "1.0.0")] + impl TyCompat for T {} + + #[lang = "EffectsIntersection"] + #[stable(feature = "minicore", since = "1.0.0")] + pub trait Intersection { + #[lang = "EffectsIntersectionOutput"] + #[stable(feature = "minicore", since = "1.0.0")] + type Output: ?Sized; + } +} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-fns-are-early-bound.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-fns-are-early-bound.stderr index 42b19fce28e9c..7aa3aa8c6bbb3 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-fns-are-early-bound.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-fns-are-early-bound.stderr @@ -1,11 +1,20 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/const-fns-are-early-bound.rs:10:5 +error[E0277]: the trait bound `FnOnce<()>::{synthetic#0}: const Compat` is not satisfied + --> $DIR/const-fns-are-early-bound.rs:31:17 | -LL | effects, - | ^^^^^^^ +LL | is_const_fn(foo); + | ----------- ^^^ the trait `const Compat` is not implemented for `FnOnce<()>::{synthetic#0}` + | | + | required by a bound introduced by this call | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default +note: required by a bound in `is_const_fn` + --> $DIR/const-fns-are-early-bound.rs:25:12 + | +LL | fn is_const_fn(_: F) + | ----------- required by a bound in this function +LL | where +LL | F: const FnOnce<()>, + | ^^^^^^^^^^^^^^^^ required by this bound in `is_const_fn` -warning: 1 warning emitted +error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr index fb282d9ee2b47..2a030369093d6 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr @@ -7,6 +7,11 @@ LL | #![feature(const_trait_impl, effects)] = note: see issue #102090 for more information = note: `#[warn(incomplete_features)]` on by default +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + error: const `impl` for trait `A` which is not marked with `#[const_trait]` --> $DIR/const-impl-requires-const-trait.rs:8:12 | @@ -19,15 +24,5 @@ LL | impl const A for () {} = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change -error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates - --> $DIR/const-impl-requires-const-trait.rs:8:6 - | -LL | impl const A for () {} - | ^^^^^ unconstrained const parameter - | - = note: expressions using a const parameter must map each value to a distinct output value - = note: proving the result of expressions other than the parameter are unique is not supported - error: aborting due to 2 previous errors; 1 warning emitted -For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr index af50a115c69f7..b59c6d1eed8da 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr @@ -4,6 +4,11 @@ error[E0635]: unknown feature `const_cmp` LL | const_cmp, | ^^^^^^^^^ +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/const-impl-trait.rs:13:30 | @@ -238,7 +243,7 @@ LL | const fn apit_assoc_bound(_: impl IntoIterator + ~const Des | | | the destructor for this type cannot be evaluated in constant functions -error: aborting due to 32 previous errors +error: aborting due to 33 previous errors Some errors have detailed explanations: E0493, E0635. For more information about an error, try `rustc --explain E0493`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds-trait-objects.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds-trait-objects.rs index 8e71fa4d51902..691bce19dc245 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds-trait-objects.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds-trait-objects.rs @@ -1,4 +1,5 @@ -#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +#![feature(const_trait_impl)] +// FIXME(effects) add effects //@ edition: 2021 #[const_trait] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds-trait-objects.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds-trait-objects.stderr index 7d774bef0e94a..bd29b4b860b62 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds-trait-objects.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds-trait-objects.stderr @@ -1,11 +1,11 @@ error: const trait bounds are not allowed in trait object types - --> $DIR/const-trait-bounds-trait-objects.rs:8:17 + --> $DIR/const-trait-bounds-trait-objects.rs:9:17 | LL | let _: &dyn const Trait; | ^^^^^^^^^^^ error: `~const` is not allowed here - --> $DIR/const-trait-bounds-trait-objects.rs:9:17 + --> $DIR/const-trait-bounds-trait-objects.rs:10:17 | LL | let _: &dyn ~const Trait; | ^^^^^^ @@ -13,27 +13,18 @@ LL | let _: &dyn ~const Trait; = note: trait objects cannot have `~const` trait bounds error: const trait bounds are not allowed in trait object types - --> $DIR/const-trait-bounds-trait-objects.rs:14:25 + --> $DIR/const-trait-bounds-trait-objects.rs:15:25 | LL | const fn handle(_: &dyn const NonConst) {} | ^^^^^^^^^^^^^^ error: `~const` is not allowed here - --> $DIR/const-trait-bounds-trait-objects.rs:16:23 + --> $DIR/const-trait-bounds-trait-objects.rs:17:23 | LL | const fn take(_: &dyn ~const NonConst) {} | ^^^^^^ | = note: trait objects cannot have `~const` trait bounds -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/const-trait-bounds-trait-objects.rs:1:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - -error: aborting due to 4 previous errors; 1 warning emitted +error: aborting due to 4 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds.rs index cf452cf852687..3b4ba6a998f88 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds.rs @@ -1,5 +1,6 @@ -//@ check-pass - +//@ known-bug: #110395 +//@ compile-flags: -Znext-solver +// FIXME(effects): check-pass #![feature(const_trait_impl, effects, generic_const_exprs)] #![allow(incomplete_features)] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds.stderr new file mode 100644 index 0000000000000..4d543f6a1559a --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds.stderr @@ -0,0 +1,30 @@ +error[E0284]: type annotations needed: cannot normalize `process::{constant#0}` + --> $DIR/const-trait-bounds.rs:12:35 + | +LL | fn process(input: [(); T::make(2)]) -> [(); T::make(2)] { + | ^^^^^^^^^^^^^^^^ cannot normalize `process::{constant#0}` + +error[E0284]: type annotations needed: cannot satisfy `the constant `T::make(P)` can be evaluated` + --> $DIR/const-trait-bounds.rs:18:5 + | +LL | [u32; T::make(P)]:, + | ^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `T::make(P)` can be evaluated` + | +note: required by a bound in `Struct` + --> $DIR/const-trait-bounds.rs:18:11 + | +LL | struct Struct + | ------ required by a bound in this struct +LL | where +LL | [u32; T::make(P)]:, + | ^^^^^^^^^^ required by this bound in `Struct` + +error[E0284]: type annotations needed: cannot normalize `process::{constant#1}` + --> $DIR/const-trait-bounds.rs:13:5 + | +LL | input + | ^^^^^ cannot normalize `process::{constant#1}` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-gate.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-gate.rs index 348ca0ab1906b..a772d69c9e2e2 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-gate.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-gate.rs @@ -1,4 +1,5 @@ #[derive_const(Default)] //~ ERROR use of unstable library feature +//~^ ERROR const `impl` for trait `Default` which is not marked with `#[const_trait]` pub struct S; fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr index 9ec2ac9338175..3ccae5a83e665 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr @@ -7,6 +7,16 @@ LL | #[derive_const(Default)] = help: add `#![feature(derive_const)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error: const `impl` for trait `Default` which is not marked with `#[const_trait]` + --> $DIR/derive-const-gate.rs:1:16 + | +LL | #[derive_const(Default)] + | ^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + = note: this error originates in the derive macro `Default` (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 E0658`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr index 1e091283510d6..777b3313da6b2 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr @@ -7,6 +7,11 @@ LL | #![feature(derive_const, effects)] = note: see issue #102090 for more information = note: `#[warn(incomplete_features)]` on by default +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + error: const `impl` for trait `Default` which is not marked with `#[const_trait]` --> $DIR/derive-const-non-const-type.rs:10:16 | @@ -17,11 +22,5 @@ LL | #[derive_const(Default)] = note: adding a non-const method body in the future would be a breaking change = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates - | - = note: expressions using a const parameter must map each value to a distinct output value - = note: proving the result of expressions other than the parameter are unique is not supported - error: aborting due to 2 previous errors; 1 warning emitted -For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr index 925b2c58ed77b..ad727fc36cd76 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr @@ -19,6 +19,11 @@ error[E0635]: unknown feature `const_default_impls` LL | #![feature(const_trait_impl, const_cmp, const_default_impls, derive_const, effects)] | ^^^^^^^^^^^^^^^^^^^ +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + error: const `impl` for trait `Default` which is not marked with `#[const_trait]` --> $DIR/derive-const-use.rs:7:12 | @@ -28,33 +33,6 @@ LL | impl const Default for A { = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change -error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates - --> $DIR/derive-const-use.rs:7:6 - | -LL | impl const Default for A { - | ^^^^^ unconstrained const parameter - | - = note: expressions using a const parameter must map each value to a distinct output value - = note: proving the result of expressions other than the parameter are unique is not supported - -error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` - --> $DIR/derive-const-use.rs:11:12 - | -LL | impl const PartialEq for A { - | ^^^^^^^^^ - | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` - = note: adding a non-const method body in the future would be a breaking change - -error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates - --> $DIR/derive-const-use.rs:11:6 - | -LL | impl const PartialEq for A { - | ^^^^^ unconstrained const parameter - | - = note: expressions using a const parameter must map each value to a distinct output value - = note: proving the result of expressions other than the parameter are unique is not supported - error: const `impl` for trait `Default` which is not marked with `#[const_trait]` --> $DIR/derive-const-use.rs:15:16 | @@ -65,10 +43,14 @@ LL | #[derive_const(Default, PartialEq)] = note: adding a non-const method body in the future would be a breaking change = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates +error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` + --> $DIR/derive-const-use.rs:11:12 + | +LL | impl const PartialEq for A { + | ^^^^^^^^^ | - = note: expressions using a const parameter must map each value to a distinct output value - = note: proving the result of expressions other than the parameter are unique is not supported + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` --> $DIR/derive-const-use.rs:15:25 @@ -80,73 +62,29 @@ LL | #[derive_const(Default, PartialEq)] = note: adding a non-const method body in the future would be a breaking change = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates - | - = note: expressions using a const parameter must map each value to a distinct output value - = note: proving the result of expressions other than the parameter are unique is not supported - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0284]: type annotations needed - --> $DIR/derive-const-use.rs:18:35 - | -LL | const _: () = assert!(S((), A) == S::default()); - | ^^^^^^^^^^^^ cannot infer the value of the constant `_` - | -note: required for `S` to implement `Default` - --> $DIR/derive-const-use.rs:15:16 - | -LL | #[derive_const(Default, PartialEq)] - | ^^^^^^^ unsatisfied trait bound introduced in this `derive` macro - = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0284]: type annotations needed - --> $DIR/derive-const-use.rs:18:23 - | -LL | const _: () = assert!(S((), A) == S::default()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer the value of the constant `_` - | -note: required for `S` to implement `PartialEq` - --> $DIR/derive-const-use.rs:15:25 - | -LL | #[derive_const(Default, PartialEq)] - | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro - = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0284]: type annotations needed - --> $DIR/derive-const-use.rs:16:18 +error[E0080]: evaluation of constant value failed + --> $DIR/derive-const-use.rs:16:14 | LL | #[derive_const(Default, PartialEq)] | ------- in this derive macro expansion LL | pub struct S((), A); - | ^ cannot infer the value of the constant `_` + | ^^ calling non-const function `<() as Default>::default` | -note: required for `A` to implement `Default` - --> $DIR/derive-const-use.rs:7:12 - | -LL | impl const Default for A { - | ----- ^^^^^^^ ^ - | | - | unsatisfied trait bound introduced here - = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0284]: type annotations needed - --> $DIR/derive-const-use.rs:16:18 +note: inside `::default` + --> $DIR/derive-const-use.rs:16:14 | LL | #[derive_const(Default, PartialEq)] - | --------- in this derive macro expansion + | ------- in this derive macro expansion LL | pub struct S((), A); - | ^ cannot infer the value of the constant `_` - | -note: required for `A` to implement `PartialEq` - --> $DIR/derive-const-use.rs:11:12 + | ^^ +note: inside `_` + --> $DIR/derive-const-use.rs:18:35 | -LL | impl const PartialEq for A { - | ----- ^^^^^^^^^ ^ - | | - | unsatisfied trait bound introduced here - = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) +LL | const _: () = assert!(S((), A) == S::default()); + | ^^^^^^^^^^^^ + = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 14 previous errors; 1 warning emitted +error: aborting due to 8 previous errors; 1 warning emitted -Some errors have detailed explanations: E0207, E0284, E0635. -For more information about an error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0080, E0635. +For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.stderr index 5d3aa250d1854..addce8dcd6c75 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.stderr @@ -7,6 +7,11 @@ LL | #![feature(const_trait_impl, effects)] = note: see issue #102090 for more information = note: `#[warn(incomplete_features)]` on by default +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` --> $DIR/derive-const-with-params.rs:7:16 | @@ -25,25 +30,5 @@ LL | #[derive_const(PartialEq)] | = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates - | - = note: expressions using a const parameter must map each value to a distinct output value - = note: proving the result of expressions other than the parameter are unique is not supported - -error[E0284]: type annotations needed - --> $DIR/derive-const-with-params.rs:11:5 - | -LL | a == b - | ^^^^^^ cannot infer the value of the constant `_` - | -note: required for `Reverse` to implement `PartialEq` - --> $DIR/derive-const-with-params.rs:7:16 - | -LL | #[derive_const(PartialEq)] - | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro - = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 4 previous errors; 1 warning emitted +error: aborting due to 3 previous errors; 1 warning emitted -Some errors have detailed explanations: E0207, E0284. -For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs index d8be8b13d0822..9ee5254dbf8a8 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs @@ -2,8 +2,9 @@ // be called from a const context when used across crates. // //@ check-pass - -#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] //@ aux-build: cross-crate.rs extern crate cross_crate; diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.stderr deleted file mode 100644 index 2f1e1e6b8d2b9..0000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/cross-crate-default-method-body-is-const.rs:6:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.gated.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.gated.stderr deleted file mode 100644 index 2ce29a74eaeb0..0000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.gated.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/cross-crate.rs:3:60 - | -LL | #![cfg_attr(any(gated, gatednc), feature(const_trait_impl, effects))] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr index ddb5b3c7c5078..b7209827c22c0 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr @@ -1,20 +1,18 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/cross-crate.rs:3:60 - | -LL | #![cfg_attr(any(gated, gatednc), feature(const_trait_impl, effects))] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - -error[E0277]: the trait bound `cross_crate::NonConst: ~const cross_crate::MyTrait` is not satisfied - --> $DIR/cross-crate.rs:18:14 +error[E0277]: the trait bound `cross_crate::MyTrait::{synthetic#0}: ~const Compat` is not satisfied + --> $DIR/cross-crate.rs:19:14 | LL | NonConst.func(); - | ^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst` + | ^^^^ the trait `~const Compat` is not implemented for `cross_crate::MyTrait::{synthetic#0}` + | +note: required by a bound in `func` + --> $DIR/auxiliary/cross-crate.rs:5:1 | - = help: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst` +LL | #[const_trait] + | ^^^^^^^^^^^^^^ required by this bound in `MyTrait::func` +... +LL | fn func(self); + | ---- required by a bound in this associated function -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.rs index 04c101d0fc5fb..cfcada9c828d4 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.rs @@ -1,7 +1,8 @@ //@ revisions: stock gated stocknc gatednc //@ [gated] check-pass +//@ compile-flags: -Znext-solver #![cfg_attr(any(gated, gatednc), feature(const_trait_impl, effects))] -//[gated,gatednc]~^ WARN the feature `effects` is incomplete +#![allow(incomplete_features)] //@ aux-build: cross-crate.rs extern crate cross_crate; diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.stock.stderr index 3df875057f2c8..b481bdc470ce3 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.stock.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.stock.stderr @@ -1,5 +1,5 @@ error[E0015]: cannot call non-const fn `::func` in constant functions - --> $DIR/cross-crate.rs:21:11 + --> $DIR/cross-crate.rs:22:11 | LL | Const.func(); | ^^^^^^ diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr index e56a5e4165ce3..5c3e3b6ff4008 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr @@ -1,5 +1,5 @@ error[E0015]: cannot call non-const fn `::func` in constant functions - --> $DIR/cross-crate.rs:18:14 + --> $DIR/cross-crate.rs:19:14 | LL | NonConst.func(); | ^^^^^^ @@ -11,7 +11,7 @@ LL + #![feature(const_trait_impl)] | error[E0015]: cannot call non-const fn `::func` in constant functions - --> $DIR/cross-crate.rs:21:11 + --> $DIR/cross-crate.rs:22:11 | LL | Const.func(); | ^^^^^^ diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr index 67a936d0882f4..1b5aa9c91918c 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr @@ -7,14 +7,27 @@ LL | #![feature(const_trait_impl, effects)] = note: see issue #102090 for more information = note: `#[warn(incomplete_features)]` on by default -error[E0277]: the trait bound `(): ~const Tr` is not satisfied +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error[E0277]: the trait bound `Runtime: ~const Compat` is not satisfied --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:12 | LL | ().a() - | ^ the trait `~const Tr` is not implemented for `()` + | ^ the trait `~const Compat` is not implemented for `Runtime` + | + = help: the trait `Compat` is implemented for `Runtime` +note: required by a bound in `Tr::a` + --> $DIR/default-method-body-is-const-same-trait-ck.rs:3:1 | - = help: the trait `Tr` is implemented for `()` +LL | #[const_trait] + | ^^^^^^^^^^^^^^ required by this bound in `Tr::a` +LL | pub trait Tr { +LL | fn a(&self) {} + | - required by a bound in this associated function -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 2 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/do-not-const-check-override.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/do-not-const-check-override.rs index be5e66478dfaf..71e6375283fd8 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/do-not-const-check-override.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/do-not-const-check-override.rs @@ -1,5 +1,7 @@ //@ check-pass -#![feature(const_trait_impl, rustc_attrs, effects)] //~ WARN the feature `effects` is incomplete +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, rustc_attrs, effects)] #[const_trait] trait Foo { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/do-not-const-check-override.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/do-not-const-check-override.stderr deleted file mode 100644 index 4be1160b58cb2..0000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/do-not-const-check-override.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/do-not-const-check-override.rs:2:43 - | -LL | #![feature(const_trait_impl, rustc_attrs, effects)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/auxiliary/cross-crate.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/auxiliary/cross-crate.rs index 5c32eee8737e8..779527e22d4ab 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/auxiliary/cross-crate.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/auxiliary/cross-crate.rs @@ -1,4 +1,6 @@ -#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] pub const fn foo() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.rs index a1c0425b24e38..3debc22098afc 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.rs @@ -1,5 +1,6 @@ //@ check-pass // FIXME(effects) this shouldn't pass +//@ compile-flags: -Znext-solver #![feature(const_closures, const_trait_impl, effects)] #![allow(incomplete_features)] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/effect-param-infer.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/effect-param-infer.rs index b354591e0070f..958b9ac6d5773 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/effect-param-infer.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/effect-param-infer.rs @@ -2,8 +2,9 @@ // at the end of generic args when the generics have defaulted params. // //@ check-pass - -#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] #[const_trait] pub trait Foo { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/effect-param-infer.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/effect-param-infer.stderr deleted file mode 100644 index 7ceb3669e5983..0000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/effect-param-infer.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/effect-param-infer.rs:6:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/fallback.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/fallback.rs index d949e4b829fc4..4cfba00526b0b 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/fallback.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/fallback.rs @@ -1,6 +1,7 @@ //@ check-pass - -#![feature(effects)] //~ WARN the feature `effects` is incomplete +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(effects)] pub const fn owo() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/fallback.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/fallback.stderr deleted file mode 100644 index f7d5de829b200..0000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/fallback.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/fallback.rs:3:12 - | -LL | #![feature(effects)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/group-traits.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/group-traits.rs new file mode 100644 index 0000000000000..2c5b6cc40e638 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/group-traits.rs @@ -0,0 +1,14 @@ +//@ check-pass +use std::ops::Add; + +pub trait GroupOpsOwned: for<'r> Add<&'r Rhs, Output = Output> {} + +pub trait Curve: Sized + GroupOpsOwned { + type AffineRepr; +} + +pub trait CofactorCurve: Curve::Affine> { + type Affine; +} + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/helloworld.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/helloworld.rs index eed8cdc447c55..54f362b4413b9 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/helloworld.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/helloworld.rs @@ -1,11 +1,11 @@ //@ check-pass - +//@ compile-flags: -Znext-solver // gate-test-effects // ^ effects doesn't have a gate so we will trick tidy into thinking this is a gate test - +#![allow(incomplete_features)] #![feature( const_trait_impl, - effects, //~ WARN the feature `effects` is incomplete + effects, core_intrinsics, const_eval_select )] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/helloworld.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/helloworld.stderr deleted file mode 100644 index 8719c5cbcef0f..0000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/helloworld.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/helloworld.rs:8:5 - | -LL | effects, - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-112822-expected-type-for-param.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-112822-expected-type-for-param.stderr index 3f0ed13d665f8..526746eec7346 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-112822-expected-type-for-param.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-112822-expected-type-for-param.stderr @@ -17,6 +17,11 @@ LL | #![feature(const_trait_impl, effects)] = note: see issue #102090 for more information = note: `#[warn(incomplete_features)]` on by default +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/ice-112822-expected-type-for-param.rs:3:32 | @@ -40,7 +45,7 @@ LL | assert_eq!(first, &b'f'); = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 4 previous errors; 1 warning emitted +error: aborting due to 5 previous errors; 1 warning emitted Some errors have detailed explanations: E0015, E0658. For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-113375-index-out-of-bounds-generics.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-113375-index-out-of-bounds-generics.rs index 53f8e3c56d761..06e3377c5eec1 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-113375-index-out-of-bounds-generics.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-113375-index-out-of-bounds-generics.rs @@ -1,5 +1,5 @@ //@ check-pass - +//@ compile-flags: -Znext-solver // effects ice https://github.com/rust-lang/rust/issues/113375 index out of bounds #![allow(incomplete_features, unused)] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/infer-fallback.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/infer-fallback.rs index ff3a27c3ee479..581c3949d3811 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/infer-fallback.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/infer-fallback.rs @@ -1,5 +1,7 @@ //@ check-pass -#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] const fn a() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/infer-fallback.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/infer-fallback.stderr deleted file mode 100644 index 49c7d3958466a..0000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/infer-fallback.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/infer-fallback.rs:2:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.stderr index e4a5f3686084e..1963332b856de 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.stderr @@ -7,12 +7,11 @@ LL | #![feature(const_trait_impl, effects, const_mut_refs)] = note: see issue #102090 for more information = note: `#[warn(incomplete_features)]` on by default -error[E0094]: intrinsic has wrong number of const parameters: found 1, expected 0 - --> $DIR/minicore.rs:517:27 +error: requires `EffectsCompat` lang_item + --> $DIR/minicore.rs:455:9 | -LL | const fn const_eval_select( - | ^^^^^^^^^^^^^^^^^^^^^^^ expected 0 const parameters +LL | impl Clone for RefCell { + | ^^^^^ error: aborting due to 1 previous error; 1 warning emitted -For more information about this error, try `rustc --explain E0094`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params-cross-crate.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params-cross-crate.stderr index cc870ad336cd1..fa2e3da368bd8 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params-cross-crate.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params-cross-crate.stderr @@ -7,7 +7,7 @@ LL | foo::(); | expected 0 generic arguments | note: function defined here, with 0 generic parameters - --> $DIR/auxiliary/cross-crate.rs:3:14 + --> $DIR/auxiliary/cross-crate.rs:5:14 | LL | pub const fn foo() {} | ^^^ @@ -16,15 +16,17 @@ error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplie --> $DIR/no-explicit-const-params-cross-crate.rs:16:12 | LL | <() as Bar>::bar(); - | ^^^------- help: remove these generics - | | - | expected 0 generic arguments + | ^^^ expected 0 generic arguments | note: trait defined here, with 0 generic parameters - --> $DIR/auxiliary/cross-crate.rs:6:11 + --> $DIR/auxiliary/cross-crate.rs:8:11 | LL | pub trait Bar { | ^^^ +help: replace the generic bound with the associated type + | +LL | <() as Bar< = false>>::bar(); + | + error[E0107]: function takes 0 generic arguments but 1 generic argument was supplied --> $DIR/no-explicit-const-params-cross-crate.rs:7:5 @@ -35,7 +37,7 @@ LL | foo::(); | expected 0 generic arguments | note: function defined here, with 0 generic parameters - --> $DIR/auxiliary/cross-crate.rs:3:14 + --> $DIR/auxiliary/cross-crate.rs:5:14 | LL | pub const fn foo() {} | ^^^ @@ -44,15 +46,17 @@ error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplie --> $DIR/no-explicit-const-params-cross-crate.rs:9:12 | LL | <() as Bar>::bar(); - | ^^^------ help: remove these generics - | | - | expected 0 generic arguments + | ^^^ expected 0 generic arguments | note: trait defined here, with 0 generic parameters - --> $DIR/auxiliary/cross-crate.rs:6:11 + --> $DIR/auxiliary/cross-crate.rs:8:11 | LL | pub trait Bar { | ^^^ +help: replace the generic bound with the associated type + | +LL | <() as Bar< = true>>::bar(); + | + error: aborting due to 4 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params.stderr index 39aa5825611f3..fbb96dfd85e1b 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params.stderr @@ -7,6 +7,11 @@ LL | #![feature(const_trait_impl, effects)] = note: see issue #102090 for more information = note: `#[warn(incomplete_features)]` on by default +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + error[E0107]: function takes 0 generic arguments but 1 generic argument was supplied --> $DIR/no-explicit-const-params.rs:22:5 | @@ -25,15 +30,17 @@ error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplie --> $DIR/no-explicit-const-params.rs:24:12 | LL | <() as Bar>::bar(); - | ^^^------- help: remove these generics - | | - | expected 0 generic arguments + | ^^^ expected 0 generic arguments | note: trait defined here, with 0 generic parameters --> $DIR/no-explicit-const-params.rs:6:7 | LL | trait Bar { | ^^^ +help: replace the generic bound with the associated type + | +LL | <() as Bar< = false>>::bar(); + | + error[E0308]: mismatched types --> $DIR/no-explicit-const-params.rs:24:5 @@ -62,17 +69,19 @@ error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplie --> $DIR/no-explicit-const-params.rs:17:12 | LL | <() as Bar>::bar(); - | ^^^------ help: remove these generics - | | - | expected 0 generic arguments + | ^^^ expected 0 generic arguments | note: trait defined here, with 0 generic parameters --> $DIR/no-explicit-const-params.rs:6:7 | LL | trait Bar { | ^^^ +help: replace the generic bound with the associated type + | +LL | <() as Bar< = true>>::bar(); + | + -error: aborting due to 5 previous errors; 1 warning emitted +error: aborting due to 6 previous errors; 1 warning emitted Some errors have detailed explanations: E0107, E0308. For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs index 0592ac2e0e70c..9f6ca1f294f01 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs @@ -1,12 +1,10 @@ -//@ known-bug: #110395 -// FIXME: effects - +//@ check-pass +//@ compile-flags: -Znext-solver #![feature(const_trait_impl, effects)] +#![allow(incomplete_features)] -// This fails because `~const Uwu` doesn't imply (non-const) `Uwu`. - -// FIXME: #[const_trait] -pub trait Owo::T> {} +#[const_trait] +pub trait Owo::T> {} #[const_trait] pub trait Uwu: Owo { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.stderr deleted file mode 100644 index ab5f7b55a4e47..0000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.stderr +++ /dev/null @@ -1,74 +0,0 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/project.rs:4:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - -error[E0277]: the trait bound `Self: Uwu` is not satisfied - --> $DIR/project.rs:12:1 - | -LL | pub trait Uwu: Owo { - | ^^^^^^^^^^^^^^^^^^ the trait `Uwu` is not implemented for `Self` - | -help: consider further restricting `Self` - | -LL | pub trait Uwu: Owo + Uwu { - | +++++ - -error[E0277]: the trait bound `Self: Uwu` is not satisfied - --> $DIR/project.rs:12:1 - | -LL | / pub trait Uwu: Owo { -LL | | type T; -LL | | } - | |_^ the trait `Uwu` is not implemented for `Self` - | -help: consider further restricting `Self` - | -LL | pub trait Uwu: Owo + Uwu { - | +++++ - -error[E0277]: the trait bound `Self: Uwu` is not satisfied - --> $DIR/project.rs:12:16 - | -LL | pub trait Uwu: Owo { - | ^^^ the trait `Uwu` is not implemented for `Self` - | -note: required by a bound in `Owo` - --> $DIR/project.rs:9:15 - | -LL | pub trait Owo::T> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Owo` -help: consider further restricting `Self` - | -LL | pub trait Uwu: Owo + Uwu { - | +++++ - -error[E0277]: the trait bound `Self: Uwu` is not satisfied - --> $DIR/project.rs:13:5 - | -LL | type T; - | ^^^^^^ the trait `Uwu` is not implemented for `Self` - | -help: consider further restricting `Self` - | -LL | pub trait Uwu: Owo + Uwu { - | +++++ - -error[E0277]: the trait bound `Self: Uwu` is not satisfied - --> $DIR/project.rs:13:5 - | -LL | type T; - | ^^^^^^^ the trait `Uwu` is not implemented for `Self` - | -help: consider further restricting `Self` - | -LL | pub trait Uwu: Owo + Uwu { - | +++++ - -error: aborting due to 5 previous errors; 1 warning emitted - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.rs index 987a162cd6cae..e6e41c472bdc7 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.rs @@ -6,7 +6,6 @@ trait T {} impl const dyn T { //~^ ERROR inherent impls cannot be `const` - //~| ERROR the const parameter `host` is not constrained by the impl trait, self type, or pub const fn new() -> std::sync::Mutex {} //~^ ERROR mismatched types //~| ERROR cannot be known at compilation time diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.stderr index f24d7c7a16017..5ff1c6c5b9f15 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.stderr @@ -17,17 +17,13 @@ LL | #![feature(effects)] = note: see issue #102090 for more information = note: `#[warn(incomplete_features)]` on by default -error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates - --> $DIR/span-bug-issue-121418.rs:7:6 +error: using `#![feature(effects)]` without enabling next trait solver globally | -LL | impl const dyn T { - | ^^^^^ unconstrained const parameter - | - = note: expressions using a const parameter must map each value to a distinct output value - = note: proving the result of expressions other than the parameter are unique is not supported + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable error[E0308]: mismatched types - --> $DIR/span-bug-issue-121418.rs:10:27 + --> $DIR/span-bug-issue-121418.rs:9:27 | LL | pub const fn new() -> std::sync::Mutex {} | --- ^^^^^^^^^^^^^^^^^^^^^^^ expected `Mutex`, found `()` @@ -38,7 +34,7 @@ LL | pub const fn new() -> std::sync::Mutex {} found unit type `()` error[E0277]: the size for values of type `(dyn T + 'static)` cannot be known at compilation time - --> $DIR/span-bug-issue-121418.rs:10:27 + --> $DIR/span-bug-issue-121418.rs:9:27 | LL | pub const fn new() -> std::sync::Mutex {} | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -50,5 +46,5 @@ note: required because it appears within the type `Mutex<(dyn T + 'static)>` error: aborting due to 4 previous errors; 1 warning emitted -Some errors have detailed explanations: E0207, E0277, E0308. -For more information about an error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.rs index 00465b0f53d5a..0508b1c5e26b6 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.rs @@ -11,12 +11,11 @@ trait Foo {} impl const Foo for T {} //~^ error: const `impl` for trait `Foo` which is not marked with `#[const_trait]` -//~| error: the const parameter `host` is not constrained by the impl trait, self type, or predicates [E0207] impl const Foo for T where T: const Specialize {} //~^ error: const `impl` for trait `Foo` which is not marked with `#[const_trait]` //~| error: `const` can only be applied to `#[const_trait]` traits -//~| error: the const parameter `host` is not constrained by the impl trait, self type, or predicates [E0207] -//~| error: conflicting implementations of trait `Foo` +//~| error: specialization impl does not specialize any associated items +//~| error: cannot specialize on trait `Specialize` fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.stderr index 8d69151bf74c3..e97a9615ae1a0 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.stderr @@ -7,6 +7,11 @@ LL | #![feature(effects)] = note: see issue #102090 for more information = note: `#[warn(incomplete_features)]` on by default +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + error: const `impl` for trait `Foo` which is not marked with `#[const_trait]` --> $DIR/spec-effectvar-ice.rs:12:15 | @@ -20,7 +25,7 @@ LL | impl const Foo for T {} = note: adding a non-const method body in the future would be a breaking change error: const `impl` for trait `Foo` which is not marked with `#[const_trait]` - --> $DIR/spec-effectvar-ice.rs:16:15 + --> $DIR/spec-effectvar-ice.rs:15:15 | LL | trait Foo {} | - help: mark `Foo` as const: `#[const_trait]` @@ -32,39 +37,28 @@ LL | impl const Foo for T where T: const Specialize {} = note: adding a non-const method body in the future would be a breaking change error: `const` can only be applied to `#[const_trait]` traits - --> $DIR/spec-effectvar-ice.rs:16:40 + --> $DIR/spec-effectvar-ice.rs:15:40 | LL | impl const Foo for T where T: const Specialize {} | ^^^^^^^^^^ -error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates - --> $DIR/spec-effectvar-ice.rs:12:9 +error: specialization impl does not specialize any associated items + --> $DIR/spec-effectvar-ice.rs:15:1 | -LL | impl const Foo for T {} - | ^^^^^ unconstrained const parameter +LL | impl const Foo for T where T: const Specialize {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expressions using a const parameter must map each value to a distinct output value - = note: proving the result of expressions other than the parameter are unique is not supported - -error[E0119]: conflicting implementations of trait `Foo` - --> $DIR/spec-effectvar-ice.rs:16:1 +note: impl is a specialization of this impl + --> $DIR/spec-effectvar-ice.rs:12:1 | LL | impl const Foo for T {} - | ----------------------- first implementation here -... -LL | impl const Foo for T where T: const Specialize {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + | ^^^^^^^^^^^^^^^^^^^^^^^ -error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates - --> $DIR/spec-effectvar-ice.rs:16:9 +error: cannot specialize on trait `Specialize` + --> $DIR/spec-effectvar-ice.rs:15:34 | LL | impl const Foo for T where T: const Specialize {} - | ^^^^^ unconstrained const parameter - | - = note: expressions using a const parameter must map each value to a distinct output value - = note: proving the result of expressions other than the parameter are unique is not supported + | ^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors; 1 warning emitted -Some errors have detailed explanations: E0119, E0207. -For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.stderr index 33914cb306dc6..15cb84026e470 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.stderr @@ -63,6 +63,11 @@ LL | #![feature(const_trait_impl, effects)] = note: see issue #102090 for more information = note: `#[warn(incomplete_features)]` on by default -error: aborting due to 4 previous errors; 1 warning emitted +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: aborting due to 5 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0379`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/with-without-next-solver.coherence.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/with-without-next-solver.coherence.stderr new file mode 100644 index 0000000000000..20448f51de22c --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/with-without-next-solver.coherence.stderr @@ -0,0 +1,7 @@ +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: aborting due to 1 previous error + diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/with-without-next-solver.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/with-without-next-solver.rs new file mode 100644 index 0000000000000..f022af05c50e7 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/with-without-next-solver.rs @@ -0,0 +1,10 @@ +// test that we error correctly when effects is used without the next-solver flag. +//@ revisions: stock coherence full +//@[coherence] compile-flags: -Znext-solver=coherence +//@[full] compile-flags: -Znext-solver +//@[full] check-pass + +#![feature(effects)] +#![allow(incomplete_features)] + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/with-without-next-solver.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/with-without-next-solver.stock.stderr new file mode 100644 index 0000000000000..20448f51de22c --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/with-without-next-solver.stock.stderr @@ -0,0 +1,7 @@ +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: aborting due to 1 previous error + diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/generic-bound.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/generic-bound.stderr index 7905abfa40ed6..2baac1d2a168e 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/generic-bound.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/generic-bound.stderr @@ -1,20 +1,24 @@ +error: const `impl` for trait `Add` which is not marked with `#[const_trait]` + --> $DIR/generic-bound.rs:16:15 + | +LL | impl const std::ops::Add for S { + | ^^^^^^^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + error[E0015]: cannot call non-const operator in constant functions --> $DIR/generic-bound.rs:25:5 | LL | arg + arg | ^^^^^^^^^ | -note: impl defined here, but it is not `const` - --> $DIR/generic-bound.rs:16:1 - | -LL | impl const std::ops::Add for S { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants help: add `#![feature(effects)]` to the crate attributes to enable | LL + #![feature(effects)] | -error: aborting due to 1 previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/hir-const-check.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/hir-const-check.stderr index 416ba248a5f31..598129d8694e0 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/hir-const-check.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/hir-const-check.stderr @@ -17,6 +17,11 @@ LL | Some(())?; = help: add `#![feature(const_try)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error; 1 warning emitted +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: aborting due to 2 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-119717-constant-lifetime.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-119717-constant-lifetime.rs new file mode 100644 index 0000000000000..c2f452a9925c6 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-119717-constant-lifetime.rs @@ -0,0 +1,15 @@ +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects, try_trait_v2)] + +use std::ops::FromResidual; + +impl const FromResidual for T { + //~^ ERROR const `impl` for trait `FromResidual` which is not marked with `#[const_trait]` + //~| type parameter `T` must be used as the type parameter for some local type + fn from_residual(t: T) -> _ { + //~^ the placeholder `_` is not allowed + t + } +} + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-119717-constant-lifetime.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-119717-constant-lifetime.stderr new file mode 100644 index 0000000000000..50cdded8d5114 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-119717-constant-lifetime.stderr @@ -0,0 +1,38 @@ +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: const `impl` for trait `FromResidual` which is not marked with `#[const_trait]` + --> $DIR/ice-119717-constant-lifetime.rs:6:15 + | +LL | impl const FromResidual for T { + | ^^^^^^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/ice-119717-constant-lifetime.rs:6:6 + | +LL | impl const FromResidual for T { + | ^ type parameter `T` must be used as the type parameter for some local type + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/ice-119717-constant-lifetime.rs:9:31 + | +LL | fn from_residual(t: T) -> _ { + | ^ not allowed in type signatures + | +help: try replacing `_` with the type in the corresponding trait method signature + | +LL | fn from_residual(t: T) -> T { + | ~ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0121, E0210. +For more information about an error, try `rustc --explain E0121`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-120503-async-const-method.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-120503-async-const-method.stderr index 011232f30b8a6..1f309e1e85446 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-120503-async-const-method.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-120503-async-const-method.stderr @@ -55,6 +55,11 @@ LL | #![feature(effects)] = note: see issue #102090 for more information = note: `#[warn(incomplete_features)]` on by default +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + error[E0425]: cannot find function `main8` in this scope --> $DIR/ice-120503-async-const-method.rs:13:9 | @@ -95,7 +100,7 @@ LL | async const fn bar(&self) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to 6 previous errors; 1 warning emitted +error: aborting due to 7 previous errors; 1 warning emitted Some errors have detailed explanations: E0379, E0391, E0407, E0425. For more information about an error, try `rustc --explain E0379`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-121536-const-method.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-121536-const-method.stderr index 4fe88f263c81b..29187654c3cc7 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-121536-const-method.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-121536-const-method.stderr @@ -23,6 +23,11 @@ LL | #![feature(const_trait_impl, effects)] = note: see issue #102090 for more information = note: `#[warn(incomplete_features)]` on by default -error: aborting due to 1 previous error; 1 warning emitted +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: aborting due to 2 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0379`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-123664-unexpected-bound-var.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-123664-unexpected-bound-var.rs new file mode 100644 index 0000000000000..64634e7b7ac30 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-123664-unexpected-bound-var.rs @@ -0,0 +1,7 @@ +#![allow(incomplete_features)] +#![feature(generic_const_exprs, const_trait_impl, effects)] + +const fn with_positive() {} +//~^ ERROR `~const` can only be applied to `#[const_trait]` traits + +pub fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-123664-unexpected-bound-var.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-123664-unexpected-bound-var.stderr new file mode 100644 index 0000000000000..c937430a1ca19 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-123664-unexpected-bound-var.stderr @@ -0,0 +1,13 @@ +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/ice-123664-unexpected-bound-var.rs:4:34 + | +LL | const fn with_positive() {} + | ^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-124857-combine-effect-const-infer-vars.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-124857-combine-effect-const-infer-vars.rs new file mode 100644 index 0000000000000..d4fcbfb1b83e6 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-124857-combine-effect-const-infer-vars.rs @@ -0,0 +1,14 @@ +//@ compile-flags: -Znext-solver=coherence + +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] + +#[const_trait] +trait Foo {} + +impl const Foo for i32 {} + +impl const Foo for T where T: ~const Foo {} +//~^ ERROR conflicting implementations of trait `Foo` for type `i32` + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-124857-combine-effect-const-infer-vars.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-124857-combine-effect-const-infer-vars.stderr new file mode 100644 index 0000000000000..284757c1a8977 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-124857-combine-effect-const-infer-vars.stderr @@ -0,0 +1,17 @@ +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error[E0119]: conflicting implementations of trait `Foo` for type `i32` + --> $DIR/ice-124857-combine-effect-const-infer-vars.rs:11:1 + | +LL | impl const Foo for i32 {} + | ---------------------- first implementation here +LL | +LL | impl const Foo for T where T: ~const Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-126148-failed-to-normalize.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-126148-failed-to-normalize.rs new file mode 100644 index 0000000000000..717c0e7c08829 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-126148-failed-to-normalize.rs @@ -0,0 +1,28 @@ +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects, try_trait_v2, const_try)] +use std::ops::{FromResidual, Try}; + +struct TryMe; +struct Error; + +impl const FromResidual for TryMe {} +//~^ ERROR const `impl` for trait `FromResidual` which is not marked with `#[const_trait]` +//~| ERROR not all trait items implemented + +impl const Try for TryMe { + //~^ ERROR const `impl` for trait `Try` which is not marked with `#[const_trait]` + //~| ERROR not all trait items implemented + type Output = (); + type Residual = Error; +} + +const fn t() -> TryMe { + TryMe?; + TryMe +} + +const _: () = { + t(); +}; + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-126148-failed-to-normalize.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-126148-failed-to-normalize.stderr new file mode 100644 index 0000000000000..e49436c8f0f78 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-126148-failed-to-normalize.stderr @@ -0,0 +1,43 @@ +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: const `impl` for trait `FromResidual` which is not marked with `#[const_trait]` + --> $DIR/ice-126148-failed-to-normalize.rs:8:12 + | +LL | impl const FromResidual for TryMe {} + | ^^^^^^^^^^^^^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error[E0046]: not all trait items implemented, missing: `from_residual` + --> $DIR/ice-126148-failed-to-normalize.rs:8:1 + | +LL | impl const FromResidual for TryMe {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `from_residual` in implementation + | + = help: implement the missing item: `fn from_residual(_: Error) -> Self { todo!() }` + +error: const `impl` for trait `Try` which is not marked with `#[const_trait]` + --> $DIR/ice-126148-failed-to-normalize.rs:12:12 + | +LL | impl const Try for TryMe { + | ^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error[E0046]: not all trait items implemented, missing: `from_output`, `branch` + --> $DIR/ice-126148-failed-to-normalize.rs:12:1 + | +LL | impl const Try for TryMe { + | ^^^^^^^^^^^^^^^^^^^^^^^^ missing `from_output`, `branch` in implementation + | + = help: implement the missing item: `fn from_output(_: ::Output) -> Self { todo!() }` + = help: implement the missing item: `fn branch(self) -> ControlFlow<::Residual, ::Output> { todo!() }` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs index 6df9696f2cbd7..49741ca24c7e7 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs @@ -1,4 +1,5 @@ -#![feature(const_trait_impl)] +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] #[const_trait] trait Tr { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr index 36c8163f1c567..2ea203627f435 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr @@ -1,5 +1,10 @@ +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + error[E0046]: not all trait items implemented, missing: `req` - --> $DIR/impl-with-default-fn-fail.rs:12:1 + --> $DIR/impl-with-default-fn-fail.rs:13:1 | LL | fn req(&self); | -------------- `req` from trait @@ -7,6 +12,6 @@ LL | fn req(&self); LL | impl const Tr for u16 { | ^^^^^^^^^^^^^^^^^^^^^ missing `req` in implementation -error: aborting due to 1 previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs index c6fab4aabb6b7..2c375036941c0 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs @@ -1,6 +1,7 @@ //@ check-pass - -#![feature(const_trait_impl)] +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] #[const_trait] trait Tr { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.nn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.nn.stderr new file mode 100644 index 0000000000000..4a949e90d8554 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.nn.stderr @@ -0,0 +1,9 @@ +error[E0271]: type mismatch resolving `<() as Index>::Output == &mut <() as Index>::Output` + --> $DIR/issue-100222.rs:34:12 + | +LL | fn foo(&mut self, x: ::Output) -> ::Output + | ^^^^^^^^^ types differ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.ny.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.ny.stderr new file mode 100644 index 0000000000000..1bfce48d26a2d --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.ny.stderr @@ -0,0 +1,9 @@ +error[E0271]: type mismatch resolving `<() as Index>::Output == &mut <() as Index>::Output` + --> $DIR/issue-100222.rs:25:12 + | +LL | fn foo(&mut self, x: ::Output) -> ::Output + | ^^^^^^^^^ types differ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.rs index 2a40a1b86ca28..7949772a2b4e9 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.rs @@ -1,6 +1,8 @@ //@ revisions: nn ny yn yy -//@ check-pass -#![feature(const_trait_impl, associated_type_defaults, const_mut_refs)] +//@ known-bug: #110395 +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects, associated_type_defaults, const_mut_refs)] #[cfg_attr(any(yn, yy), const_trait)] pub trait Index { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.yn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.yn.stderr new file mode 100644 index 0000000000000..4a949e90d8554 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.yn.stderr @@ -0,0 +1,9 @@ +error[E0271]: type mismatch resolving `<() as Index>::Output == &mut <() as Index>::Output` + --> $DIR/issue-100222.rs:34:12 + | +LL | fn foo(&mut self, x: ::Output) -> ::Output + | ^^^^^^^^^ types differ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.yy.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.yy.stderr new file mode 100644 index 0000000000000..1bfce48d26a2d --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.yy.stderr @@ -0,0 +1,9 @@ +error[E0271]: type mismatch resolving `<() as Index>::Output == &mut <() as Index>::Output` + --> $DIR/issue-100222.rs:25:12 + | +LL | fn foo(&mut self, x: ::Output) -> ::Output + | ^^^^^^^^^ types differ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.rs index 36c82dfe68485..b8b9e07b3bd60 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.rs @@ -1,5 +1,7 @@ +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] #![feature(const_fmt_arguments_new)] -#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +#![feature(const_trait_impl, effects)] #[const_trait] trait Tr { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.stderr index 9da31486faaff..9e6348d37ed5e 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.stderr @@ -1,14 +1,5 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-79450.rs:2:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - error[E0015]: cannot call non-const fn `_print` in constant functions - --> $DIR/issue-79450.rs:9:9 + --> $DIR/issue-79450.rs:11:9 | LL | println!("lul"); | ^^^^^^^^^^^^^^^ @@ -16,6 +7,6 @@ LL | println!("lul"); = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs index 825ddb6a5cdb9..e666355db6ffc 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs @@ -1,8 +1,10 @@ // Regression test for #92230. // //@ check-pass +//@ compile-flags: -Znext-solver -#![feature(const_trait_impl)] +#![feature(const_trait_impl, effects)] +#![allow(incomplete_features)] #[const_trait] pub trait Super {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.stderr index ae76cab2f2e66..de4783bdb3fe6 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.stderr @@ -4,5 +4,28 @@ error: `~const` can only be applied to `#[const_trait]` traits LL | impl const Convert for A where B: ~const From { | ^^^^^^^ -error: aborting due to 1 previous error +error[E0049]: method `to` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/non-const-op-in-closure-in-const.rs:5:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Convert { +LL | fn to(self) -> T; + | - expected 0 const parameters + +error[E0015]: cannot call non-const fn `>::from` in constant functions + --> $DIR/non-const-op-in-closure-in-const.rs:12:9 + | +LL | B::from(self) + | ^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + +error: aborting due to 3 previous errors +Some errors have detailed explanations: E0015, E0049. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs index fe4df09342f77..69dcb403aa908 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs @@ -1,6 +1,6 @@ // Tests that trait bounds on specializing trait impls must be `~const` if the // same bound is present on the default impl and is `~const` there. -//@ check-pass +//@ known-bug: #110395 // FIXME(effects) ^ should error #![feature(const_trait_impl)] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.stderr new file mode 100644 index 0000000000000..b4c4cf0a89059 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.stderr @@ -0,0 +1,41 @@ +error[E0049]: method `bar` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/const-default-bound-non-const-specialized-bound.rs:16:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Bar { +LL | fn bar(); + | - expected 0 const parameters + +error: cannot specialize on const impl with non-const impl + --> $DIR/const-default-bound-non-const-specialized-bound.rs:28:1 + | +LL | / impl Bar for T +LL | | where +LL | | T: Foo, //FIXME ~ ERROR missing `~const` qualifier +LL | | T: Specialize, + | |__________________^ + +error[E0049]: method `baz` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/const-default-bound-non-const-specialized-bound.rs:36:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Baz { +LL | fn baz(); + | - expected 0 const parameters + +error[E0049]: method `baz` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/const-default-bound-non-const-specialized-bound.rs:36:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Baz { +LL | fn baz(); + | - expected 0 const parameters + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0049`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs index c653e62032e6e..a48a50b9e5ce4 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs @@ -1,9 +1,10 @@ // Tests that a const default trait impl can be specialized by another const // trait impl and that the specializing impl will be used during const-eval. -//@ run-pass +//@ known-bug: #110395 +// FIXME(effects) run-pass -#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +#![feature(const_trait_impl)] #![feature(min_specialization)] #[const_trait] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.stderr index f533fb61aad75..cabf201405f55 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.stderr @@ -1,11 +1,36 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/const-default-const-specialized.rs:6:30 +error[E0049]: method `value` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/const-default-const-specialized.rs:10:1 | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Value { +LL | fn value() -> u32; + | - expected 0 const parameters + +error[E0049]: method `value` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/const-default-const-specialized.rs:10:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Value { +LL | fn value() -> u32; + | - expected 0 const parameters + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0015]: cannot call non-const fn `::value` in constant functions + --> $DIR/const-default-const-specialized.rs:16:5 + | +LL | T::value() + | ^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default -warning: 1 warning emitted +error: aborting due to 3 previous errors +Some errors have detailed explanations: E0015, E0049. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.stderr index 363fbee1f8bfb..c51d169dd3397 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.stderr @@ -7,11 +7,16 @@ LL | #![feature(const_trait_impl, effects)] = note: see issue #102090 for more information = note: `#[warn(incomplete_features)]` on by default +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + error: cannot specialize on const impl with non-const impl --> $DIR/const-default-impl-non-const-specialized-impl.rs:19:1 | LL | impl Value for FortyTwo { | ^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 2 previous errors; 1 warning emitted diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/default-keyword.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/default-keyword.rs index bc45a70777ca5..d9ffd237dcefd 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/default-keyword.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/default-keyword.rs @@ -1,4 +1,5 @@ -//@ check-pass +//@ known-bug: #110395 +// FIXME check-pass #![feature(const_trait_impl)] #![feature(min_specialization)] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/default-keyword.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/default-keyword.stderr new file mode 100644 index 0000000000000..52c8708f2c88d --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/default-keyword.stderr @@ -0,0 +1,12 @@ +error[E0049]: method `foo` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/default-keyword.rs:7:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Foo { +LL | fn foo(); + | - expected 0 const parameters + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0049`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.rs index d80370aee8209..219e5f3a600c1 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.rs @@ -1,6 +1,7 @@ // Tests that `~const` trait bounds can be used to specialize const trait impls. -//@ check-pass +//@ known-bug: #110395 +// FIXME check-pass #![feature(const_trait_impl)] #![feature(rustc_attrs)] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.stderr new file mode 100644 index 0000000000000..1aa34637ca482 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.stderr @@ -0,0 +1,43 @@ +error[E0049]: method `foo` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/issue-95186-specialize-on-tilde-const.rs:14:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Foo { +LL | fn foo(); + | - expected 0 const parameters + +error[E0049]: method `foo` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/issue-95186-specialize-on-tilde-const.rs:14:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Foo { +LL | fn foo(); + | - expected 0 const parameters + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0049]: method `bar` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/issue-95186-specialize-on-tilde-const.rs:30:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Bar { +LL | fn bar() {} + | - expected 0 const parameters + +error[E0049]: method `bar` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/issue-95186-specialize-on-tilde-const.rs:30:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Bar { +LL | fn bar() {} + | - expected 0 const parameters + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0049`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.rs index d97469edaf97f..7514baa2fd554 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.rs @@ -2,7 +2,8 @@ // `T: Foo` in the default impl for the purposes of specialization (i.e., it // does not think that the user is attempting to specialize on trait `Foo`). -//@ check-pass +//@ known-bug: #110395 +// FIXME check-pass #![feature(rustc_attrs)] #![feature(min_specialization)] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.stderr new file mode 100644 index 0000000000000..0e0f391b0865e --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.stderr @@ -0,0 +1,43 @@ +error[E0049]: method `bar` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/issue-95187-same-trait-bound-different-constness.rs:18:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Bar { +LL | fn bar(); + | - expected 0 const parameters + +error[E0049]: method `bar` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/issue-95187-same-trait-bound-different-constness.rs:18:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Bar { +LL | fn bar(); + | - expected 0 const parameters + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0049]: method `baz` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/issue-95187-same-trait-bound-different-constness.rs:38:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Baz { +LL | fn baz(); + | - expected 0 const parameters + +error[E0049]: method `baz` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/issue-95187-same-trait-bound-different-constness.rs:38:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Baz { +LL | fn baz(); + | - expected 0 const parameters + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0049`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.rs index fc8fc3f2a1d9c..912b35095f918 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.rs @@ -1,9 +1,9 @@ // Tests that a non-const default impl can be specialized by a const trait impl, // but that the default impl cannot be used in a const context. //@ known-bug: #110395 -// FIXME run-pass +// FIXME(effects) run-pass -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #![feature(min_specialization)] #[const_trait] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr index bcccc855aab52..d49beb932591c 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr @@ -1,21 +1,36 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/non-const-default-const-specialized.rs:6:30 +error[E0049]: method `value` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/non-const-default-const-specialized.rs:9:1 | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Value { +LL | fn value() -> u32; + | - expected 0 const parameters + +error[E0049]: method `value` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/non-const-default-const-specialized.rs:9:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Value { +LL | fn value() -> u32; + | - expected 0 const parameters | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0119]: conflicting implementations of trait `Value` for type `FortyTwo` - --> $DIR/non-const-default-const-specialized.rs:27:1 +error[E0015]: cannot call non-const fn `::value` in constant functions + --> $DIR/non-const-default-const-specialized.rs:15:5 + | +LL | T::value() + | ^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] | -LL | impl Value for T { - | ------------------- first implementation here -... -LL | impl const Value for FortyTwo { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `FortyTwo` -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0119`. +Some errors have detailed explanations: E0015, E0049. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.rs index 5218ea925661e..c1fe42b975127 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.rs @@ -1,4 +1,4 @@ -#![feature(const_trait_impl, effects, min_specialization, rustc_attrs)] +#![feature(const_trait_impl, min_specialization, rustc_attrs)] //@ known-bug: #110395 #[rustc_specialization_trait] #[const_trait] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr index 7404b6a8b11f2..d082cd6de6097 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr @@ -1,31 +1,36 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/specializing-constness-2.rs:1:30 +error[E0049]: method `a` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/specializing-constness-2.rs:9:1 | -LL | #![feature(const_trait_impl, effects, min_specialization, rustc_attrs)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | pub trait A { +LL | fn a() -> u32; + | - expected 0 const parameters -error[E0119]: conflicting implementations of trait `A` - --> $DIR/specializing-constness-2.rs:20:1 +error[E0049]: method `a` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/specializing-constness-2.rs:9:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | pub trait A { +LL | fn a() -> u32; + | - expected 0 const parameters | -LL | impl A for T { - | ------------------------ first implementation here -... -LL | impl const A for T { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0308]: mismatched types +error[E0015]: cannot call non-const fn `::a` in constant functions --> $DIR/specializing-constness-2.rs:27:5 | LL | ::a(); - | ^^^^^^^^^^^^^ expected `host`, found `true` + | ^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] | - = note: expected constant `host` - found constant `true` -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0119, E0308. -For more information about an error, try `rustc --explain E0119`. +Some errors have detailed explanations: E0015, E0049. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.rs index 3aabaf137d54c..4501a218ad723 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.rs @@ -22,6 +22,8 @@ impl const A for T { impl A for T { //~^ ERROR: cannot specialize +//~| ERROR: cannot specialize +//~| ERROR: cannot specialize //FIXME(effects) ~| ERROR: missing `~const` qualifier fn a() -> u32 { 3 diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.stderr index 226295bf949df..90721af8e5aab 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.stderr @@ -7,11 +7,28 @@ LL | #![feature(const_trait_impl, effects, min_specialization, rustc_attrs)] = note: see issue #102090 for more information = note: `#[warn(incomplete_features)]` on by default +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + error: cannot specialize on const impl with non-const impl --> $DIR/specializing-constness.rs:23:1 | LL | impl A for T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error; 1 warning emitted +error: cannot specialize on trait `Compat` + --> $DIR/specializing-constness.rs:23:16 + | +LL | impl A for T { + | ^^^ + +error: cannot specialize on trait `Compat` + --> $DIR/specializing-constness.rs:23:9 + | +LL | impl A for T { + | ^^^^ + +error: aborting due to 4 previous errors; 1 warning emitted diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.rs index 460c2ef617438..f87e723472ad8 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.rs @@ -1,7 +1,9 @@ //@ revisions: stable unstable +//@ compile-flags: -Znext-solver #![cfg_attr(unstable, feature(unstable))] // The feature from the ./auxiliary/staged-api.rs file. -#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +#![feature(const_trait_impl, effects)] +#![allow(incomplete_features)] #![feature(staged_api)] #![stable(feature = "rust1", since = "1.0.0")] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.stable.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.stable.stderr index 0604b22ecbb3e..6c07a253f5b09 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.stable.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.stable.stderr @@ -1,14 +1,5 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/staged-api.rs:4:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - error: trait implementations cannot be const stable yet - --> $DIR/staged-api.rs:19:1 + --> $DIR/staged-api.rs:21:1 | LL | / impl const MyTrait for Foo { LL | | @@ -19,7 +10,7 @@ LL | | } = note: see issue #67792 for more information error: function has missing const stability attribute - --> $DIR/staged-api.rs:41:1 + --> $DIR/staged-api.rs:43:1 | LL | / pub const fn const_context_not_const_stable() { LL | | @@ -31,7 +22,7 @@ LL | | } | |_^ error: `::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:32:5 + --> $DIR/staged-api.rs:34:5 | LL | Unstable::func(); | ^^^^^^^^^^^^^^^^ @@ -39,7 +30,7 @@ LL | Unstable::func(); = help: add `#![feature(unstable)]` to the crate attributes to enable error: `::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:43:5 + --> $DIR/staged-api.rs:45:5 | LL | Unstable::func(); | ^^^^^^^^^^^^^^^^ @@ -47,12 +38,12 @@ LL | Unstable::func(); = help: add `#![feature(unstable)]` to the crate attributes to enable error: `::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:53:5 + --> $DIR/staged-api.rs:55:5 | LL | Unstable::func(); | ^^^^^^^^^^^^^^^^ | = help: const-stable functions can only call other const-stable functions -error: aborting due to 5 previous errors; 1 warning emitted +error: aborting due to 5 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.unstable.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.unstable.stderr index b53e7b6f6acec..1c772f13dd511 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.unstable.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.unstable.stderr @@ -1,14 +1,5 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/staged-api.rs:4:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - error: `::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:34:5 + --> $DIR/staged-api.rs:36:5 | LL | Foo::func(); | ^^^^^^^^^^^ @@ -16,7 +7,7 @@ LL | Foo::func(); = help: add `#![feature(foo)]` to the crate attributes to enable error: `::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:45:5 + --> $DIR/staged-api.rs:47:5 | LL | Foo::func(); | ^^^^^^^^^^^ @@ -24,7 +15,7 @@ LL | Foo::func(); = help: add `#![feature(foo)]` to the crate attributes to enable error: `::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:53:5 + --> $DIR/staged-api.rs:55:5 | LL | Unstable::func(); | ^^^^^^^^^^^^^^^^ @@ -32,7 +23,7 @@ LL | Unstable::func(); = help: const-stable functions can only call other const-stable functions error: `::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:55:5 + --> $DIR/staged-api.rs:57:5 | LL | Foo::func(); | ^^^^^^^^^^^ @@ -40,12 +31,12 @@ LL | Foo::func(); = help: const-stable functions can only call other const-stable functions error: `const_context_not_const_stable` is not yet stable as a const fn - --> $DIR/staged-api.rs:57:5 + --> $DIR/staged-api.rs:59:5 | LL | const_context_not_const_stable() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: const-stable functions can only call other const-stable functions -error: aborting due to 5 previous errors; 1 warning emitted +error: aborting due to 5 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr index 3a36a5b750932..48bb1907be2eb 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr @@ -1,32 +1,23 @@ error: `~const` is not allowed here - --> $DIR/super-traits-fail-2.rs:10:12 + --> $DIR/super-traits-fail-2.rs:12:12 | LL | trait Bar: ~const Foo {} | ^^^^^^ | note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds - --> $DIR/super-traits-fail-2.rs:10:1 + --> $DIR/super-traits-fail-2.rs:12:1 | LL | trait Bar: ~const Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/super-traits-fail-2.rs:1:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-2.rs:10:19 + --> $DIR/super-traits-fail-2.rs:12:19 | LL | trait Bar: ~const Foo {} | ^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-2.rs:10:19 + --> $DIR/super-traits-fail-2.rs:12:19 | LL | trait Bar: ~const Foo {} | ^^^ @@ -34,12 +25,12 @@ LL | trait Bar: ~const Foo {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-2.rs:10:19 + --> $DIR/super-traits-fail-2.rs:12:19 | LL | trait Bar: ~const Foo {} | ^^^ | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 4 previous errors; 1 warning emitted +error: aborting due to 4 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr index beb931570cb85..029c3b4bde3ec 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr @@ -1,20 +1,11 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/super-traits-fail-2.rs:1:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-2.rs:10:19 + --> $DIR/super-traits-fail-2.rs:12:19 | LL | trait Bar: ~const Foo {} | ^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-2.rs:10:19 + --> $DIR/super-traits-fail-2.rs:12:19 | LL | trait Bar: ~const Foo {} | ^^^ @@ -22,12 +13,12 @@ LL | trait Bar: ~const Foo {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-2.rs:10:19 + --> $DIR/super-traits-fail-2.rs:12:19 | LL | trait Bar: ~const Foo {} | ^^^ | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.rs index 2f26eebbe32f9..0d659744e700e 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.rs @@ -1,4 +1,6 @@ -#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] //@ revisions: yy yn ny nn #[cfg_attr(any(yy, yn), const_trait)] @@ -15,7 +17,7 @@ trait Bar: ~const Foo {} const fn foo(x: &T) { x.a(); - //[yy,yn]~^ ERROR mismatched types + //[yy,yn]~^ ERROR the trait bound // FIXME(effects) diagnostic } diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr index f96e6fb4ae468..d4064e01ef10c 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr @@ -1,33 +1,34 @@ error: `~const` is not allowed here - --> $DIR/super-traits-fail-2.rs:10:12 + --> $DIR/super-traits-fail-2.rs:12:12 | LL | trait Bar: ~const Foo {} | ^^^^^^ | note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds - --> $DIR/super-traits-fail-2.rs:10:1 + --> $DIR/super-traits-fail-2.rs:12:1 | LL | trait Bar: ~const Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/super-traits-fail-2.rs:1:30 +error[E0277]: the trait bound `Foo::{synthetic#0}: ~const Compat` is not satisfied + --> $DIR/super-traits-fail-2.rs:19:7 | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ +LL | x.a(); + | ^ the trait `~const Compat` is not implemented for `Foo::{synthetic#0}` | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - -error[E0308]: mismatched types - --> $DIR/super-traits-fail-2.rs:17:5 +note: required by a bound in `Foo::a` + --> $DIR/super-traits-fail-2.rs:6:25 | -LL | x.a(); - | ^^^^^ expected `host`, found `true` +LL | #[cfg_attr(any(yy, yn), const_trait)] + | ^^^^^^^^^^^ required by this bound in `Foo::a` +LL | trait Foo { +LL | fn a(&self); + | - required by a bound in this associated function +help: consider further restricting the associated type | - = note: expected constant `host` - found constant `true` +LL | const fn foo(x: &T) where Foo::{synthetic#0}: ~const Compat { + | +++++++++++++++++++++++++++++++++++++++ -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr index ffc259e590e80..9f9f96c6b486b 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr @@ -1,21 +1,22 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/super-traits-fail-2.rs:1:30 +error[E0277]: the trait bound `Foo::{synthetic#0}: ~const Compat` is not satisfied + --> $DIR/super-traits-fail-2.rs:19:7 | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ +LL | x.a(); + | ^ the trait `~const Compat` is not implemented for `Foo::{synthetic#0}` | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - -error[E0308]: mismatched types - --> $DIR/super-traits-fail-2.rs:17:5 +note: required by a bound in `Foo::a` + --> $DIR/super-traits-fail-2.rs:6:25 | -LL | x.a(); - | ^^^^^ expected `host`, found `true` +LL | #[cfg_attr(any(yy, yn), const_trait)] + | ^^^^^^^^^^^ required by this bound in `Foo::a` +LL | trait Foo { +LL | fn a(&self); + | - required by a bound in this associated function +help: consider further restricting the associated type | - = note: expected constant `host` - found constant `true` +LL | const fn foo(x: &T) where Foo::{synthetic#0}: ~const Compat { + | +++++++++++++++++++++++++++++++++++++++ -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr index cde4b1ff77f35..f40583f0ca57f 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr @@ -1,32 +1,23 @@ error: `~const` is not allowed here - --> $DIR/super-traits-fail-3.rs:12:12 + --> $DIR/super-traits-fail-3.rs:14:12 | LL | trait Bar: ~const Foo {} | ^^^^^^ | note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds - --> $DIR/super-traits-fail-3.rs:12:1 + --> $DIR/super-traits-fail-3.rs:14:1 | LL | trait Bar: ~const Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/super-traits-fail-3.rs:1:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:12:19 + --> $DIR/super-traits-fail-3.rs:14:19 | LL | trait Bar: ~const Foo {} | ^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:12:19 + --> $DIR/super-traits-fail-3.rs:14:19 | LL | trait Bar: ~const Foo {} | ^^^ @@ -34,7 +25,7 @@ LL | trait Bar: ~const Foo {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:12:19 + --> $DIR/super-traits-fail-3.rs:14:19 | LL | trait Bar: ~const Foo {} | ^^^ @@ -42,10 +33,10 @@ LL | trait Bar: ~const Foo {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:18:24 + --> $DIR/super-traits-fail-3.rs:20:24 | LL | const fn foo(x: &T) { | ^^^ -error: aborting due to 5 previous errors; 1 warning emitted +error: aborting due to 5 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr index 6f1840181481c..3f6dfa7b00896 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr @@ -1,20 +1,11 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/super-traits-fail-3.rs:1:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:12:19 + --> $DIR/super-traits-fail-3.rs:14:19 | LL | trait Bar: ~const Foo {} | ^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:12:19 + --> $DIR/super-traits-fail-3.rs:14:19 | LL | trait Bar: ~const Foo {} | ^^^ @@ -22,12 +13,12 @@ LL | trait Bar: ~const Foo {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:12:19 + --> $DIR/super-traits-fail-3.rs:14:19 | LL | trait Bar: ~const Foo {} | ^^^ | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs index f7e85902a41b2..6694351265007 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs @@ -1,7 +1,9 @@ -#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] //@ revisions: yy yn ny nn -//@[yy] check-pass +//@[yy] known-bug: #110395 #[cfg_attr(any(yy, yn), const_trait)] trait Foo { @@ -18,7 +20,7 @@ trait Bar: ~const Foo {} const fn foo(x: &T) { //[yn,nn]~^ ERROR: `~const` can only be applied to `#[const_trait]` x.a(); - //[yn]~^ ERROR: mismatched types + //[yn]~^ ERROR: the trait bound } fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr index b0a3b39631dca..0b48633a10e20 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr @@ -1,39 +1,40 @@ error: `~const` is not allowed here - --> $DIR/super-traits-fail-3.rs:12:12 + --> $DIR/super-traits-fail-3.rs:14:12 | LL | trait Bar: ~const Foo {} | ^^^^^^ | note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds - --> $DIR/super-traits-fail-3.rs:12:1 + --> $DIR/super-traits-fail-3.rs:14:1 | LL | trait Bar: ~const Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/super-traits-fail-3.rs:1:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:18:24 + --> $DIR/super-traits-fail-3.rs:20:24 | LL | const fn foo(x: &T) { | ^^^ -error[E0308]: mismatched types - --> $DIR/super-traits-fail-3.rs:20:5 +error[E0277]: the trait bound `Foo::{synthetic#0}: ~const Compat` is not satisfied + --> $DIR/super-traits-fail-3.rs:22:7 | LL | x.a(); - | ^^^^^ expected `host`, found `true` + | ^ the trait `~const Compat` is not implemented for `Foo::{synthetic#0}` + | +note: required by a bound in `Foo::a` + --> $DIR/super-traits-fail-3.rs:8:25 + | +LL | #[cfg_attr(any(yy, yn), const_trait)] + | ^^^^^^^^^^^ required by this bound in `Foo::a` +LL | trait Foo { +LL | fn a(&self); + | - required by a bound in this associated function +help: consider further restricting the associated type | - = note: expected constant `host` - found constant `true` +LL | const fn foo(x: &T) where Foo::{synthetic#0}: ~const Compat { + | +++++++++++++++++++++++++++++++++++++++ -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yy.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yy.stderr index e354c66919ec6..ea0e6c690b72b 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yy.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yy.stderr @@ -1,11 +1,22 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/super-traits-fail-3.rs:1:30 +error[E0277]: the trait bound `Foo::{synthetic#0}: ~const Compat` is not satisfied + --> $DIR/super-traits-fail-3.rs:22:7 | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ +LL | x.a(); + | ^ the trait `~const Compat` is not implemented for `Foo::{synthetic#0}` | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default +note: required by a bound in `Foo::a` + --> $DIR/super-traits-fail-3.rs:8:25 + | +LL | #[cfg_attr(any(yy, yn), const_trait)] + | ^^^^^^^^^^^ required by this bound in `Foo::a` +LL | trait Foo { +LL | fn a(&self); + | - required by a bound in this associated function +help: consider further restricting the associated type + | +LL | const fn foo(x: &T) where Foo::{synthetic#0}: ~const Compat { + | +++++++++++++++++++++++++++++++++++++++ -warning: 1 warning emitted +error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail.rs index 0bbf2dabffe57..637a24f53bc63 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail.rs @@ -1,7 +1,8 @@ //@ check-pass -//@ known-bug: #110395 +//@ compile-flags: -Znext-solver -#![feature(const_trait_impl)] +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] #[const_trait] trait Foo { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.rs index cfbb8e9f6be57..fbe89b00b974b 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.rs @@ -1,5 +1,8 @@ -//@ check-pass -#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +// FIXME(effects) check-pass +//@ known-bug: #110395 +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] #[const_trait] trait Foo { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.stderr index 2ff1a880d84f0..5b6b39ee05ef6 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.stderr @@ -1,11 +1,22 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/super-traits.rs:2:30 +error[E0277]: the trait bound `Foo::{synthetic#0}: ~const Compat` is not satisfied + --> $DIR/super-traits.rs:23:7 | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ +LL | t.a(); + | ^ the trait `~const Compat` is not implemented for `Foo::{synthetic#0}` | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default +note: required by a bound in `Foo::a` + --> $DIR/super-traits.rs:7:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ required by this bound in `Foo::a` +LL | trait Foo { +LL | fn a(&self); + | - required by a bound in this associated function +help: consider further restricting the associated type + | +LL | const fn foo(t: &T) where Foo::{synthetic#0}: ~const Compat { + | +++++++++++++++++++++++++++++++++++++++ -warning: 1 warning emitted +error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr index b479793814cb9..73526a26e081e 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr @@ -22,6 +22,11 @@ note: this function is not `const`, so it cannot have `~const` trait bounds LL | fn bar(_: Foo) -> Foo<{ A::add(N) }> { | ^^^ +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + error[E0308]: mismatched types --> $DIR/tilde-const-and-const-params.rs:27:61 | @@ -40,6 +45,6 @@ LL | fn add(self) -> Foo<{ A::add(N) }> { = note: expected constant `false` found constant `true` -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-assoc-fn-in-trait-impl.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-assoc-fn-in-trait-impl.rs index 86a2bbe35ed7d..8e7202ecaa1ff 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-assoc-fn-in-trait-impl.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-assoc-fn-in-trait-impl.rs @@ -1,7 +1,8 @@ // Regression test for issue #119700. //@ check-pass - -#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] #[const_trait] trait Main { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-assoc-fn-in-trait-impl.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-assoc-fn-in-trait-impl.stderr deleted file mode 100644 index 70019ce57f29e..0000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-assoc-fn-in-trait-impl.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/tilde-const-assoc-fn-in-trait-impl.rs:4:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-inherent-assoc-const-fn.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-inherent-assoc-const-fn.rs index 0f5729e3daf62..71c5d8366b2f4 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-inherent-assoc-const-fn.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-inherent-assoc-const-fn.rs @@ -1,5 +1,7 @@ //@ check-pass -#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] #[const_trait] trait Foo { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-inherent-assoc-const-fn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-inherent-assoc-const-fn.stderr deleted file mode 100644 index 4ec8dac1f0d3a..0000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-inherent-assoc-const-fn.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/tilde-const-inherent-assoc-const-fn.rs:2:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-trait-assoc-tys.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-trait-assoc-tys.rs index c2d3b2036c638..254cf2200d853 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-trait-assoc-tys.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-trait-assoc-tys.rs @@ -1,5 +1,7 @@ //@ check-pass -#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] #[const_trait] trait Trait { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-trait-assoc-tys.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-trait-assoc-tys.stderr deleted file mode 100644 index 1ead23d5c2c1d..0000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-trait-assoc-tys.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/tilde-const-trait-assoc-tys.rs:2:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-default-body-stability.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-default-body-stability.rs index f41e70c99ff8a..b36e9535ca113 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-default-body-stability.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-default-body-stability.rs @@ -1,5 +1,6 @@ //@ known-bug: #110395 - +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] #![feature(staged_api)] #![feature(const_trait_impl, effects)] #![feature(const_t_try)] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-default-body-stability.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-default-body-stability.stderr index adb1b01f08704..49fbef9aaa29f 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-default-body-stability.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-default-body-stability.stderr @@ -1,14 +1,5 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/trait-default-body-stability.rs:4:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - error: const `impl` for trait `Try` which is not marked with `#[const_trait]` - --> $DIR/trait-default-body-stability.rs:18:12 + --> $DIR/trait-default-body-stability.rs:19:12 | LL | impl const Try for T { | ^^^ @@ -17,7 +8,7 @@ LL | impl const Try for T { = note: adding a non-const method body in the future would be a breaking change error: const `impl` for trait `FromResidual` which is not marked with `#[const_trait]` - --> $DIR/trait-default-body-stability.rs:33:12 + --> $DIR/trait-default-body-stability.rs:34:12 | LL | impl const FromResidual for T { | ^^^^^^^^^^^^ @@ -25,112 +16,5 @@ LL | impl const FromResidual for T { = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change -error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates - --> $DIR/trait-default-body-stability.rs:18:6 - | -LL | impl const Try for T { - | ^^^^^ unconstrained const parameter - | - = note: expressions using a const parameter must map each value to a distinct output value - = note: proving the result of expressions other than the parameter are unique is not supported - -error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates - --> $DIR/trait-default-body-stability.rs:33:6 - | -LL | impl const FromResidual for T { - | ^^^^^ unconstrained const parameter - | - = note: expressions using a const parameter must map each value to a distinct output value - = note: proving the result of expressions other than the parameter are unique is not supported - -error[E0284]: type annotations needed - --> $DIR/trait-default-body-stability.rs:33:6 - | -LL | impl const FromResidual for T { - | ^^^^^ cannot infer the value of the constant `_` - | -note: required for `T` to implement `Try` - --> $DIR/trait-default-body-stability.rs:18:12 - | -LL | impl const Try for T { - | ----- ^^^ ^ - | | - | unsatisfied trait bound introduced here - -error[E0284]: type annotations needed - --> $DIR/trait-default-body-stability.rs:44:9 - | -LL | T? - | ^^ cannot infer the value of the constant `_` - | -note: required for `T` to implement `Try` - --> $DIR/trait-default-body-stability.rs:18:12 - | -LL | impl const Try for T { - | ----- ^^^ ^ - | | - | unsatisfied trait bound introduced here - -error[E0284]: type annotations needed - --> $DIR/trait-default-body-stability.rs:44:9 - | -LL | T? - | ^^ cannot infer the value of the constant `_` - | -note: required for `T` to implement `FromResidual` - --> $DIR/trait-default-body-stability.rs:33:12 - | -LL | impl const FromResidual for T { - | ----- ^^^^^^^^^^^^ ^ - | | - | unsatisfied trait bound introduced here - -error[E0284]: type annotations needed - --> $DIR/trait-default-body-stability.rs:44:9 - | -LL | T? - | ^^ cannot infer the value of the constant `_` - | -note: required for `T` to implement `Try` - --> $DIR/trait-default-body-stability.rs:18:12 - | -LL | impl const Try for T { - | ----- ^^^ ^ - | | - | unsatisfied trait bound introduced here - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0284]: type annotations needed - --> $DIR/trait-default-body-stability.rs:44:9 - | -LL | T? - | ^^ cannot infer the value of the constant `_` - | -note: required for `T` to implement `FromResidual` - --> $DIR/trait-default-body-stability.rs:33:12 - | -LL | impl const FromResidual for T { - | ----- ^^^^^^^^^^^^ ^ - | | - | unsatisfied trait bound introduced here - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0284]: type annotations needed - --> $DIR/trait-default-body-stability.rs:44:9 - | -LL | T? - | ^^ cannot infer the value of the constant `_` - | -note: required for `T` to implement `Try` - --> $DIR/trait-default-body-stability.rs:18:12 - | -LL | impl const Try for T { - | ----- ^^^ ^ - | | - | unsatisfied trait bound introduced here - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 10 previous errors; 1 warning emitted +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0207, E0284. -For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.rs index 364ddfcc8ddd5..8ca9b7cc7aa0a 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.rs @@ -1,10 +1,11 @@ +//@ compile-flags: -Znext-solver // Like trait-where-clause.rs, but we are calling from a const context. // Checking the validity of traits' where clauses happen at a later stage. // (`rustc_const_eval` instead of `rustc_hir_analysis`) Therefore one file as a // test is not enough. -//@ known-bug: #110395 -// FIXME check-pass + #![feature(const_trait_impl, effects)] +#![allow(incomplete_features)] #[const_trait] trait Bar {} @@ -19,9 +20,11 @@ trait Foo { const fn test1() { T::a(); T::b(); - //FIXME ~^ ERROR the trait bound + //~^ ERROR mismatched types + //~| ERROR the trait bound T::c::(); - //FIXME ~^ ERROR the trait bound + //~^ ERROR mismatched types + //~| ERROR the trait bound } const fn test2() { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr index 95c32b12241c9..979f1e798e0a7 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr @@ -1,44 +1,60 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/trait-where-clause-const.rs:7:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - -error[E0277]: the trait bound `T: ~const Bar` is not satisfied - --> $DIR/trait-where-clause-const.rs:21:5 +error[E0277]: the trait bound `Foo::{synthetic#0}: Compat` is not satisfied + --> $DIR/trait-where-clause-const.rs:22:5 | LL | T::b(); - | ^ the trait `~const Bar` is not implemented for `T` + | ^ the trait `Compat` is not implemented for `Foo::{synthetic#0}` | note: required by a bound in `Foo::b` - --> $DIR/trait-where-clause-const.rs:15:24 + --> $DIR/trait-where-clause-const.rs:13:1 | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ required by this bound in `Foo::b` +... LL | fn b() where Self: ~const Bar; - | ^^^^^^^^^^ required by this bound in `Foo::b` -help: consider further restricting this bound + | - required by a bound in this associated function +help: consider further restricting the associated type | -LL | const fn test1() { - | ++++++++++++ +LL | const fn test1() where Foo::{synthetic#0}: Compat { + | ++++++++++++++++++++++++++++++++ -error[E0277]: the trait bound `T: ~const Bar` is not satisfied - --> $DIR/trait-where-clause-const.rs:23:12 +error[E0308]: mismatched types + --> $DIR/trait-where-clause-const.rs:22:5 + | +LL | T::b(); + | ^^^^^^ expected `host`, found `true` + | + = note: expected constant `host` + found constant `true` + +error[E0277]: the trait bound `Foo::{synthetic#0}: Compat` is not satisfied + --> $DIR/trait-where-clause-const.rs:25:5 | LL | T::c::(); - | ^ the trait `~const Bar` is not implemented for `T` + | ^ the trait `Compat` is not implemented for `Foo::{synthetic#0}` | note: required by a bound in `Foo::c` - --> $DIR/trait-where-clause-const.rs:16:13 + --> $DIR/trait-where-clause-const.rs:13:1 | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ required by this bound in `Foo::c` +... LL | fn c(); - | ^^^^^^^^^^ required by this bound in `Foo::c` -help: consider further restricting this bound + | - required by a bound in this associated function +help: consider further restricting the associated type + | +LL | const fn test1() where Foo::{synthetic#0}: Compat { + | ++++++++++++++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/trait-where-clause-const.rs:25:5 + | +LL | T::c::(); + | ^^^^^^^^^^^ expected `host`, found `true` | -LL | const fn test1() { - | ++++++++++++ + = note: expected constant `host` + found constant `true` -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.rs index afc5b1c836993..2837c83542999 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.rs @@ -1,6 +1,8 @@ //@ run-pass +//@ compile-flags: -Znext-solver -#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +#![feature(const_trait_impl, effects)] +#![allow(incomplete_features)] #[const_trait] trait Bar { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.stderr deleted file mode 100644 index aef4f569d5e11..0000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/trait-where-clause-run.rs:3:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs index 59ddc2f748ede..cb5cc924bfd34 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs @@ -1,6 +1,7 @@ //@ check-pass - -#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] #[const_trait] trait Foo { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.stderr deleted file mode 100644 index 6e9e948e45cd3..0000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/trait-where-clause-self-referential.rs:3:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.rs index 8f441410c1784..c50c755f667fc 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.rs @@ -1,4 +1,5 @@ // Ensure that we print unsatisfied always-const trait bounds as `const Trait` in diagnostics. +//@ compile-flags: -Znext-solver #![feature(const_trait_impl, effects, generic_const_exprs)] #![allow(incomplete_features)] @@ -17,7 +18,8 @@ impl Trait for Ty { } fn main() { - require::(); //~ ERROR the trait bound `Ty: const Trait` is not satisfied + // FIXME(effects): improve diagnostics on this + require::(); //~ ERROR the trait bound `Trait::{synthetic#0}: const Compat` is not satisfied } struct Container; diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.stderr index 258f95b5c4a89..b9f6c9e883562 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/unsatisfied-const-trait-bound.rs:27:37 + --> $DIR/unsatisfied-const-trait-bound.rs:29:37 | LL | fn accept0(_: Container<{ T::make() }>) {} | ^^^^^^^^^ expected `false`, found `true` @@ -8,7 +8,7 @@ LL | fn accept0(_: Container<{ T::make() }>) {} found constant `true` error[E0308]: mismatched types - --> $DIR/unsatisfied-const-trait-bound.rs:32:50 + --> $DIR/unsatisfied-const-trait-bound.rs:34:50 | LL | const fn accept1(_: Container<{ T::make() }>) {} | ^^^^^^^^^ expected `false`, found `host` @@ -16,15 +16,14 @@ LL | const fn accept1(_: Container<{ T::make() }>) {} = note: expected constant `false` found constant `host` -error[E0277]: the trait bound `Ty: const Trait` is not satisfied - --> $DIR/unsatisfied-const-trait-bound.rs:20:15 +error[E0277]: the trait bound `Trait::{synthetic#0}: const Compat` is not satisfied + --> $DIR/unsatisfied-const-trait-bound.rs:22:15 | LL | require::(); - | ^^ the trait `const Trait` is not implemented for `Ty` + | ^^ the trait `const Compat` is not implemented for `Trait::{synthetic#0}` | - = help: the trait `Trait` is implemented for `Ty` note: required by a bound in `require` - --> $DIR/unsatisfied-const-trait-bound.rs:6:15 + --> $DIR/unsatisfied-const-trait-bound.rs:7:15 | LL | fn require() {} | ^^^^^^^^^^^ required by this bound in `require` diff --git a/tests/ui/simd/dont-invalid-bitcast-masks.rs b/tests/ui/simd/dont-invalid-bitcast-masks.rs new file mode 100644 index 0000000000000..3d8376207cd07 --- /dev/null +++ b/tests/ui/simd/dont-invalid-bitcast-masks.rs @@ -0,0 +1,17 @@ +//@ build-pass +//@ compile-flags: -Copt-level=3 + +// regression test for https://github.com/rust-lang/rust/issues/110722 +// in --release we were optimizing to invalid bitcasts, due to a combination of MIR inlining and +// mostly bad repr(simd) lowering which prevented even basic splats from working +#![crate_type = "rlib"] +#![feature(portable_simd)] +use std::simd::*; +use std::simd::num::*; + +pub unsafe fn mask_to_array(mask: u8) -> [i32; 8] { + let mut output = [0; 8]; + let m = masksizex8::from_bitmask(mask as _); + output.copy_from_slice(&m.to_int().cast::().to_array()); + output +} diff --git a/tests/ui/simd/dont-invalid-bitcast-x86_64.rs b/tests/ui/simd/dont-invalid-bitcast-x86_64.rs new file mode 100644 index 0000000000000..e6e435bcfc902 --- /dev/null +++ b/tests/ui/simd/dont-invalid-bitcast-x86_64.rs @@ -0,0 +1,27 @@ +//@ build-pass +//@ compile-flags: -Copt-level=3 +//@ only-x86_64 +// ignore-tidy-linelength + +// regression test for https://github.com/rust-lang/rust/issues/110707 +// in --release we were optimizing to invalid bitcasts, due to a combination of MIR inlining and +// mostly bad repr(simd) lowering which prevented even basic splats from working + +#![crate_type = "rlib"] +#![feature(portable_simd)] +use std::simd::*; +use std::arch::x86_64::*; + +#[target_feature(enable = "sse4.1")] +pub unsafe fn fast_round_sse(i: f32x8) -> f32x8 { + let a = i.to_array(); + let [low, high]: [[f32; 4]; 2] = + unsafe { std::mem::transmute::<[f32; 8], [[f32; 4]; 2]>(a) }; + + let low = f32x4::from(_mm_round_ps::<{_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC}>(f32x4::from_array(low).into())); + let high = f32x4::from(_mm_round_ps::<{_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC}>(f32x4::from_array(high).into())); + + let a: [f32; 8] = + unsafe { std::mem::transmute::<[[f32; 4]; 2], [f32; 8]>([low.to_array(), high.to_array()]) }; + f32x8::from_array(a) +} diff --git a/tests/ui/specialization/const_trait_impl.stderr b/tests/ui/specialization/const_trait_impl.stderr index fc02f6f8f7433..e39138983c6e6 100644 --- a/tests/ui/specialization/const_trait_impl.stderr +++ b/tests/ui/specialization/const_trait_impl.stderr @@ -1,3 +1,23 @@ +error[E0049]: method `foo` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/const_trait_impl.rs:6:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | pub unsafe trait Sup { +LL | fn foo() -> u32; + | - expected 0 const parameters + +error[E0049]: method `foo` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/const_trait_impl.rs:6:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | pub unsafe trait Sup { +LL | fn foo() -> u32; + | - expected 0 const parameters + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/const_trait_impl.rs:34:16 | @@ -16,6 +36,37 @@ error: `~const` can only be applied to `#[const_trait]` traits LL | impl const A for T { | ^^^^^^^ +error[E0049]: method `a` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/const_trait_impl.rs:29:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | pub trait A { +LL | fn a() -> u32; + | - expected 0 const parameters + +error[E0049]: method `a` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/const_trait_impl.rs:29:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | pub trait A { +LL | fn a() -> u32; + | - expected 0 const parameters + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0049]: method `a` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/const_trait_impl.rs:29:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | pub trait A { +LL | fn a() -> u32; + | - expected 0 const parameters + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error[E0015]: cannot call non-const fn `<() as A>::a` in constants --> $DIR/const_trait_impl.rs:52:23 | @@ -52,6 +103,19 @@ help: add `#![feature(effects)]` to the crate attributes to enable LL + #![feature(effects)] | -error: aborting due to 6 previous errors +error[E0015]: cannot call non-const fn `::foo` in constant functions + --> $DIR/const_trait_impl.rs:48:9 + | +LL | T::foo() + | ^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + +error: aborting due to 12 previous errors -For more information about this error, try `rustc --explain E0015`. +Some errors have detailed explanations: E0015, E0049. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/stability-attribute/missing-const-stability.rs b/tests/ui/stability-attribute/missing-const-stability.rs index 62bb0239168e0..82da18cc9ac2c 100644 --- a/tests/ui/stability-attribute/missing-const-stability.rs +++ b/tests/ui/stability-attribute/missing-const-stability.rs @@ -1,3 +1,4 @@ +//@ compile-flags: -Znext-solver #![feature(staged_api)] #![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete #![stable(feature = "stable", since = "1.0.0")] diff --git a/tests/ui/stability-attribute/missing-const-stability.stderr b/tests/ui/stability-attribute/missing-const-stability.stderr index 4e488124fe394..adf60c3861140 100644 --- a/tests/ui/stability-attribute/missing-const-stability.stderr +++ b/tests/ui/stability-attribute/missing-const-stability.stderr @@ -1,5 +1,5 @@ warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/missing-const-stability.rs:2:30 + --> $DIR/missing-const-stability.rs:3:30 | LL | #![feature(const_trait_impl, effects)] | ^^^^^^^ @@ -8,13 +8,13 @@ LL | #![feature(const_trait_impl, effects)] = note: `#[warn(incomplete_features)]` on by default error: function has missing const stability attribute - --> $DIR/missing-const-stability.rs:6:1 + --> $DIR/missing-const-stability.rs:7:1 | LL | pub const fn foo() {} | ^^^^^^^^^^^^^^^^^^^^^ error: implementation has missing const stability attribute - --> $DIR/missing-const-stability.rs:28:1 + --> $DIR/missing-const-stability.rs:29:1 | LL | / impl const Bar for Foo { LL | | @@ -23,7 +23,7 @@ LL | | } | |_^ error: associated function has missing const stability attribute - --> $DIR/missing-const-stability.rs:15:5 + --> $DIR/missing-const-stability.rs:16:5 | LL | pub const fn foo() {} | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/static/reference-of-mut-static-unsafe-fn.rs b/tests/ui/static/reference-of-mut-static-unsafe-fn.rs deleted file mode 100644 index 5652703a27186..0000000000000 --- a/tests/ui/static/reference-of-mut-static-unsafe-fn.rs +++ /dev/null @@ -1,26 +0,0 @@ -//@ compile-flags: --edition 2024 -Z unstable-options - -fn main() {} - -unsafe fn _foo() { - static mut X: i32 = 1; - static mut Y: i32 = 1; - - let _y = &X; - //~^ ERROR creating a shared reference to a mutable static [E0796] - - let ref _a = X; - //~^ ERROR creating a shared reference to a mutable static [E0796] - - let ref mut _a = X; - //~^ ERROR creating a mutable reference to a mutable static [E0796] - - let (_b, _c) = (&X, &mut Y); - //~^ ERROR creating a shared reference to a mutable static [E0796] - //~^^ ERROR creating a mutable reference to a mutable static [E0796] - - foo(&X); - //~^ ERROR creating a shared reference to a mutable static [E0796] -} - -fn foo<'a>(_x: &'a i32) {} diff --git a/tests/ui/static/reference-of-mut-static-unsafe-fn.stderr b/tests/ui/static/reference-of-mut-static-unsafe-fn.stderr deleted file mode 100644 index 5675d313e0763..0000000000000 --- a/tests/ui/static/reference-of-mut-static-unsafe-fn.stderr +++ /dev/null @@ -1,75 +0,0 @@ -error[E0796]: creating a shared reference to a mutable static - --> $DIR/reference-of-mut-static-unsafe-fn.rs:9:14 - | -LL | let _y = &X; - | ^^ shared reference to mutable static - | - = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior -help: use `addr_of!` instead to create a raw pointer - | -LL | let _y = addr_of!(X); - | ~~~~~~~~~~~ - -error[E0796]: creating a shared reference to a mutable static - --> $DIR/reference-of-mut-static-unsafe-fn.rs:12:18 - | -LL | let ref _a = X; - | ^ shared reference to mutable static - | - = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior -help: use `addr_of!` instead to create a raw pointer - | -LL | let ref _a = addr_of!(X); - | ~~~~~~~~~~~ - -error[E0796]: creating a mutable reference to a mutable static - --> $DIR/reference-of-mut-static-unsafe-fn.rs:15:22 - | -LL | let ref mut _a = X; - | ^ mutable reference to mutable static - | - = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior -help: use `addr_of_mut!` instead to create a raw pointer - | -LL | let ref mut _a = addr_of_mut!(X); - | ~~~~~~~~~~~~~~~ - -error[E0796]: creating a shared reference to a mutable static - --> $DIR/reference-of-mut-static-unsafe-fn.rs:18:21 - | -LL | let (_b, _c) = (&X, &mut Y); - | ^^ shared reference to mutable static - | - = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior -help: use `addr_of!` instead to create a raw pointer - | -LL | let (_b, _c) = (addr_of!(X), &mut Y); - | ~~~~~~~~~~~ - -error[E0796]: creating a mutable reference to a mutable static - --> $DIR/reference-of-mut-static-unsafe-fn.rs:18:25 - | -LL | let (_b, _c) = (&X, &mut Y); - | ^^^^^^ mutable reference to mutable static - | - = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior -help: use `addr_of_mut!` instead to create a raw pointer - | -LL | let (_b, _c) = (&X, addr_of_mut!(Y)); - | ~~~~~~~~~~~~~~~ - -error[E0796]: creating a shared reference to a mutable static - --> $DIR/reference-of-mut-static-unsafe-fn.rs:22:9 - | -LL | foo(&X); - | ^^ shared reference to mutable static - | - = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior -help: use `addr_of!` instead to create a raw pointer - | -LL | foo(addr_of!(X)); - | ~~~~~~~~~~~ - -error: aborting due to 6 previous errors - -For more information about this error, try `rustc --explain E0796`. diff --git a/tests/ui/static/reference-of-mut-static.e2021.stderr b/tests/ui/static/reference-of-mut-static.e2021.stderr deleted file mode 100644 index f7ad51b615711..0000000000000 --- a/tests/ui/static/reference-of-mut-static.e2021.stderr +++ /dev/null @@ -1,91 +0,0 @@ -error: creating a shared reference to mutable static is discouraged - --> $DIR/reference-of-mut-static.rs:16:18 - | -LL | let _y = &X; - | ^^ shared reference to mutable static - | - = note: for more information, see issue #114447 - = note: this will be a hard error in the 2024 edition - = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior -note: the lint level is defined here - --> $DIR/reference-of-mut-static.rs:6:9 - | -LL | #![deny(static_mut_refs)] - | ^^^^^^^^^^^^^^^ -help: use `addr_of!` instead to create a raw pointer - | -LL | let _y = addr_of!(X); - | ~~~~~~~~~~~ - -error: creating a mutable reference to mutable static is discouraged - --> $DIR/reference-of-mut-static.rs:20:18 - | -LL | let _y = &mut X; - | ^^^^^^ mutable reference to mutable static - | - = note: for more information, see issue #114447 - = note: this will be a hard error in the 2024 edition - = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior -help: use `addr_of_mut!` instead to create a raw pointer - | -LL | let _y = addr_of_mut!(X); - | ~~~~~~~~~~~~~~~ - -error: creating a shared reference to mutable static is discouraged - --> $DIR/reference-of-mut-static.rs:28:22 - | -LL | let ref _a = X; - | ^ shared reference to mutable static - | - = note: for more information, see issue #114447 - = note: this will be a hard error in the 2024 edition - = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior -help: use `addr_of!` instead to create a raw pointer - | -LL | let ref _a = addr_of!(X); - | ~~~~~~~~~~~ - -error: creating a shared reference to mutable static is discouraged - --> $DIR/reference-of-mut-static.rs:32:25 - | -LL | let (_b, _c) = (&X, &Y); - | ^^ shared reference to mutable static - | - = note: for more information, see issue #114447 - = note: this will be a hard error in the 2024 edition - = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior -help: use `addr_of!` instead to create a raw pointer - | -LL | let (_b, _c) = (addr_of!(X), &Y); - | ~~~~~~~~~~~ - -error: creating a shared reference to mutable static is discouraged - --> $DIR/reference-of-mut-static.rs:32:29 - | -LL | let (_b, _c) = (&X, &Y); - | ^^ shared reference to mutable static - | - = note: for more information, see issue #114447 - = note: this will be a hard error in the 2024 edition - = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior -help: use `addr_of!` instead to create a raw pointer - | -LL | let (_b, _c) = (&X, addr_of!(Y)); - | ~~~~~~~~~~~ - -error: creating a shared reference to mutable static is discouraged - --> $DIR/reference-of-mut-static.rs:38:13 - | -LL | foo(&X); - | ^^ shared reference to mutable static - | - = note: for more information, see issue #114447 - = note: this will be a hard error in the 2024 edition - = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior -help: use `addr_of!` instead to create a raw pointer - | -LL | foo(addr_of!(X)); - | ~~~~~~~~~~~ - -error: aborting due to 6 previous errors - diff --git a/tests/ui/static/reference-of-mut-static.e2024.stderr b/tests/ui/static/reference-of-mut-static.e2024.stderr deleted file mode 100644 index 6205c10ac416f..0000000000000 --- a/tests/ui/static/reference-of-mut-static.e2024.stderr +++ /dev/null @@ -1,75 +0,0 @@ -error[E0796]: creating a shared reference to a mutable static - --> $DIR/reference-of-mut-static.rs:16:18 - | -LL | let _y = &X; - | ^^ shared reference to mutable static - | - = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior -help: use `addr_of!` instead to create a raw pointer - | -LL | let _y = addr_of!(X); - | ~~~~~~~~~~~ - -error[E0796]: creating a mutable reference to a mutable static - --> $DIR/reference-of-mut-static.rs:20:18 - | -LL | let _y = &mut X; - | ^^^^^^ mutable reference to mutable static - | - = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior -help: use `addr_of_mut!` instead to create a raw pointer - | -LL | let _y = addr_of_mut!(X); - | ~~~~~~~~~~~~~~~ - -error[E0796]: creating a shared reference to a mutable static - --> $DIR/reference-of-mut-static.rs:28:22 - | -LL | let ref _a = X; - | ^ shared reference to mutable static - | - = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior -help: use `addr_of!` instead to create a raw pointer - | -LL | let ref _a = addr_of!(X); - | ~~~~~~~~~~~ - -error[E0796]: creating a shared reference to a mutable static - --> $DIR/reference-of-mut-static.rs:32:25 - | -LL | let (_b, _c) = (&X, &Y); - | ^^ shared reference to mutable static - | - = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior -help: use `addr_of!` instead to create a raw pointer - | -LL | let (_b, _c) = (addr_of!(X), &Y); - | ~~~~~~~~~~~ - -error[E0796]: creating a shared reference to a mutable static - --> $DIR/reference-of-mut-static.rs:32:29 - | -LL | let (_b, _c) = (&X, &Y); - | ^^ shared reference to mutable static - | - = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior -help: use `addr_of!` instead to create a raw pointer - | -LL | let (_b, _c) = (&X, addr_of!(Y)); - | ~~~~~~~~~~~ - -error[E0796]: creating a shared reference to a mutable static - --> $DIR/reference-of-mut-static.rs:38:13 - | -LL | foo(&X); - | ^^ shared reference to mutable static - | - = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior -help: use `addr_of!` instead to create a raw pointer - | -LL | foo(addr_of!(X)); - | ~~~~~~~~~~~ - -error: aborting due to 6 previous errors - -For more information about this error, try `rustc --explain E0796`. diff --git a/tests/ui/static/reference-of-mut-static.rs b/tests/ui/static/reference-of-mut-static.rs deleted file mode 100644 index af2cab7dd8723..0000000000000 --- a/tests/ui/static/reference-of-mut-static.rs +++ /dev/null @@ -1,50 +0,0 @@ -//@ revisions: e2021 e2024 - -//@ [e2021] edition:2021 -//@ [e2024] compile-flags: --edition 2024 -Z unstable-options - -#![deny(static_mut_refs)] - -use std::ptr::{addr_of, addr_of_mut}; - -fn main() { - static mut X: i32 = 1; - - static mut Y: i32 = 1; - - unsafe { - let _y = &X; - //[e2024]~^ ERROR creating a shared reference to a mutable static [E0796] - //[e2021]~^^ ERROR shared reference to mutable static is discouraged [static_mut_refs] - - let _y = &mut X; - //[e2024]~^ ERROR creating a mutable reference to a mutable static [E0796] - //[e2021]~^^ ERROR mutable reference to mutable static is discouraged [static_mut_refs] - - let _z = addr_of_mut!(X); - - let _p = addr_of!(X); - - let ref _a = X; - //[e2024]~^ ERROR creating a shared reference to a mutable static [E0796] - //[e2021]~^^ ERROR shared reference to mutable static is discouraged [static_mut_refs] - - let (_b, _c) = (&X, &Y); - //[e2024]~^ ERROR creating a shared reference to a mutable static [E0796] - //[e2021]~^^ ERROR shared reference to mutable static is discouraged [static_mut_refs] - //[e2024]~^^^ ERROR creating a shared reference to a mutable static [E0796] - //[e2021]~^^^^ ERROR shared reference to mutable static is discouraged [static_mut_refs] - - foo(&X); - //[e2024]~^ ERROR creating a shared reference to a mutable static [E0796] - //[e2021]~^^ ERROR shared reference to mutable static is discouraged [static_mut_refs] - - static mut Z: &[i32; 3] = &[0, 1, 2]; - - let _ = Z.len(); - let _ = Z[0]; - let _ = format!("{:?}", Z); - } -} - -fn foo<'a>(_x: &'a i32) {} diff --git a/tests/ui/static/reference-to-mut-static-safe.e2024.stderr b/tests/ui/static/reference-to-mut-static-safe.e2024.stderr index 607c1bba1352a..c57b418d7b2e2 100644 --- a/tests/ui/static/reference-to-mut-static-safe.e2024.stderr +++ b/tests/ui/static/reference-to-mut-static-safe.e2024.stderr @@ -10,6 +10,15 @@ help: use `addr_of!` instead to create a raw pointer LL | let _x = addr_of!(X); | ~~~~~~~~~~~ -error: aborting due to 1 previous error +error[E0133]: use of mutable static is unsafe and requires unsafe block + --> $DIR/reference-to-mut-static-safe.rs:9:15 + | +LL | let _x = &X; + | ^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0796`. +Some errors have detailed explanations: E0133, E0796. +For more information about an error, try `rustc --explain E0133`. diff --git a/tests/ui/static/reference-to-mut-static-safe.rs b/tests/ui/static/reference-to-mut-static-safe.rs index de4f4be8f7621..98afdadf4d255 100644 --- a/tests/ui/static/reference-to-mut-static-safe.rs +++ b/tests/ui/static/reference-to-mut-static-safe.rs @@ -8,6 +8,6 @@ fn main() { let _x = &X; //[e2024]~^ creating a shared reference to a mutable static [E0796] - //[e2021]~^^ use of mutable static is unsafe and requires unsafe function or block [E0133] + //~^^ use of mutable static is unsafe and requires unsafe //[e2021]~^^^ shared reference to mutable static is discouraged [static_mut_refs] } diff --git a/tests/ui/static/reference-to-mut-static-unsafe-fn.rs b/tests/ui/static/reference-to-mut-static-unsafe-fn.rs index 5652703a27186..d63fd5460d840 100644 --- a/tests/ui/static/reference-to-mut-static-unsafe-fn.rs +++ b/tests/ui/static/reference-to-mut-static-unsafe-fn.rs @@ -3,24 +3,26 @@ fn main() {} unsafe fn _foo() { - static mut X: i32 = 1; - static mut Y: i32 = 1; + unsafe { + static mut X: i32 = 1; + static mut Y: i32 = 1; - let _y = &X; - //~^ ERROR creating a shared reference to a mutable static [E0796] + let _y = &X; + //~^ ERROR creating a shared reference to a mutable static [E0796] - let ref _a = X; - //~^ ERROR creating a shared reference to a mutable static [E0796] + let ref _a = X; + //~^ ERROR creating a shared reference to a mutable static [E0796] - let ref mut _a = X; - //~^ ERROR creating a mutable reference to a mutable static [E0796] + let ref mut _a = X; + //~^ ERROR creating a mutable reference to a mutable static [E0796] - let (_b, _c) = (&X, &mut Y); - //~^ ERROR creating a shared reference to a mutable static [E0796] - //~^^ ERROR creating a mutable reference to a mutable static [E0796] + let (_b, _c) = (&X, &mut Y); + //~^ ERROR creating a shared reference to a mutable static [E0796] + //~^^ ERROR creating a mutable reference to a mutable static [E0796] - foo(&X); - //~^ ERROR creating a shared reference to a mutable static [E0796] + foo(&X); + //~^ ERROR creating a shared reference to a mutable static [E0796] + } } fn foo<'a>(_x: &'a i32) {} diff --git a/tests/ui/static/reference-to-mut-static-unsafe-fn.stderr b/tests/ui/static/reference-to-mut-static-unsafe-fn.stderr index 77d2aa5d1aec6..b24943cf59363 100644 --- a/tests/ui/static/reference-to-mut-static-unsafe-fn.stderr +++ b/tests/ui/static/reference-to-mut-static-unsafe-fn.stderr @@ -1,74 +1,74 @@ error[E0796]: creating a shared reference to a mutable static - --> $DIR/reference-to-mut-static-unsafe-fn.rs:9:14 + --> $DIR/reference-to-mut-static-unsafe-fn.rs:10:18 | -LL | let _y = &X; - | ^^ shared reference to mutable static +LL | let _y = &X; + | ^^ shared reference to mutable static | = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior help: use `addr_of!` instead to create a raw pointer | -LL | let _y = addr_of!(X); - | ~~~~~~~~~~~ +LL | let _y = addr_of!(X); + | ~~~~~~~~~~~ error[E0796]: creating a shared reference to a mutable static - --> $DIR/reference-to-mut-static-unsafe-fn.rs:12:18 + --> $DIR/reference-to-mut-static-unsafe-fn.rs:13:22 | -LL | let ref _a = X; - | ^ shared reference to mutable static +LL | let ref _a = X; + | ^ shared reference to mutable static | = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior help: use `addr_of!` instead to create a raw pointer | -LL | let ref _a = addr_of!(X); - | ~~~~~~~~~~~ +LL | let ref _a = addr_of!(X); + | ~~~~~~~~~~~ error[E0796]: creating a mutable reference to a mutable static - --> $DIR/reference-to-mut-static-unsafe-fn.rs:15:22 + --> $DIR/reference-to-mut-static-unsafe-fn.rs:16:26 | -LL | let ref mut _a = X; - | ^ mutable reference to mutable static +LL | let ref mut _a = X; + | ^ mutable reference to mutable static | = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior help: use `addr_of_mut!` instead to create a raw pointer | -LL | let ref mut _a = addr_of_mut!(X); - | ~~~~~~~~~~~~~~~ +LL | let ref mut _a = addr_of_mut!(X); + | ~~~~~~~~~~~~~~~ error[E0796]: creating a shared reference to a mutable static - --> $DIR/reference-to-mut-static-unsafe-fn.rs:18:21 + --> $DIR/reference-to-mut-static-unsafe-fn.rs:19:25 | -LL | let (_b, _c) = (&X, &mut Y); - | ^^ shared reference to mutable static +LL | let (_b, _c) = (&X, &mut Y); + | ^^ shared reference to mutable static | = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior help: use `addr_of!` instead to create a raw pointer | -LL | let (_b, _c) = (addr_of!(X), &mut Y); - | ~~~~~~~~~~~ +LL | let (_b, _c) = (addr_of!(X), &mut Y); + | ~~~~~~~~~~~ error[E0796]: creating a mutable reference to a mutable static - --> $DIR/reference-to-mut-static-unsafe-fn.rs:18:25 + --> $DIR/reference-to-mut-static-unsafe-fn.rs:19:29 | -LL | let (_b, _c) = (&X, &mut Y); - | ^^^^^^ mutable reference to mutable static +LL | let (_b, _c) = (&X, &mut Y); + | ^^^^^^ mutable reference to mutable static | = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior help: use `addr_of_mut!` instead to create a raw pointer | -LL | let (_b, _c) = (&X, addr_of_mut!(Y)); - | ~~~~~~~~~~~~~~~ +LL | let (_b, _c) = (&X, addr_of_mut!(Y)); + | ~~~~~~~~~~~~~~~ error[E0796]: creating a shared reference to a mutable static - --> $DIR/reference-to-mut-static-unsafe-fn.rs:22:9 + --> $DIR/reference-to-mut-static-unsafe-fn.rs:23:13 | -LL | foo(&X); - | ^^ shared reference to mutable static +LL | foo(&X); + | ^^ shared reference to mutable static | = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior help: use `addr_of!` instead to create a raw pointer | -LL | foo(addr_of!(X)); - | ~~~~~~~~~~~ +LL | foo(addr_of!(X)); + | ~~~~~~~~~~~ error: aborting due to 6 previous errors diff --git a/tests/ui/suggestions/types/dont-suggest-path-names.rs b/tests/ui/suggestions/types/dont-suggest-path-names.rs new file mode 100644 index 0000000000000..d160e49cd0358 --- /dev/null +++ b/tests/ui/suggestions/types/dont-suggest-path-names.rs @@ -0,0 +1,17 @@ +// This is a regression test for #123630 +// +// Prior to #123703 this was resulting in compiler suggesting add a type signature +// for `lit` containing path to a file containing `Select` - something obviously invalid. + +struct Select(F, I); +fn select(filter: F) -> Select {} +//~^ 7:31: 7:43: mismatched types [E0308] + +fn parser1() { + let lit = select(|x| match x { + //~^ 11:23: 11:24: type annotations needed [E0282] + _ => (), + }); +} + +fn main() {} diff --git a/tests/ui/suggestions/types/dont-suggest-path-names.stderr b/tests/ui/suggestions/types/dont-suggest-path-names.stderr new file mode 100644 index 0000000000000..5c71e350f81a3 --- /dev/null +++ b/tests/ui/suggestions/types/dont-suggest-path-names.stderr @@ -0,0 +1,26 @@ +error[E0308]: mismatched types + --> $DIR/dont-suggest-path-names.rs:7:31 + | +LL | fn select(filter: F) -> Select {} + | ------ ^^^^^^^^^^^^ expected `Select`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + | + = note: expected struct `Select` + found unit type `()` + +error[E0282]: type annotations needed + --> $DIR/dont-suggest-path-names.rs:11:23 + | +LL | let lit = select(|x| match x { + | ^ - type must be known at this point + | +help: consider giving this closure parameter an explicit type + | +LL | let lit = select(|x: /* Type */| match x { + | ++++++++++++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0282, E0308. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr b/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr index 7df1a08bc883d..0c2772683a918 100644 --- a/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr +++ b/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr @@ -44,18 +44,6 @@ LL | LL | call(operation).await | ^^^^^^^^^^^^^^^ -error[E0792]: expected generic lifetime parameter, found `'any` - --> $DIR/hkl_forbidden4.rs:23:1 - | -LL | type FutNothing<'a> = impl 'a + Future; - | -- this generic parameter must be used with a generic lifetime parameter -... -LL | / { -LL | | -LL | | -LL | | } - | |_^ - error: concrete type differs from previous defining opaque type use --> $DIR/hkl_forbidden4.rs:13:1 | @@ -68,6 +56,18 @@ note: previous use here LL | call(operation).await | ^^^^^^^^^^^^^^^ +error[E0792]: expected generic lifetime parameter, found `'any` + --> $DIR/hkl_forbidden4.rs:23:1 + | +LL | type FutNothing<'a> = impl 'a + Future; + | -- this generic parameter must be used with a generic lifetime parameter +... +LL | / { +LL | | +LL | | +LL | | } + | |_^ + error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/issue-53092-2.rs b/tests/ui/type-alias-impl-trait/issue-53092-2.rs index 61b23a3a93322..2adfad4fc5b80 100644 --- a/tests/ui/type-alias-impl-trait/issue-53092-2.rs +++ b/tests/ui/type-alias-impl-trait/issue-53092-2.rs @@ -5,6 +5,8 @@ type Bug = impl Fn(T) -> U + Copy; //~ ERROR cycle detected const CONST_BUG: Bug = unsafe { std::mem::transmute(|_: u8| ()) }; //~^ ERROR: non-defining opaque type use +//~| ERROR: item does not constrain +//~| ERROR: item does not constrain fn make_bug>() -> Bug { |x| x.into() //~ ERROR the trait bound `U: From` is not satisfied diff --git a/tests/ui/type-alias-impl-trait/issue-53092-2.stderr b/tests/ui/type-alias-impl-trait/issue-53092-2.stderr index c2da5fc265cc2..121f765e66726 100644 --- a/tests/ui/type-alias-impl-trait/issue-53092-2.stderr +++ b/tests/ui/type-alias-impl-trait/issue-53092-2.stderr @@ -36,14 +36,40 @@ LL | type Bug = impl Fn(T) -> U + Copy; | ^^^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information +error: item does not constrain `Bug::{opaque#0}`, but has it in its signature + --> $DIR/issue-53092-2.rs:6:7 + | +LL | const CONST_BUG: Bug = unsafe { std::mem::transmute(|_: u8| ()) }; + | ^^^^^^^^^ + | + = note: consider moving the opaque type's declaration and defining uses into a separate module +note: this opaque type is in the signature + --> $DIR/issue-53092-2.rs:4:18 + | +LL | type Bug = impl Fn(T) -> U + Copy; + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: item does not constrain `Bug::{opaque#0}`, but has it in its signature + --> $DIR/issue-53092-2.rs:6:61 + | +LL | const CONST_BUG: Bug = unsafe { std::mem::transmute(|_: u8| ()) }; + | ^^^^^^^ + | + = note: consider moving the opaque type's declaration and defining uses into a separate module +note: this opaque type is in the signature + --> $DIR/issue-53092-2.rs:4:18 + | +LL | type Bug = impl Fn(T) -> U + Copy; + | ^^^^^^^^^^^^^^^^^^^^^^ + error[E0277]: the trait bound `U: From` is not satisfied - --> $DIR/issue-53092-2.rs:10:5 + --> $DIR/issue-53092-2.rs:12:5 | LL | |x| x.into() | ^^^^^^^^^^^^ the trait `From` is not implemented for `U` | note: required by a bound in `make_bug` - --> $DIR/issue-53092-2.rs:9:19 + --> $DIR/issue-53092-2.rs:11:19 | LL | fn make_bug>() -> Bug { | ^^^^^^^ required by this bound in `make_bug` @@ -52,7 +78,7 @@ help: consider restricting type parameter `U` LL | type Bug> = impl Fn(T) -> U + Copy; | +++++++++++++++++++++++ -error: aborting due to 3 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0277, E0391, E0792. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/typeck_type_placeholder_item.rs b/tests/ui/typeck/typeck_type_placeholder_item.rs index a95b44e807c5d..29a21a1f45f56 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.rs +++ b/tests/ui/typeck/typeck_type_placeholder_item.rs @@ -47,7 +47,7 @@ impl Test9 { fn test11(x: &usize) -> &_ { //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types - &x //~ ERROR cannot return reference to function parameter + &x } unsafe fn test12(x: *const usize) -> *const *const _ { diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr index 7977504dae1d6..9d295f88da5aa 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr @@ -158,7 +158,7 @@ LL | fn test11(x: &usize) -> &_ { | -^ | || | |not allowed in type signatures - | help: replace with the correct return type: `&'static &'static usize` + | help: replace with the correct return type: `&&usize` error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:53:52 @@ -687,13 +687,7 @@ help: add `#![feature(const_trait_impl)]` to the crate attributes to enable LL + #![feature(const_trait_impl)] | -error[E0515]: cannot return reference to function parameter `x` - --> $DIR/typeck_type_placeholder_item.rs:50:5 - | -LL | &x - | ^^ returns a reference to data owned by the current function - -error: aborting due to 75 previous errors +error: aborting due to 74 previous errors -Some errors have detailed explanations: E0015, E0046, E0121, E0282, E0403, E0515. +Some errors have detailed explanations: E0015, E0046, E0121, E0282, E0403. For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/used.stderr b/tests/ui/used.stderr index ea77f129d8ef0..c586dc722932f 100644 --- a/tests/ui/used.stderr +++ b/tests/ui/used.stderr @@ -3,24 +3,32 @@ error: attribute must be applied to a `static` variable | LL | #[used] | ^^^^^^^ +LL | fn foo() {} + | ----------- but this is a function error: attribute must be applied to a `static` variable --> $DIR/used.rs:7:1 | LL | #[used] | ^^^^^^^ +LL | struct Foo {} + | ------------- but this is a struct error: attribute must be applied to a `static` variable --> $DIR/used.rs:10:1 | LL | #[used] | ^^^^^^^ +LL | trait Bar {} + | ------------ but this is a trait error: attribute must be applied to a `static` variable --> $DIR/used.rs:13:1 | LL | #[used] | ^^^^^^^ +LL | impl Bar for Foo {} + | ------------------- but this is a implementation block error: aborting due to 4 previous errors diff --git a/triagebot.toml b/triagebot.toml index 62e0917efabed..8ae454d412a6f 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -331,6 +331,7 @@ trigger_files = [ "src/tools/tidy", "src/tools/rustdoc-gui-test", "src/tools/libcxx-version", + "src/tools/rustc-perf-wrapper", ] [autolabel."T-infra"]