From 61d86fa06ca4d7c93109fc857300abbd25a19a0a Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Fri, 25 Sep 2020 13:48:48 -0700 Subject: [PATCH 01/16] Check for missing const-stability attributes in `stability` This used to happen as a side-effect of `is_min_const_fn`, which was subtle. --- compiler/rustc_passes/src/stability.rs | 38 +++++++++++++++++++++----- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 4ca52f405fb94..24972b5cc6a6f 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -368,6 +368,21 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> { self.tcx.sess.span_err(span, &format!("{} has missing stability attribute", descr)); } } + + fn check_missing_const_stability(&self, hir_id: HirId, span: Span) { + let stab_map = self.tcx.stability(); + let stab = stab_map.local_stability(hir_id); + if stab.map_or(false, |stab| stab.level.is_stable()) { + let const_stab = stab_map.local_const_stability(hir_id); + if const_stab.is_none() { + self.tcx.sess.span_err( + span, + "`#[stable]` const functions must also be either \ + `#[rustc_const_stable]` or `#[rustc_const_unstable]`", + ); + } + } + } } impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> { @@ -378,14 +393,23 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> { } fn visit_item(&mut self, i: &'tcx Item<'tcx>) { - match i.kind { - // Inherent impls and foreign modules serve only as containers for other items, - // they don't have their own stability. They still can be annotated as unstable - // and propagate this unstability to children, but this annotation is completely - // optional. They inherit stability from their parents when unannotated. - hir::ItemKind::Impl { of_trait: None, .. } | hir::ItemKind::ForeignMod(..) => {} + // Inherent impls and foreign modules serve only as containers for other items, + // they don't have their own stability. They still can be annotated as unstable + // and propagate this unstability to children, but this annotation is completely + // optional. They inherit stability from their parents when unannotated. + if !matches!( + i.kind, + hir::ItemKind::Impl { of_trait: None, .. } | hir::ItemKind::ForeignMod(..) + ) { + self.check_missing_stability(i.hir_id, i.span); + } - _ => self.check_missing_stability(i.hir_id, i.span), + // Ensure `const fn` that are `stable` have one of `rustc_const_unstable` or + // `rustc_const_stable`. + if self.tcx.features().staged_api + && matches!(&i.kind, hir::ItemKind::Fn(sig, ..) if sig.header.is_const()) + { + self.check_missing_const_stability(i.hir_id, i.span); } intravisit::walk_item(self, i) From 11bfc60a4b5fa111527a69e5f511cb69ae5325af Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Fri, 25 Sep 2020 14:08:44 -0700 Subject: [PATCH 02/16] Change error in `fn_queries` to `delay_span_bug` This should be caught by the new check in `rustc_passes`. At some point, this function will be removed entirely. --- compiler/rustc_mir/src/const_eval/fn_queries.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir/src/const_eval/fn_queries.rs b/compiler/rustc_mir/src/const_eval/fn_queries.rs index 9ef63b3322dd5..1db1f6ceedac5 100644 --- a/compiler/rustc_mir/src/const_eval/fn_queries.rs +++ b/compiler/rustc_mir/src/const_eval/fn_queries.rs @@ -50,7 +50,7 @@ pub fn is_min_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool { None => { if let Some(stab) = tcx.lookup_stability(def_id) { if stab.level.is_stable() { - tcx.sess.span_err( + tcx.sess.delay_span_bug( tcx.def_span(def_id), "stable const functions must have either `rustc_const_stable` or \ `rustc_const_unstable` attribute", From 76c6f2dc3f0769653e80c58bd3f288594fa11dc6 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Fri, 25 Sep 2020 13:50:18 -0700 Subject: [PATCH 03/16] No need to call `is_min_const_fn` for side-effects --- compiler/rustc_mir/src/transform/check_consts/validation.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs index dc28ba46d7cbb..3a5ae4c8348f5 100644 --- a/compiler/rustc_mir/src/transform/check_consts/validation.rs +++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs @@ -204,9 +204,6 @@ impl Validator<'mir, 'tcx> { pub fn check_body(&mut self) { let ConstCx { tcx, body, def_id, .. } = *self.ccx; - // HACK: This function has side-effects???? Make sure we call it. - let _ = crate::const_eval::is_min_const_fn(tcx, def_id.to_def_id()); - // The local type and predicate checks are not free and only relevant for `const fn`s. if self.const_kind() == hir::ConstContext::ConstFn { // Prevent const trait methods from being annotated as `stable`. From 6ce178f60eec86cfd9245e6289598938df519359 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Fri, 25 Sep 2020 13:51:52 -0700 Subject: [PATCH 04/16] Test for missing const-stability attributes --- .../stability-attribute/missing-const-stability.rs | 12 ++++++++++++ .../missing-const-stability.stderr | 8 ++++++++ 2 files changed, 20 insertions(+) create mode 100644 src/test/ui/stability-attribute/missing-const-stability.rs create mode 100644 src/test/ui/stability-attribute/missing-const-stability.stderr diff --git a/src/test/ui/stability-attribute/missing-const-stability.rs b/src/test/ui/stability-attribute/missing-const-stability.rs new file mode 100644 index 0000000000000..7d499c611a43c --- /dev/null +++ b/src/test/ui/stability-attribute/missing-const-stability.rs @@ -0,0 +1,12 @@ +#![feature(staged_api)] + +#![stable(feature = "rust1", since = "1.0.0")] + +#[stable(feature = "foo", since = "1.0.0")] +pub const fn foo() {} +//~^ ERROR rustc_const_stable + +#[unstable(feature = "bar", issue = "none")] +pub const fn bar() {} // ok + +fn main() {} diff --git a/src/test/ui/stability-attribute/missing-const-stability.stderr b/src/test/ui/stability-attribute/missing-const-stability.stderr new file mode 100644 index 0000000000000..450a5303fd86f --- /dev/null +++ b/src/test/ui/stability-attribute/missing-const-stability.stderr @@ -0,0 +1,8 @@ +error: `#[stable]` const functions must also be either `#[rustc_const_stable]` or `#[rustc_const_unstable]` + --> $DIR/missing-const-stability.rs:6:1 + | +LL | pub const fn foo() {} + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + From 58c232af6a86bfcde605ec4f2302af52f1cac139 Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Sun, 27 Sep 2020 04:22:55 +0200 Subject: [PATCH 05/16] reduce overlong line --- src/bootstrap/defaults/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/defaults/README.md b/src/bootstrap/defaults/README.md index a91fc3538eb55..f5b96db1b0f47 100644 --- a/src/bootstrap/defaults/README.md +++ b/src/bootstrap/defaults/README.md @@ -4,7 +4,8 @@ These defaults are intended to be a good starting point for working with x.py, with the understanding that no one set of defaults make sense for everyone. They are still experimental, and we'd appreciate your help improving them! -If you use a setting that's not in these defaults that you think others would benefit from, please [file an issue] or make a PR with the changes. +If you use a setting that's not in these defaults that you think +others would benefit from, please [file an issue] or make a PR with the changes. Similarly, if one of these defaults doesn't match what you use personally, please open an issue to get it changed. From 9000710959b797986b3e14553e2261f62634929d Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Wed, 16 Sep 2020 15:35:58 +0000 Subject: [PATCH 06/16] Add MIPS asm! support This patch also: * Add soft-float supports: only f32 * zero-extend i8/i16 to i32 because MIPS only supports register-length arithmetic. * Update table in asm! chapter in unstable book. --- compiler/rustc_codegen_llvm/src/asm.rs | 25 +++ compiler/rustc_target/src/asm/mips.rs | 132 ++++++++++++ compiler/rustc_target/src/asm/mod.rs | 25 +++ .../unstable-book/src/library-features/asm.md | 17 +- src/test/assembly/asm/mips-types.rs | 191 ++++++++++++++++++ 5 files changed, 389 insertions(+), 1 deletion(-) create mode 100644 compiler/rustc_target/src/asm/mips.rs create mode 100644 src/test/assembly/asm/mips-types.rs diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index a468d09c2d93d..f801f845ac16c 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -259,6 +259,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {} InlineAsmArch::Nvptx64 => {} InlineAsmArch::Hexagon => {} + InlineAsmArch::Mips => {} } } if !options.contains(InlineAsmOptions::NOMEM) { @@ -505,6 +506,8 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>) InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg) => "w", InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => "f", InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => "h", InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => "r", InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => "l", @@ -551,6 +554,7 @@ fn modifier_to_llvm( } } InlineAsmRegClass::Hexagon(_) => None, + InlineAsmRegClass::Mips(_) => None, InlineAsmRegClass::Nvptx(_) => None, InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) | InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => None, @@ -603,6 +607,8 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll cx.type_vector(cx.type_i64(), 2) } InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => cx.type_f32(), InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => cx.type_i16(), InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => cx.type_i32(), InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => cx.type_i64(), @@ -700,6 +706,12 @@ fn llvm_fixup_input( value } } + (InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => match s.value { + // MIPS only supports register-length arithmetics. + Primitive::Int(Integer::I8 | Integer::I16, _) => bx.zext(value, bx.cx.type_i32()), + Primitive::F32 => bx.bitcast(value, bx.cx.type_i32()), + _ => value, + }, _ => value, } } @@ -768,6 +780,13 @@ fn llvm_fixup_output( value } } + (InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => match s.value { + // MIPS only supports register-length arithmetics. + Primitive::Int(Integer::I8, _) => bx.trunc(value, bx.cx.type_i8()), + Primitive::Int(Integer::I16, _) => bx.trunc(value, bx.cx.type_i16()), + Primitive::F32 => bx.bitcast(value, bx.cx.type_f32()), + _ => value, + }, _ => value, } } @@ -831,6 +850,12 @@ fn llvm_fixup_output_type( layout.llvm_type(cx) } } + (InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => match s.value { + // MIPS only supports register-length arithmetics. + Primitive::Int(Integer::I8 | Integer::I16, _) => cx.type_i32(), + Primitive::F32 => cx.type_i32(), + _ => layout.llvm_type(cx), + }, _ => layout.llvm_type(cx), } } diff --git a/compiler/rustc_target/src/asm/mips.rs b/compiler/rustc_target/src/asm/mips.rs new file mode 100644 index 0000000000000..638c52d97f1e3 --- /dev/null +++ b/compiler/rustc_target/src/asm/mips.rs @@ -0,0 +1,132 @@ +use super::{InlineAsmArch, InlineAsmType}; +use rustc_macros::HashStable_Generic; +use std::fmt; + +def_reg_class! { + Mips MipsInlineAsmRegClass { + reg, + freg, + } +} + +impl MipsInlineAsmRegClass { + pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] { + &[] + } + + pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option { + None + } + + pub fn suggest_modifier( + self, + _arch: InlineAsmArch, + _ty: InlineAsmType, + ) -> Option<(char, &'static str)> { + None + } + + pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> { + None + } + + pub fn supported_types( + self, + _arch: InlineAsmArch, + ) -> &'static [(InlineAsmType, Option<&'static str>)] { + match self { + Self::reg => types! { _: I8, I16, I32, F32; }, + Self::freg => types! { _: F32; }, + } + } +} + +// The reserved registers are somewhat taken from . +def_regs! { + Mips MipsInlineAsmReg MipsInlineAsmRegClass { + v0: reg = ["$2", "$v0"], + v1: reg = ["$3", "$v1"], + a0: reg = ["$4", "$a0"], + a1: reg = ["$5", "$a1"], + a2: reg = ["$6", "$a2"], + a3: reg = ["$7", "$a3"], + // FIXME: Reserve $t0, $t1 if in mips16 mode. + t0: reg = ["$8", "$t0"], + t1: reg = ["$9", "$t1"], + t2: reg = ["$10", "$t2"], + t3: reg = ["$11", "$t3"], + t4: reg = ["$12", "$t4"], + t5: reg = ["$13", "$t5"], + t6: reg = ["$14", "$t6"], + t7: reg = ["$15", "$t7"], + s0: reg = ["$16", "$s0"], + s1: reg = ["$17", "$s1"], + s2: reg = ["$18", "$s2"], + s3: reg = ["$19", "$s3"], + s4: reg = ["$20", "$s4"], + s5: reg = ["$21", "$s5"], + s6: reg = ["$22", "$s6"], + s7: reg = ["$23", "$s7"], + t8: reg = ["$24", "$t8"], + t9: reg = ["$25", "$t9"], + f0: freg = ["$f0"], + f1: freg = ["$f1"], + f2: freg = ["$f2"], + f3: freg = ["$f3"], + f4: freg = ["$f4"], + f5: freg = ["$f5"], + f6: freg = ["$f6"], + f7: freg = ["$f7"], + f8: freg = ["$f8"], + f9: freg = ["$f9"], + f10: freg = ["$f10"], + f11: freg = ["$f11"], + f12: freg = ["$f12"], + f13: freg = ["$f13"], + f14: freg = ["$f14"], + f15: freg = ["$f15"], + f16: freg = ["$f16"], + f17: freg = ["$f17"], + f18: freg = ["$f18"], + f19: freg = ["$f19"], + f20: freg = ["$f20"], + f21: freg = ["$f21"], + f22: freg = ["$f22"], + f23: freg = ["$f23"], + f24: freg = ["$f24"], + f25: freg = ["$f25"], + f26: freg = ["$f26"], + f27: freg = ["$f27"], + f28: freg = ["$f28"], + f29: freg = ["$f29"], + f30: freg = ["$f30"], + f31: freg = ["$f31"], + #error = ["$0", "$zero"] => + "constant zero cannot be used as an operand for inline asm", + #error = ["$1", "$at"] => + "reserved for assembler (Assembler Temp)", + #error = ["$26", "$k0"] => + "OS-reserved register cannot be used as an operand for inline asm", + #error = ["$27", "$k1"] => + "OS-reserved register cannot be used as an operand for inline asm", + #error = ["$28", "$gp"] => + "the global pointer cannot be used as an operand for inline asm", + #error = ["$29", "$sp"] => + "the stack pointer cannot be used as an operand for inline asm", + #error = ["$30", "$s8", "$fp"] => + "the frame pointer cannot be used as an operand for inline asm", + #error = ["$31", "$ra"] => + "the return address register cannot be used as an operand for inline asm", + } +} + +impl MipsInlineAsmReg { + pub fn emit( + self, + out: &mut dyn fmt::Write, + _arch: InlineAsmArch, + _modifier: Option, + ) -> fmt::Result { + out.write_str(self.name()) + } +} diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index c22644bf813a4..e2f8e91fa9574 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -152,6 +152,7 @@ macro_rules! types { mod aarch64; mod arm; mod hexagon; +mod mips; mod nvptx; mod riscv; mod x86; @@ -159,6 +160,7 @@ mod x86; pub use aarch64::{AArch64InlineAsmReg, AArch64InlineAsmRegClass}; pub use arm::{ArmInlineAsmReg, ArmInlineAsmRegClass}; pub use hexagon::{HexagonInlineAsmReg, HexagonInlineAsmRegClass}; +pub use mips::{MipsInlineAsmReg, MipsInlineAsmRegClass}; pub use nvptx::{NvptxInlineAsmReg, NvptxInlineAsmRegClass}; pub use riscv::{RiscVInlineAsmReg, RiscVInlineAsmRegClass}; pub use x86::{X86InlineAsmReg, X86InlineAsmRegClass}; @@ -173,6 +175,7 @@ pub enum InlineAsmArch { RiscV64, Nvptx64, Hexagon, + Mips, } impl FromStr for InlineAsmArch { @@ -188,6 +191,7 @@ impl FromStr for InlineAsmArch { "riscv64" => Ok(Self::RiscV64), "nvptx64" => Ok(Self::Nvptx64), "hexagon" => Ok(Self::Hexagon), + "mips" => Ok(Self::Mips), _ => Err(()), } } @@ -201,6 +205,7 @@ pub enum InlineAsmReg { RiscV(RiscVInlineAsmReg), Nvptx(NvptxInlineAsmReg), Hexagon(HexagonInlineAsmReg), + Mips(MipsInlineAsmReg), } impl InlineAsmReg { @@ -211,6 +216,7 @@ impl InlineAsmReg { Self::AArch64(r) => r.name(), Self::RiscV(r) => r.name(), Self::Hexagon(r) => r.name(), + Self::Mips(r) => r.name(), } } @@ -221,6 +227,7 @@ impl InlineAsmReg { Self::AArch64(r) => InlineAsmRegClass::AArch64(r.reg_class()), Self::RiscV(r) => InlineAsmRegClass::RiscV(r.reg_class()), Self::Hexagon(r) => InlineAsmRegClass::Hexagon(r.reg_class()), + Self::Mips(r) => InlineAsmRegClass::Mips(r.reg_class()), } } @@ -252,6 +259,9 @@ impl InlineAsmReg { InlineAsmArch::Hexagon => { Self::Hexagon(HexagonInlineAsmReg::parse(arch, has_feature, target, &name)?) } + InlineAsmArch::Mips => { + Self::Mips(MipsInlineAsmReg::parse(arch, has_feature, target, &name)?) + } }) } @@ -269,6 +279,7 @@ impl InlineAsmReg { Self::AArch64(r) => r.emit(out, arch, modifier), Self::RiscV(r) => r.emit(out, arch, modifier), Self::Hexagon(r) => r.emit(out, arch, modifier), + Self::Mips(r) => r.emit(out, arch, modifier), } } @@ -279,6 +290,7 @@ impl InlineAsmReg { Self::AArch64(_) => cb(self), Self::RiscV(_) => cb(self), Self::Hexagon(r) => r.overlapping_regs(|r| cb(Self::Hexagon(r))), + Self::Mips(_) => cb(self), } } } @@ -291,6 +303,7 @@ pub enum InlineAsmRegClass { RiscV(RiscVInlineAsmRegClass), Nvptx(NvptxInlineAsmRegClass), Hexagon(HexagonInlineAsmRegClass), + Mips(MipsInlineAsmRegClass), } impl InlineAsmRegClass { @@ -302,6 +315,7 @@ impl InlineAsmRegClass { Self::RiscV(r) => r.name(), Self::Nvptx(r) => r.name(), Self::Hexagon(r) => r.name(), + Self::Mips(r) => r.name(), } } @@ -316,6 +330,7 @@ impl InlineAsmRegClass { Self::RiscV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::RiscV), Self::Nvptx(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Nvptx), Self::Hexagon(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Hexagon), + Self::Mips(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Mips), } } @@ -337,6 +352,7 @@ impl InlineAsmRegClass { Self::RiscV(r) => r.suggest_modifier(arch, ty), Self::Nvptx(r) => r.suggest_modifier(arch, ty), Self::Hexagon(r) => r.suggest_modifier(arch, ty), + Self::Mips(r) => r.suggest_modifier(arch, ty), } } @@ -354,6 +370,7 @@ impl InlineAsmRegClass { Self::RiscV(r) => r.default_modifier(arch), Self::Nvptx(r) => r.default_modifier(arch), Self::Hexagon(r) => r.default_modifier(arch), + Self::Mips(r) => r.default_modifier(arch), } } @@ -370,6 +387,7 @@ impl InlineAsmRegClass { Self::RiscV(r) => r.supported_types(arch), Self::Nvptx(r) => r.supported_types(arch), Self::Hexagon(r) => r.supported_types(arch), + Self::Mips(r) => r.supported_types(arch), } } @@ -391,6 +409,7 @@ impl InlineAsmRegClass { InlineAsmArch::Hexagon => { Self::Hexagon(HexagonInlineAsmRegClass::parse(arch, name)?) } + InlineAsmArch::Mips => Self::Mips(MipsInlineAsmRegClass::parse(arch, name)?), }) }) } @@ -405,6 +424,7 @@ impl InlineAsmRegClass { Self::RiscV(r) => r.valid_modifiers(arch), Self::Nvptx(r) => r.valid_modifiers(arch), Self::Hexagon(r) => r.valid_modifiers(arch), + Self::Mips(r) => r.valid_modifiers(arch), } } } @@ -545,5 +565,10 @@ pub fn allocatable_registers( hexagon::fill_reg_map(arch, has_feature, target, &mut map); map } + InlineAsmArch::Mips => { + let mut map = mips::regclass_map(); + mips::fill_reg_map(arch, has_feature, target, &mut map); + map + } } } diff --git a/src/doc/unstable-book/src/library-features/asm.md b/src/doc/unstable-book/src/library-features/asm.md index 28a5fe31fc4b5..9b68f462dca70 100644 --- a/src/doc/unstable-book/src/library-features/asm.md +++ b/src/doc/unstable-book/src/library-features/asm.md @@ -27,6 +27,7 @@ Inline assembly is currently supported on the following architectures: - RISC-V - NVPTX - Hexagon +- MIPS32 ## Basic usage @@ -493,6 +494,8 @@ Here is the list of currently supported register classes: | ARM | `qreg` | `q[0-15]` | `w` | | ARM | `qreg_low8` | `q[0-7]` | `t` | | ARM | `qreg_low4` | `q[0-3]` | `x` | +| MIPS32 | `reg` | `$[2-25]` | `r` | +| MIPS32 | `freg` | `$f[0-31]` | `f` | | NVPTX | `reg16` | None\* | `h` | | NVPTX | `reg32` | None\* | `r` | | NVPTX | `reg64` | None\* | `l` | @@ -528,6 +531,8 @@ Each register class has constraints on which value types they can be used with. | ARM | `sreg` | `vfp2` | `i32`, `f32` | | ARM | `dreg` | `vfp2` | `i64`, `f64`, `i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2` | | ARM | `qreg` | `neon` | `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4` | +| MIPS32 | `reg` | None | `i8`, `i16`, `i32`, `f32` | +| MIPS32 | `freg` | None | `f32` | | NVPTX | `reg16` | None | `i8`, `i16` | | NVPTX | `reg32` | None | `i8`, `i16`, `i32`, `f32` | | NVPTX | `reg64` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` | @@ -576,6 +581,7 @@ Some registers have multiple names. These are all treated by the compiler as ide | ARM | `r13` | `sp` | | ARM | `r14` | `lr` | | ARM | `r15` | `pc` | +| MIPS32 | `$[2-25]` | Please [see the Wikipedia page][mips-regs] | | RISC-V | `x0` | `zero` | | RISC-V | `x1` | `ra` | | RISC-V | `x2` | `sp` | @@ -596,12 +602,14 @@ Some registers have multiple names. These are all treated by the compiler as ide | Hexagon | `r30` | `fr` | | Hexagon | `r31` | `lr` | +[mips-regs]: https://en.wikibooks.org/wiki/MIPS_Assembly/Register_File#Registers + Some registers cannot be used for input or output operands: | Architecture | Unsupported register | Reason | | ------------ | -------------------- | ------ | | All | `sp` | The stack pointer must be restored to its original value at the end of an asm code block. | -| All | `bp` (x86), `x29` (AArch64), `x8` (RISC-V), `fr` (Hexagon) | The frame pointer cannot be used as an input or output. | +| All | `bp` (x86), `x29` (AArch64), `x8` (RISC-V), `fr` (Hexagon), `$fp` (MIPS) | The frame pointer cannot be used as an input or output. | | ARM | `r7` or `r11` | On ARM the frame pointer can be either `r7` or `r11` depending on the target. The frame pointer cannot be used as an input or output. | | ARM | `r6` | `r6` is used internally by LLVM as a base pointer and therefore cannot be used as an input or output. | | x86 | `k0` | This is a constant zero register which can't be modified. | @@ -610,6 +618,11 @@ Some registers cannot be used for input or output operands: | x86 | `st([0-7])` | x87 registers are not currently supported (but may be in the future). | | AArch64 | `xzr` | This is a constant zero register which can't be modified. | | ARM | `pc` | This is the program counter, not a real register. | +| MIPS32 | `$0` or `$zero` | This is a constant zero register which can't be modified. | +| MIPS32 | `$1` or `$at` | Reserved for assembler. | +| MIPS32 | `$26`/`$k0`, `$27`/`$k1` | OS-reserved registers. | +| MIPS32 | `$28`/`$gp` | Global pointer cannot be used as inputs or outputs. | +| MIPS32 | `$ra` | Return address cannot be used as inputs or outputs. | | RISC-V | `x0` | This is a constant zero register which can't be modified. | | RISC-V | `gp`, `tp` | These registers are reserved and cannot be used as inputs or outputs. | | Hexagon | `lr` | This is the link register which cannot be used as an input or output. | @@ -657,6 +670,8 @@ The supported modifiers are a subset of LLVM's (and GCC's) [asm template argumen | ARM | `dreg` | None | `d0` | `P` | | ARM | `qreg` | None | `q0` | `q` | | ARM | `qreg` | `e` / `f` | `d0` / `d1` | `e` / `f` | +| MIPS32 | `reg` | None | `$2` | None | +| MIPS32 | `freg` | None | `$f0` | None | | NVPTX | `reg16` | None | `rs0` | None | | NVPTX | `reg32` | None | `r0` | None | | NVPTX | `reg64` | None | `rd0` | None | diff --git a/src/test/assembly/asm/mips-types.rs b/src/test/assembly/asm/mips-types.rs new file mode 100644 index 0000000000000..b195ed88c7245 --- /dev/null +++ b/src/test/assembly/asm/mips-types.rs @@ -0,0 +1,191 @@ +// no-system-llvm +// assembly-output: emit-asm +// compile-flags: --target mips-unknown-linux-gnu +// needs-llvm-components: mips + +#![feature(no_core, lang_items, rustc_attrs, repr_simd)] +#![crate_type = "rlib"] +#![no_core] +#![allow(asm_sub_register, non_camel_case_types)] + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} +#[rustc_builtin_macro] +macro_rules! concat { + () => {}; +} +#[rustc_builtin_macro] +macro_rules! stringify { + () => {}; +} + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +type ptr = *const i32; + +impl Copy for i8 {} +impl Copy for u8 {} +impl Copy for i16 {} +impl Copy for i32 {} +impl Copy for f32 {} +impl Copy for ptr {} +extern "C" { + fn extern_func(); + static extern_static: u8; +} + +// Hack to avoid function merging +extern "Rust" { + fn dont_merge(s: &str); +} + +macro_rules! check { ($func:ident, $ty:ty, $class:ident) => { + #[no_mangle] + pub unsafe fn $func(x: $ty) -> $ty { + dont_merge(stringify!($func)); + + let y; + asm!("move {}, {}", out($class) y, in($class) x); + y + } +};} + +macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt) => { + #[no_mangle] + pub unsafe fn $func(x: $ty) -> $ty { + dont_merge(stringify!($func)); + + let y; + asm!(concat!("move ", $reg, ", ", $reg), lateout($reg) y, in($reg) x); + y + } +};} + +// CHECK-LABEL: sym_static: +// CHECK: #APP +// CHECK: lw $3, %got(extern_static) +// CHECK: #NO_APP +#[no_mangle] +pub unsafe fn sym_static() { + dont_merge(stringify!($func)); + + asm!("la $v1, {}", sym extern_static); +} + +// CHECK-LABEL: sym_fn: +// CHECK: #APP +// CHECK: lw $3, %got(extern_func) +// CHECK: #NO_APP +#[no_mangle] +pub unsafe fn sym_fn() { + dont_merge(stringify!($func)); + + asm!("la $v1, {}", sym extern_func); +} + +// CHECK-LABEL: reg_f32: +// CHECK: #APP +// CHECK: mov.s $f{{[0-9]+}}, $f{{[0-9]+}} +// CHECK: #NO_APP +#[no_mangle] +pub unsafe fn reg_f32(x: f32) -> f32 { + dont_merge("reg_f32"); + let y; + asm!("mov.s {}, {}", out(freg) y, in(freg) x); + y +} + +// CHECK-LABEL: f0_f32: +// CHECK: #APP +// CHECK: mov.s $f0, $f0 +// CHECK: #NO_APP +#[no_mangle] +pub unsafe fn f0_f32(x: f32) -> f32 { + dont_merge("f0_f32"); + let y; + asm!("mov.s $f0, $f0", lateout("$f0") y, in("$f0") x); + y +} + +// CHECK-LABEL: reg_ptr: +// CHECK: #APP +// CHECK: move ${{[0-9]+}}, ${{[0-9]+}} +// CHECK: #NO_APP +check!(reg_ptr, ptr, reg); + +// CHECK-LABEL: reg_i32: +// CHECK: #APP +// CHECK: move ${{[0-9]+}}, ${{[0-9]+}} +// CHECK: #NO_APP +check!(reg_i32, i32, reg); + +// CHECK-LABEL: reg_f32_soft: +// CHECK: #APP +// CHECK: move ${{[0-9]+}}, ${{[0-9]+}} +// CHECK: #NO_APP +check!(reg_f32_soft, f32, reg); + +// CHECK-LABEL: reg_i8: +// CHECK: #APP +// CHECK: move ${{[0-9]+}}, ${{[0-9]+}} +// CHECK: #NO_APP +check!(reg_i8, i8, reg); + +// CHECK-LABEL: reg_u8: +// CHECK: #APP +// CHECK: move ${{[0-9]+}}, ${{[0-9]+}} +// CHECK: #NO_APP +check!(reg_u8, u8, reg); + +// CHECK-LABEL: reg_i16: +// CHECK: #APP +// CHECK: move ${{[0-9]+}}, ${{[0-9]+}} +// CHECK: #NO_APP +check!(reg_i16, i16, reg); + +// CHECK-LABEL: t0_ptr: +// CHECK: #APP +// CHECK: move $8, $8 +// CHECK: #NO_APP +check_reg!(t0_ptr, ptr, "$t0"); + +// CHECK-LABEL: t0_i32: +// CHECK: #APP +// CHECK: move $8, $8 +// CHECK: #NO_APP +check_reg!(t0_i32, i32, "$t0"); + +// CHECK-LABEL: t0_f32: +// CHECK: #APP +// CHECK: move $8, $8 +// CHECK: #NO_APP +check_reg!(t0_f32, f32, "$t0"); + +// CHECK-LABEL: t0_i8: +// CHECK: #APP +// CHECK: move $8, $8 +// CHECK: #NO_APP +check_reg!(t0_i8, i8, "$t0"); + +// CHECK-LABEL: t0_u8: +// CHECK: #APP +// CHECK: move $8, $8 +// CHECK: #NO_APP +check_reg!(t0_u8, u8, "$t0"); + +// CHECK-LABEL: t0_i16: +// CHECK: #APP +// CHECK: move $8, $8 +// CHECK: #NO_APP +check_reg!(t0_i16, i16, "$t0"); + +// CHECK-LABEL: r8_i16: +// CHECK: #APP +// CHECK: move $8, $8 +// CHECK: #NO_APP +check_reg!(r8_i16, i16, "$8"); From 895c37a202802bbeadc7d73bec3172a2dfaaa09c Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Thu, 24 Sep 2020 16:17:03 -0700 Subject: [PATCH 07/16] Add a feature gate for basic function pointer use in `const fn` --- compiler/rustc_feature/src/active.rs | 3 ++ .../src/transform/check_consts/ops.rs | 28 ++++++++++++++----- compiler/rustc_span/src/symbol.rs | 1 + library/core/src/lib.rs | 1 + library/core/src/task/wake.rs | 1 + library/proc_macro/src/lib.rs | 1 + library/std/src/lib.rs | 1 + 7 files changed, 29 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 17b9e1ee7e8ba..7f5b19134804e 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -587,6 +587,9 @@ declare_features! ( /// Allows basic arithmetic on floating point types in a `const fn`. (active, const_fn_floating_point_arithmetic, "1.48.0", Some(57241), None), + /// Allows using and casting function pointers in a `const fn`. + (active, const_fn_fn_ptr_basics, "1.48.0", Some(57563), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/compiler/rustc_mir/src/transform/check_consts/ops.rs b/compiler/rustc_mir/src/transform/check_consts/ops.rs index 1d74108585360..3b8d8a5aa99dd 100644 --- a/compiler/rustc_mir/src/transform/check_consts/ops.rs +++ b/compiler/rustc_mir/src/transform/check_consts/ops.rs @@ -213,11 +213,21 @@ impl NonConstOp for FnPtrCast { const STOPS_CONST_CHECKING: bool = true; fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status { - mcf_status_in_item(ccx) + if ccx.const_kind() != hir::ConstContext::ConstFn { + Status::Allowed + } else { + Status::Unstable(sym::const_fn_fn_ptr_basics) + } } fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) { - mcf_emit_error(ccx, span, "function pointer casts are not allowed in const fn"); + feature_err( + &ccx.tcx.sess.parse_sess, + sym::const_fn_fn_ptr_basics, + span, + &format!("function pointer casts are not allowed in {}s", ccx.const_kind()), + ) + .emit() } } @@ -596,17 +606,21 @@ pub mod ty { const STOPS_CONST_CHECKING: bool = true; fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status { - // FIXME: This attribute a hack to allow the specialization of the `futures` API. See - // #59739. We should have a proper feature gate for this. - if ccx.tcx.has_attr(ccx.def_id.to_def_id(), sym::rustc_allow_const_fn_ptr) { + if ccx.const_kind() != hir::ConstContext::ConstFn { Status::Allowed } else { - mcf_status_in_item(ccx) + Status::Unstable(sym::const_fn_fn_ptr_basics) } } fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) { - mcf_emit_error(ccx, span, "function pointers in const fn are unstable"); + feature_err( + &ccx.tcx.sess.parse_sess, + sym::const_fn_fn_ptr_basics, + span, + &format!("function pointers cannot appear in {}s", ccx.const_kind()), + ) + .emit() } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 12134a85f45c5..7332a7ea3317c 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -353,6 +353,7 @@ symbols! { const_extern_fn, const_fn, const_fn_floating_point_arithmetic, + const_fn_fn_ptr_basics, const_fn_transmute, const_fn_union, const_generics, diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 30fb87b022645..22bf2b15d6695 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -83,6 +83,7 @@ #![feature(const_fn_union)] #![feature(const_fn)] #![cfg_attr(not(bootstrap), feature(const_fn_floating_point_arithmetic))] +#![cfg_attr(not(bootstrap), feature(const_fn_fn_ptr_basics))] #![feature(const_generics)] #![feature(const_option)] #![feature(const_precise_live_drops)] diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 668a028a3f1ea..109dbfda105e3 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -136,6 +136,7 @@ impl RawWakerVTable { // (see https://github.com/rust-rfcs/const-eval/issues/19#issuecomment-472799062) #[rustc_allow_const_fn_ptr] #[rustc_const_stable(feature = "futures_api", since = "1.36.0")] + #[cfg_attr(not(bootstrap), allow_internal_unstable(const_fn_fn_ptr_basics))] pub const fn new( clone: unsafe fn(*const ()) -> RawWaker, wake: unsafe fn(*const ()), diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index f81ffd2bb9429..93fa1f4e58573 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -21,6 +21,7 @@ #![feature(nll)] #![feature(staged_api)] #![feature(const_fn)] +#![cfg_attr(not(bootstrap), feature(const_fn_fn_ptr_basics))] #![feature(allow_internal_unstable)] #![feature(decl_macro)] #![feature(extern_types)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index d03428dd08282..e343eef91126e 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -239,6 +239,7 @@ #![cfg_attr(not(bootstrap), feature(const_fn_floating_point_arithmetic))] #![feature(const_fn_transmute)] #![feature(const_fn)] +#![cfg_attr(not(bootstrap), feature(const_fn_fn_ptr_basics))] #![feature(const_ip)] #![feature(const_ipv6)] #![feature(const_raw_ptr_deref)] From 2863acb5bbe80584ebafd6e0795da117f3414482 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Thu, 24 Sep 2020 16:15:41 -0700 Subject: [PATCH 08/16] Remove `rustc_allow_const_fn_ptr` This was a hack to work around the lack of an escape hatch for the "min `const fn`" checks in const-stable functions. Now that we have co-opted `allow_internal_unstable` for this purpose, we no longer need the bespoke attribute. --- compiler/rustc_attr/src/builtin.rs | 31 +++++-------------- compiler/rustc_feature/src/builtin_attrs.rs | 1 - compiler/rustc_middle/src/query/mod.rs | 4 --- .../rustc_mir/src/const_eval/fn_queries.rs | 6 ---- compiler/rustc_span/src/symbol.rs | 1 - library/core/src/task/wake.rs | 7 +---- 6 files changed, 8 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 03dbcc450246f..94e2a40e1fe36 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -145,8 +145,6 @@ pub struct ConstStability { pub feature: Symbol, /// whether the function has a `#[rustc_promotable]` attribute pub promotable: bool, - /// whether the function has a `#[rustc_allow_const_fn_ptr]` attribute - pub allow_const_fn_ptr: bool, } /// The available stability levels. @@ -190,7 +188,6 @@ where let mut stab: Option = None; let mut const_stab: Option = None; let mut promotable = false; - let mut allow_const_fn_ptr = false; let diagnostic = &sess.parse_sess.span_diagnostic; 'outer: for attr in attrs_iter { @@ -200,7 +197,6 @@ where sym::unstable, sym::stable, sym::rustc_promotable, - sym::rustc_allow_const_fn_ptr, ] .iter() .any(|&s| attr.has_name(s)) @@ -215,9 +211,6 @@ where if attr.has_name(sym::rustc_promotable) { promotable = true; } - if attr.has_name(sym::rustc_allow_const_fn_ptr) { - allow_const_fn_ptr = true; - } // attributes with data else if let Some(MetaItem { kind: MetaItemKind::List(ref metas), .. }) = meta { let meta = meta.as_ref().unwrap(); @@ -360,12 +353,8 @@ where if sym::unstable == meta_name { stab = Some(Stability { level, feature }); } else { - const_stab = Some(ConstStability { - level, - feature, - promotable: false, - allow_const_fn_ptr: false, - }); + const_stab = + Some(ConstStability { level, feature, promotable: false }); } } (None, _, _) => { @@ -440,12 +429,8 @@ where if sym::stable == meta_name { stab = Some(Stability { level, feature }); } else { - const_stab = Some(ConstStability { - level, - feature, - promotable: false, - allow_const_fn_ptr: false, - }); + const_stab = + Some(ConstStability { level, feature, promotable: false }); } } (None, _) => { @@ -464,18 +449,16 @@ where } // Merge the const-unstable info into the stability info - if promotable || allow_const_fn_ptr { + if promotable { if let Some(ref mut stab) = const_stab { stab.promotable = promotable; - stab.allow_const_fn_ptr = allow_const_fn_ptr; } else { struct_span_err!( diagnostic, item_sp, E0717, - "rustc_promotable and rustc_allow_const_fn_ptr attributes \ - must be paired with either a rustc_const_unstable or a rustc_const_stable \ - attribute" + "`rustc_promotable` attribute must be paired with either a `rustc_const_unstable` \ + or a `rustc_const_stable` attribute" ) .emit(); } diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 8b7fd59cd874a..22c1ca2f289d3 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -464,7 +464,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // ========================================================================== rustc_attr!(rustc_promotable, AssumedUsed, template!(Word), IMPL_DETAIL), - rustc_attr!(rustc_allow_const_fn_ptr, AssumedUsed, template!(Word), IMPL_DETAIL), rustc_attr!(rustc_args_required_const, AssumedUsed, template!(List: "N"), INTERNAL_UNSTABLE), // ========================================================================== diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 784d6c3b2cee4..d5b99ea4d288d 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -457,10 +457,6 @@ rustc_queries! { desc { |tcx| "checking if item is promotable: `{}`", tcx.def_path_str(key) } } - query const_fn_is_allowed_fn_ptr(key: DefId) -> bool { - desc { |tcx| "checking if const fn allows `fn()` types: `{}`", tcx.def_path_str(key) } - } - /// Returns `true` if this is a foreign item (i.e., linked via `extern { ... }`). query is_foreign_item(key: DefId) -> bool { desc { |tcx| "checking if `{}` is a foreign item", tcx.def_path_str(key) } diff --git a/compiler/rustc_mir/src/const_eval/fn_queries.rs b/compiler/rustc_mir/src/const_eval/fn_queries.rs index 9ef63b3322dd5..b20d89b6e835c 100644 --- a/compiler/rustc_mir/src/const_eval/fn_queries.rs +++ b/compiler/rustc_mir/src/const_eval/fn_queries.rs @@ -151,17 +151,11 @@ fn is_promotable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool { } } -fn const_fn_is_allowed_fn_ptr(tcx: TyCtxt<'_>, def_id: DefId) -> bool { - is_const_fn(tcx, def_id) - && tcx.lookup_const_stability(def_id).map(|stab| stab.allow_const_fn_ptr).unwrap_or(false) -} - pub fn provide(providers: &mut Providers) { *providers = Providers { is_const_fn_raw, is_const_impl_raw: |tcx, def_id| is_const_impl_raw(tcx, def_id.expect_local()), is_promotable_const_fn, - const_fn_is_allowed_fn_ptr, ..*providers }; } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 7332a7ea3317c..4234aef335906 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -885,7 +885,6 @@ symbols! { rustc, rustc_allocator, rustc_allocator_nounwind, - rustc_allow_const_fn_ptr, rustc_args_required_const, rustc_attrs, rustc_builtin_macro, diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 109dbfda105e3..ba3fb35caaf9d 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -129,14 +129,9 @@ impl RawWakerVTable { /// associated task. #[rustc_promotable] #[stable(feature = "futures_api", since = "1.36.0")] - // `rustc_allow_const_fn_ptr` is a hack that should not be used anywhere else - // without first consulting with T-Lang. - // - // FIXME: remove whenever we have a stable way to accept fn pointers from const fn - // (see https://github.com/rust-rfcs/const-eval/issues/19#issuecomment-472799062) - #[rustc_allow_const_fn_ptr] #[rustc_const_stable(feature = "futures_api", since = "1.36.0")] #[cfg_attr(not(bootstrap), allow_internal_unstable(const_fn_fn_ptr_basics))] + #[cfg_attr(bootstrap, rustc_allow_const_fn_ptr)] pub const fn new( clone: unsafe fn(*const ()) -> RawWaker, wake: unsafe fn(*const ()), From a9d63ba7fc67024b45126b8d7da9222504646db4 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Thu, 24 Sep 2020 16:18:41 -0700 Subject: [PATCH 09/16] Update tests with new feature gate --- src/test/ui/consts/auxiliary/const_fn_lib.rs | 2 +- src/test/ui/consts/const-eval/issue-70804-fn-subtyping.rs | 2 +- .../const-extern-fn/const-extern-fn-min-const-fn.rs | 2 +- src/test/ui/consts/issue-37550.rs | 2 +- src/test/ui/consts/issue-56164.rs | 7 +++---- src/test/ui/consts/min_const_fn/allow_const_fn_ptr.rs | 8 +++++--- .../min_const_fn/allow_const_fn_ptr_feature_gate.rs | 7 +++++-- .../ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs | 4 +++- src/test/ui/consts/min_const_fn/cast_errors.rs | 8 ++++---- src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs | 2 +- src/test/ui/consts/min_const_fn/min_const_fn.rs | 4 ++-- src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs | 4 ++-- src/test/ui/issues/issue-37550.rs | 2 +- src/test/ui/issues/issue-46553.rs | 2 +- src/test/ui/type-alias-impl-trait/issue-53096.rs | 2 +- 15 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/test/ui/consts/auxiliary/const_fn_lib.rs b/src/test/ui/consts/auxiliary/const_fn_lib.rs index 85714efdbe99c..bf0b01a2ecfe0 100644 --- a/src/test/ui/consts/auxiliary/const_fn_lib.rs +++ b/src/test/ui/consts/auxiliary/const_fn_lib.rs @@ -1,6 +1,6 @@ // Crate that exports a const fn. Used for testing cross-crate. -#![feature(const_fn)] +#![feature(const_fn_fn_ptr_basics)] #![crate_type="rlib"] pub const fn foo() -> usize { 22 } diff --git a/src/test/ui/consts/const-eval/issue-70804-fn-subtyping.rs b/src/test/ui/consts/const-eval/issue-70804-fn-subtyping.rs index 59d46ea66c9ca..bf8bae5ea2c73 100644 --- a/src/test/ui/consts/const-eval/issue-70804-fn-subtyping.rs +++ b/src/test/ui/consts/const-eval/issue-70804-fn-subtyping.rs @@ -1,5 +1,5 @@ // check-pass -#![feature(const_fn)] +#![feature(const_fn_fn_ptr_basics)] const fn nested(x: (for<'a> fn(&'a ()), String)) -> (fn(&'static ()), String) { x diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs b/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs index 094ae7378bce8..8642954a75b45 100644 --- a/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs +++ b/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs @@ -2,7 +2,7 @@ const extern fn unsize(x: &[u8; 3]) -> &[u8] { x } const unsafe extern "C" fn closure() -> fn() { || {} } -//~^ ERROR function pointers in const fn are unstable +//~^ ERROR function pointer const unsafe extern fn use_float() { 1.0 + 1.0; } //~^ ERROR floating point arithmetic const extern "C" fn ptr_cast(val: *const u8) { val as usize; } diff --git a/src/test/ui/consts/issue-37550.rs b/src/test/ui/consts/issue-37550.rs index 04865830df2eb..15877c53747ec 100644 --- a/src/test/ui/consts/issue-37550.rs +++ b/src/test/ui/consts/issue-37550.rs @@ -2,7 +2,7 @@ #![allow(dead_code)] #![allow(unused_variables)] -#![feature(const_fn)] +#![feature(const_fn_fn_ptr_basics)] const fn x() { let t = true; diff --git a/src/test/ui/consts/issue-56164.rs b/src/test/ui/consts/issue-56164.rs index 9d1a8b59463e7..90ea217698d65 100644 --- a/src/test/ui/consts/issue-56164.rs +++ b/src/test/ui/consts/issue-56164.rs @@ -1,12 +1,11 @@ -#![feature(const_fn)] +#![feature(const_fn_fn_ptr_basics)] const fn foo() { (||{})() } -//~^ ERROR calls in constant functions are limited to constant functions, tuple structs and tuple -// variants +//~^ ERROR calls in constant functions const fn bad(input: fn()) { input() - //~^ ERROR function pointers are not allowed in const fn + //~^ ERROR function pointer } fn main() { diff --git a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.rs b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.rs index 937aae1a8e399..dc10db177ed69 100644 --- a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.rs +++ b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.rs @@ -1,12 +1,14 @@ -#![feature(rustc_attrs, staged_api)] +#![feature(rustc_attrs, staged_api, allow_internal_unstable)] +#![feature(const_fn_fn_ptr_basics)] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(since="1.0.0", feature = "mep")] -const fn error(_: fn()) {} //~ ERROR function pointers in const fn are unstable +const fn error(_: fn()) {} +//~^ ERROR const-stable function cannot use `#[feature(const_fn_fn_ptr_basics)]` #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_allow_const_fn_ptr] #[rustc_const_stable(since="1.0.0", feature = "mep")] +#[allow_internal_unstable(const_fn_fn_ptr_basics)] const fn compiles(_: fn()) {} fn main() {} diff --git a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.rs b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.rs index 0f9d37292958a..5e6c0a3320553 100644 --- a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.rs +++ b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.rs @@ -2,10 +2,13 @@ #[stable(feature = "rust1", since = "1.0.0")] const fn error(_: fn()) {} +//~^ ERROR `rustc_const_stable` or `rustc_const_unstable` +//~| ERROR `rustc_const_stable` or `rustc_const_unstable` +//~| ERROR function pointers #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_allow_const_fn_ptr] -//~^ ERROR internal implementation detail +#[rustc_const_stable(since="1.0.0", feature = "mep")] const fn compiles(_: fn()) {} +//~^ ERROR function pointers fn main() {} diff --git a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs index 7aa9bd7e2dcdd..b4e836bbc9540 100644 --- a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs +++ b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs @@ -1,11 +1,13 @@ // run-pass +#![feature(allow_internal_unstable)] +#![feature(const_fn_fn_ptr_basics)] #![feature(rustc_attrs, staged_api)] #![stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_allow_const_fn_ptr] #[rustc_const_stable(since="1.0.0", feature = "mep")] +#[allow_internal_unstable(const_fn_fn_ptr_basics)] const fn takes_fn_ptr(_: fn()) {} const FN: fn() = || (); diff --git a/src/test/ui/consts/min_const_fn/cast_errors.rs b/src/test/ui/consts/min_const_fn/cast_errors.rs index 8d730df16b0d1..43ef8ea12eb1f 100644 --- a/src/test/ui/consts/min_const_fn/cast_errors.rs +++ b/src/test/ui/consts/min_const_fn/cast_errors.rs @@ -2,12 +2,12 @@ fn main() {} const fn unsize(x: &[u8; 3]) -> &[u8] { x } const fn closure() -> fn() { || {} } -//~^ ERROR function pointers in const fn are unstable +//~^ ERROR function pointer const fn closure2() { (|| {}) as fn(); -//~^ ERROR function pointers in const fn are unstable +//~^ ERROR function pointer } const fn reify(f: fn()) -> unsafe fn() { f } -//~^ ERROR function pointers in const fn are unstable +//~^ ERROR function pointer const fn reify2() { main as unsafe fn(); } -//~^ ERROR function pointers in const fn are unstable +//~^ ERROR function pointer diff --git a/src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs b/src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs index c2600f894dc42..4aaf7b86e4560 100644 --- a/src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs +++ b/src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs @@ -1,4 +1,4 @@ -const fn cmp(x: fn(), y: fn()) -> bool { //~ ERROR function pointers in const fn are unstable +const fn cmp(x: fn(), y: fn()) -> bool { //~ ERROR function pointer unsafe { x == y } } diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.rs b/src/test/ui/consts/min_const_fn/min_const_fn.rs index 55a999d5cdc04..06a44b271064c 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.rs +++ b/src/test/ui/consts/min_const_fn/min_const_fn.rs @@ -128,6 +128,6 @@ const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 } //~^ ERROR trait bounds other than `Sized` const fn no_fn_ptrs(_x: fn()) {} -//~^ ERROR function pointers in const fn are unstable +//~^ ERROR function pointer const fn no_fn_ptrs2() -> fn() { fn foo() {} foo } -//~^ ERROR function pointers in const fn are unstable +//~^ ERROR function pointer diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs b/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs index 584ea46b1a6f7..985220ec7ae1d 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs +++ b/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs @@ -9,9 +9,9 @@ fn field() {} const fn no_inner_dyn_trait(_x: Hide) {} const fn no_inner_dyn_trait2(x: Hide) { x.0.field; -//~^ ERROR function pointers in const fn +//~^ ERROR function pointer } const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasPtr { field }) } -//~^ ERROR function pointers in const fn +//~^ ERROR function pointer fn main() {} diff --git a/src/test/ui/issues/issue-37550.rs b/src/test/ui/issues/issue-37550.rs index 505c030b96712..35b63bddca252 100644 --- a/src/test/ui/issues/issue-37550.rs +++ b/src/test/ui/issues/issue-37550.rs @@ -1,6 +1,6 @@ const fn x() { let t = true; - let x = || t; //~ ERROR function pointers in const fn are unstable + let x = || t; //~ ERROR function pointer } fn main() {} diff --git a/src/test/ui/issues/issue-46553.rs b/src/test/ui/issues/issue-46553.rs index e21a532effd1d..0a1e835672de9 100644 --- a/src/test/ui/issues/issue-46553.rs +++ b/src/test/ui/issues/issue-46553.rs @@ -1,5 +1,5 @@ // run-pass -#![feature(const_fn)] +#![feature(const_fn_fn_ptr_basics)] #![deny(const_err)] pub struct Data { diff --git a/src/test/ui/type-alias-impl-trait/issue-53096.rs b/src/test/ui/type-alias-impl-trait/issue-53096.rs index 564c5c3d33f85..bdf426bbd3788 100644 --- a/src/test/ui/type-alias-impl-trait/issue-53096.rs +++ b/src/test/ui/type-alias-impl-trait/issue-53096.rs @@ -1,5 +1,5 @@ // check-pass -#![feature(const_fn)] +#![feature(const_fn, const_fn_fn_ptr_basics)] #![feature(type_alias_impl_trait)] type Foo = impl Fn() -> usize; From 50fb9f1821ba10ba712adf40323c6a70b124ebfa Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Thu, 24 Sep 2020 16:18:49 -0700 Subject: [PATCH 10/16] Bless tests --- .../ui/consts/const-eval/const_fn_ptr.stderr | 14 +++++++- .../const-eval/const_fn_ptr_fail2.stderr | 10 ++++++ .../const-extern-fn-min-const-fn.stderr | 7 ++-- src/test/ui/consts/issue-56164.stderr | 2 +- .../min_const_fn/allow_const_fn_ptr.stderr | 12 ++++--- .../allow_const_fn_ptr_feature_gate.stderr | 34 +++++++++++++++---- .../ui/consts/min_const_fn/cast_errors.stderr | 18 +++++----- .../min_const_fn/cmp_fn_pointers.stderr | 6 ++-- .../consts/min_const_fn/min_const_fn.stderr | 8 ++--- .../min_const_fn/min_const_fn_fn_ptr.stderr | 10 +++--- .../consts/miri_unleashed/abi-mismatch.stderr | 4 +-- src/test/ui/issues/issue-37550.stderr | 6 ++-- ...caller-location-fnptr-rt-ctfe-equiv.stderr | 19 ++++++++++- 13 files changed, 106 insertions(+), 44 deletions(-) diff --git a/src/test/ui/consts/const-eval/const_fn_ptr.stderr b/src/test/ui/consts/const-eval/const_fn_ptr.stderr index d0ae94079da2e..ab18020056b0a 100644 --- a/src/test/ui/consts/const-eval/const_fn_ptr.stderr +++ b/src/test/ui/consts/const-eval/const_fn_ptr.stderr @@ -10,11 +10,23 @@ help: skipping check that does not even have a feature gate | LL | X_CONST(x) | ^^^^^^^^^^ +help: skipping check for `const_fn_fn_ptr_basics` feature + --> $DIR/const_fn_ptr.rs:19:14 + | +LL | const fn foo(x: fn(usize) -> usize, y: usize) -> usize { + | ^ +help: skipping check for `const_fn_fn_ptr_basics` feature + --> $DIR/const_fn_ptr.rs:20:5 + | +LL | x(y) + | ^ help: skipping check that does not even have a feature gate --> $DIR/const_fn_ptr.rs:20:5 | LL | x(y) | ^^^^ -warning: 1 warning emitted +error: `-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature gates, except when testing error paths in the CTFE engine + +error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr index 90ee2afa315d8..822d4af83064e 100644 --- a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr +++ b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr @@ -20,6 +20,16 @@ LL | assert_eq!(Z, 4); warning: skipping const checks | +help: skipping check for `const_fn_fn_ptr_basics` feature + --> $DIR/const_fn_ptr_fail2.rs:12:14 + | +LL | const fn bar(x: fn(usize) -> usize, y: usize) -> usize { + | ^ +help: skipping check for `const_fn_fn_ptr_basics` feature + --> $DIR/const_fn_ptr_fail2.rs:13:5 + | +LL | x(y) + | ^ help: skipping check that does not even have a feature gate --> $DIR/const_fn_ptr_fail2.rs:13:5 | diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr b/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr index fcc34f358f9f9..455a822e2d085 100644 --- a/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr +++ b/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr @@ -1,11 +1,11 @@ -error[E0723]: function pointers in const fn are unstable +error[E0658]: function pointers cannot appear in constant functions --> $DIR/const-extern-fn-min-const-fn.rs:4:41 | LL | const unsafe extern "C" fn closure() -> fn() { || {} } | ^^^^ | = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable error[E0658]: floating point arithmetic is not allowed in constant functions --> $DIR/const-extern-fn-min-const-fn.rs:6:38 @@ -27,5 +27,4 @@ LL | const extern "C" fn ptr_cast(val: *const u8) { val as usize; } error: aborting due to 3 previous errors -Some errors have detailed explanations: E0658, E0723. -For more information about an error, try `rustc --explain E0658`. +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/issue-56164.stderr b/src/test/ui/consts/issue-56164.stderr index d3e9ce379aed7..500af0a40069a 100644 --- a/src/test/ui/consts/issue-56164.stderr +++ b/src/test/ui/consts/issue-56164.stderr @@ -5,7 +5,7 @@ LL | const fn foo() { (||{})() } | ^^^^^^^^ error: function pointers are not allowed in const fn - --> $DIR/issue-56164.rs:8:5 + --> $DIR/issue-56164.rs:7:5 | LL | input() | ^^^^^^^ diff --git a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.stderr b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.stderr index 9a14bcc2f7335..94f6cda209749 100644 --- a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.stderr +++ b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.stderr @@ -1,12 +1,14 @@ -error[E0723]: function pointers in const fn are unstable - --> $DIR/allow_const_fn_ptr.rs:5:16 +error: const-stable function cannot use `#[feature(const_fn_fn_ptr_basics)]` + --> $DIR/allow_const_fn_ptr.rs:6:16 | LL | const fn error(_: fn()) {} | ^ | - = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = note: otherwise `#[allow_internal_unstable]` can be used to bypass stability checks +help: if it is not part of the public API, make this function unstably const + | +LL | #[rustc_const_unstable(feature = "...", issue = "...")] + | error: aborting due to previous error -For more information about this error, try `rustc --explain E0723`. diff --git a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.stderr b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.stderr index 7794cc7583dfc..23e31c80c435a 100644 --- a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.stderr +++ b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.stderr @@ -1,11 +1,33 @@ -error[E0658]: internal implementation detail - --> $DIR/allow_const_fn_ptr_feature_gate.rs:7:1 +error: stable const functions must have either `rustc_const_stable` or `rustc_const_unstable` attribute + --> $DIR/allow_const_fn_ptr_feature_gate.rs:4:1 | -LL | #[rustc_allow_const_fn_ptr] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | const fn error(_: fn()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: stable const functions must have either `rustc_const_stable` or `rustc_const_unstable` attribute + --> $DIR/allow_const_fn_ptr_feature_gate.rs:4:1 + | +LL | const fn error(_: fn()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0658]: function pointers cannot appear in constant functions + --> $DIR/allow_const_fn_ptr_feature_gate.rs:4:16 + | +LL | const fn error(_: fn()) {} + | ^ + | + = note: see issue #57563 for more information + = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable + +error[E0658]: function pointers cannot appear in constant functions + --> $DIR/allow_const_fn_ptr_feature_gate.rs:11:19 + | +LL | const fn compiles(_: fn()) {} + | ^ | - = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable + = note: see issue #57563 for more information + = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/min_const_fn/cast_errors.stderr b/src/test/ui/consts/min_const_fn/cast_errors.stderr index 583cb4e9720cc..ac77c181afda8 100644 --- a/src/test/ui/consts/min_const_fn/cast_errors.stderr +++ b/src/test/ui/consts/min_const_fn/cast_errors.stderr @@ -1,39 +1,39 @@ -error[E0723]: function pointers in const fn are unstable +error[E0658]: function pointers cannot appear in constant functions --> $DIR/cast_errors.rs:4:23 | LL | const fn closure() -> fn() { || {} } | ^^^^ | = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable -error[E0723]: function pointers in const fn are unstable +error[E0658]: function pointers cannot appear in constant functions --> $DIR/cast_errors.rs:7:5 | LL | (|| {}) as fn(); | ^^^^^^^^^^^^^^^ | = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable -error[E0723]: function pointers in const fn are unstable +error[E0658]: function pointers cannot appear in constant functions --> $DIR/cast_errors.rs:10:28 | LL | const fn reify(f: fn()) -> unsafe fn() { f } | ^^^^^^^^^^^ | = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable -error[E0723]: function pointers in const fn are unstable +error[E0658]: function pointers cannot appear in constant functions --> $DIR/cast_errors.rs:12:21 | LL | const fn reify2() { main as unsafe fn(); } | ^^^^^^^^^^^^^^^^^^^ | = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0723`. +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/min_const_fn/cmp_fn_pointers.stderr b/src/test/ui/consts/min_const_fn/cmp_fn_pointers.stderr index 74e5228d0dc62..e913b187feeae 100644 --- a/src/test/ui/consts/min_const_fn/cmp_fn_pointers.stderr +++ b/src/test/ui/consts/min_const_fn/cmp_fn_pointers.stderr @@ -1,12 +1,12 @@ -error[E0723]: function pointers in const fn are unstable +error[E0658]: function pointers cannot appear in constant functions --> $DIR/cmp_fn_pointers.rs:1:14 | LL | const fn cmp(x: fn(), y: fn()) -> bool { | ^ | = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable error: aborting due to previous error -For more information about this error, try `rustc --explain E0723`. +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr index a37e5203eeef4..5e6bf7ef89034 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr @@ -209,23 +209,23 @@ LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 = note: see issue #57563 for more information = help: add `#![feature(const_fn)]` to the crate attributes to enable -error[E0723]: function pointers in const fn are unstable +error[E0658]: function pointers cannot appear in constant functions --> $DIR/min_const_fn.rs:130:21 | LL | const fn no_fn_ptrs(_x: fn()) {} | ^^ | = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable -error[E0723]: function pointers in const fn are unstable +error[E0658]: function pointers cannot appear in constant functions --> $DIR/min_const_fn.rs:132:27 | LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo } | ^^^^ | = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable error: aborting due to 26 previous errors diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr index 58acbb5339aff..52269c1e2ac59 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr @@ -1,21 +1,21 @@ -error[E0723]: function pointers in const fn are unstable +error[E0658]: function pointers cannot appear in constant functions --> $DIR/min_const_fn_fn_ptr.rs:11:5 | LL | x.0.field; | ^^^^^^^^^ | = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable -error[E0723]: function pointers in const fn are unstable +error[E0658]: function pointers cannot appear in constant functions --> $DIR/min_const_fn_fn_ptr.rs:14:59 | LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasPtr { field }) } | ^^^^^ | = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0723`. +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr b/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr index 93b67fd7b1428..8fd562c5dae84 100644 --- a/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr +++ b/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr @@ -12,12 +12,12 @@ LL | static VAL: () = call_rust_fn(unsafe { std::mem::transmute(c_fn as extern " warning: skipping const checks | -help: skipping check for `const_fn` feature +help: skipping check for `const_fn_fn_ptr_basics` feature --> $DIR/abi-mismatch.rs:9:23 | LL | const fn call_rust_fn(my_fn: extern "Rust" fn()) { | ^^^^^ -help: skipping check for `const_fn` feature +help: skipping check for `const_fn_fn_ptr_basics` feature --> $DIR/abi-mismatch.rs:10:5 | LL | my_fn(); diff --git a/src/test/ui/issues/issue-37550.stderr b/src/test/ui/issues/issue-37550.stderr index 35da625801617..54b60df70fd26 100644 --- a/src/test/ui/issues/issue-37550.stderr +++ b/src/test/ui/issues/issue-37550.stderr @@ -1,12 +1,12 @@ -error[E0723]: function pointers in const fn are unstable +error[E0658]: function pointers cannot appear in constant functions --> $DIR/issue-37550.rs:3:9 | LL | let x = || t; | ^ | = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable error: aborting due to previous error -For more information about this error, try `rustc --explain E0723`. +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.stderr b/src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.stderr index cf8ca57714c29..0291a52633358 100644 --- a/src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.stderr +++ b/src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.stderr @@ -1,10 +1,27 @@ warning: skipping const checks | +help: skipping check for `const_fn_fn_ptr_basics` feature + --> $DIR/caller-location-fnptr-rt-ctfe-equiv.rs:20:9 + | +LL | let ptr: fn() -> L = attributed; + | ^^^ +help: skipping check for `const_fn_fn_ptr_basics` feature + --> $DIR/caller-location-fnptr-rt-ctfe-equiv.rs:21:5 + | +LL | ptr() + | ^^^ +help: skipping check for `const_fn_fn_ptr_basics` feature + --> $DIR/caller-location-fnptr-rt-ctfe-equiv.rs:20:26 + | +LL | let ptr: fn() -> L = attributed; + | ^^^^^^^^^^ help: skipping check that does not even have a feature gate --> $DIR/caller-location-fnptr-rt-ctfe-equiv.rs:21:5 | LL | ptr() | ^^^^^ -warning: 1 warning emitted +error: `-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature gates, except when testing error paths in the CTFE engine + +error: aborting due to previous error; 1 warning emitted From 16f36db17753f8c5eaceea633b123b21ec87ef5f Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Thu, 24 Sep 2020 16:49:12 -0700 Subject: [PATCH 11/16] Mark `min_const_fn_fn_ptr` test as gate test --- src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs | 2 ++ src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs b/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs index 985220ec7ae1d..bc6fe89222bbf 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs +++ b/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs @@ -1,3 +1,5 @@ +// gate-test-const_fn_fn_ptr_basics + struct HasPtr { field: fn(), } diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr index 52269c1e2ac59..8d60436ea39bb 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr @@ -1,5 +1,5 @@ error[E0658]: function pointers cannot appear in constant functions - --> $DIR/min_const_fn_fn_ptr.rs:11:5 + --> $DIR/min_const_fn_fn_ptr.rs:13:5 | LL | x.0.field; | ^^^^^^^^^ @@ -8,7 +8,7 @@ LL | x.0.field; = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable error[E0658]: function pointers cannot appear in constant functions - --> $DIR/min_const_fn_fn_ptr.rs:14:59 + --> $DIR/min_const_fn_fn_ptr.rs:16:59 | LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasPtr { field }) } | ^^^^^ From d9fc5b5ea8e48e9d24a7dfb8cab1dacb60d5cb7f Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 27 Sep 2020 00:09:45 -0400 Subject: [PATCH 12/16] Fix typo in ExpnData documentation This mis-highlighted the entire documentation as code. --- compiler/rustc_span/src/hygiene.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 942c6648340ef..fe500355c1ed7 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -702,7 +702,7 @@ pub struct ExpnData { /// The `DefId` of the macro being invoked, /// if this `ExpnData` corresponds to a macro invocation pub macro_def_id: Option, - /// The crate that originally created this `ExpnData. During + /// The crate that originally created this `ExpnData`. During /// metadata serialization, we only encode `ExpnData`s that were /// created locally - when our serialized metadata is decoded, /// foreign `ExpnId`s will have their `ExpnData` looked up From 3d4a2e6bb93ce4d1ffd77be7eaf3e4b752104346 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Sun, 27 Sep 2020 11:00:46 +0200 Subject: [PATCH 13/16] Remove duplicate comment --- compiler/rustc_session/src/session.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index ff67d3cb107d9..ff5e6156d846b 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1103,9 +1103,6 @@ impl Session { self.used_attrs.lock().is_marked(attr) } - /// Returns `true` if the attribute's path matches the argument. If it matches, then the - /// attribute is marked as used. - /// Returns `true` if the attribute's path matches the argument. If it /// matches, then the attribute is marked as used. /// From e4200512ff976b9c1afff8069ae66ace52dfbcb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Sun, 27 Sep 2020 11:54:50 +0200 Subject: [PATCH 14/16] Clean up trivial if let --- compiler/rustc_span/src/hygiene.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 942c6648340ef..3e28468171b2e 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -759,7 +759,7 @@ impl ExpnData { #[inline] pub fn is_root(&self) -> bool { - if let ExpnKind::Root = self.kind { true } else { false } + matches!(self.kind, ExpnKind::Root) } } From 03d8be08967e3fbc358bc9fe9fad9a06ddabb17f Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sat, 26 Sep 2020 21:27:55 -0400 Subject: [PATCH 15/16] Separate `private_intra_doc_links` and `broken_intra_doc_links` into separate lints This is not ideal because it means `deny(broken_intra_doc_links)` will no longer `deny(private_intra_doc_links)`. However, it can't be fixed with a new lint group, because `broken` is already in the `rustdoc` lint group; there would need to be a way to nest groups somehow. This also removes the early `return` so that the link will be generated even though it gives a warning. --- compiler/rustc_lint/src/lib.rs | 1 + compiler/rustc_session/src/lint/builtin.rs | 11 ++++++++++ .../passes/collect_intra_doc_links.rs | 21 ++++++++++++------- .../intra-links-private.private.stderr | 2 +- .../intra-links-private.public.stderr | 2 +- .../rustdoc-ui/issue-74134.private.stderr | 2 +- src/test/rustdoc-ui/issue-74134.public.stderr | 2 +- src/test/rustdoc/intra-doc-link-private.rs | 6 ++++++ 8 files changed, 35 insertions(+), 12 deletions(-) create mode 100644 src/test/rustdoc/intra-doc-link-private.rs diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 7f7472d9283b8..33caedfc19826 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -305,6 +305,7 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) { add_lint_group!( "rustdoc", BROKEN_INTRA_DOC_LINKS, + PRIVATE_INTRA_DOC_LINKS, INVALID_CODEBLOCK_ATTRIBUTES, MISSING_DOC_CODE_EXAMPLES, PRIVATE_DOC_TESTS diff --git a/compiler/rustc_session/src/lint/builtin.rs b/compiler/rustc_session/src/lint/builtin.rs index 13a4057a35bdf..8c3218b8e806a 100644 --- a/compiler/rustc_session/src/lint/builtin.rs +++ b/compiler/rustc_session/src/lint/builtin.rs @@ -1826,6 +1826,17 @@ declare_lint! { "failures in resolving intra-doc link targets" } +declare_lint! { + /// This is a subset of `broken_intra_doc_links` that warns when linking from + /// a public item to a private one. This is a `rustdoc` only lint, see the + /// documentation in the [rustdoc book]. + /// + /// [rustdoc book]: ../../../rustdoc/lints.html#broken_intra_doc_links + pub PRIVATE_INTRA_DOC_LINKS, + Warn, + "linking from a public item to a private one" +} + declare_lint! { /// The `invalid_codeblock_attributes` lint detects code block attributes /// in documentation examples that have potentially mis-typed values. This diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 5d74a3da9a205..cd6a7feb18029 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -11,7 +11,10 @@ use rustc_hir::def::{ use rustc_hir::def_id::DefId; use rustc_middle::ty; use rustc_resolve::ParentScope; -use rustc_session::lint; +use rustc_session::lint::{ + builtin::{BROKEN_INTRA_DOC_LINKS, PRIVATE_INTRA_DOC_LINKS}, + Lint, +}; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::Ident; use rustc_span::symbol::Symbol; @@ -988,7 +991,7 @@ impl LinkCollector<'_, '_> { let report_mismatch = |specified: Disambiguator, resolved: Disambiguator| { // The resolved item did not match the disambiguator; give a better error than 'not found' let msg = format!("incompatible link kind for `{}`", path_str); - report_diagnostic(cx, &msg, &item, dox, &link_range, |diag, sp| { + let callback = |diag: &mut DiagnosticBuilder<'_>, sp| { let note = format!( "this link resolved to {} {}, which is not {} {}", resolved.article(), @@ -998,7 +1001,8 @@ impl LinkCollector<'_, '_> { ); diag.note(¬e); suggest_disambiguator(resolved, diag, path_str, dox, sp, &link_range); - }); + }; + report_diagnostic(cx, BROKEN_INTRA_DOC_LINKS, &msg, &item, dox, &link_range, callback); }; if let Res::PrimTy(..) = res { match disambiguator { @@ -1055,7 +1059,6 @@ impl LinkCollector<'_, '_> { && !self.cx.tcx.privacy_access_levels(LOCAL_CRATE).is_exported(hir_dst) { privacy_error(cx, &item, &path_str, dox, link_range); - return; } } let id = register_res(cx, res); @@ -1417,6 +1420,7 @@ impl Suggestion { /// to it. fn report_diagnostic( cx: &DocContext<'_>, + lint: &'static Lint, msg: &str, item: &Item, dox: &str, @@ -1435,7 +1439,7 @@ fn report_diagnostic( let attrs = &item.attrs; let sp = span_of_attrs(attrs).unwrap_or(item.source.span()); - cx.tcx.struct_span_lint_hir(lint::builtin::BROKEN_INTRA_DOC_LINKS, hir_id, sp, |lint| { + cx.tcx.struct_span_lint_hir(lint, hir_id, sp, |lint| { let mut diag = lint.build(msg); let span = link_range @@ -1482,6 +1486,7 @@ fn resolution_failure( ) { report_diagnostic( collector.cx, + BROKEN_INTRA_DOC_LINKS, &format!("unresolved link to `{}`", path_str), item, dox, @@ -1695,7 +1700,7 @@ fn anchor_failure( ), }; - report_diagnostic(cx, &msg, item, dox, &link_range, |diag, sp| { + report_diagnostic(cx, BROKEN_INTRA_DOC_LINKS, &msg, item, dox, &link_range, |diag, sp| { if let Some(sp) = sp { diag.span_label(sp, "contains invalid anchor"); } @@ -1734,7 +1739,7 @@ fn ambiguity_error( } } - report_diagnostic(cx, &msg, item, dox, &link_range, |diag, sp| { + report_diagnostic(cx, BROKEN_INTRA_DOC_LINKS, &msg, item, dox, &link_range, |diag, sp| { if let Some(sp) = sp { diag.span_label(sp, "ambiguous link"); } else { @@ -1784,7 +1789,7 @@ fn privacy_error( let msg = format!("public documentation for `{}` links to private item `{}`", item_name, path_str); - report_diagnostic(cx, &msg, item, dox, &link_range, |diag, sp| { + report_diagnostic(cx, PRIVATE_INTRA_DOC_LINKS, &msg, item, dox, &link_range, |diag, sp| { if let Some(sp) = sp { diag.span_label(sp, "this item is private"); } diff --git a/src/test/rustdoc-ui/intra-links-private.private.stderr b/src/test/rustdoc-ui/intra-links-private.private.stderr index 77c4b67a6528f..eeef24b479747 100644 --- a/src/test/rustdoc-ui/intra-links-private.private.stderr +++ b/src/test/rustdoc-ui/intra-links-private.private.stderr @@ -4,7 +4,7 @@ warning: public documentation for `DocMe` links to private item `DontDocMe` LL | /// docs [DontDocMe] | ^^^^^^^^^ this item is private | - = note: `#[warn(broken_intra_doc_links)]` on by default + = note: `#[warn(private_intra_doc_links)]` on by default = note: this link resolves only because you passed `--document-private-items`, but will break without warning: 1 warning emitted diff --git a/src/test/rustdoc-ui/intra-links-private.public.stderr b/src/test/rustdoc-ui/intra-links-private.public.stderr index 312a78e8c3ec7..3f7b17586f19e 100644 --- a/src/test/rustdoc-ui/intra-links-private.public.stderr +++ b/src/test/rustdoc-ui/intra-links-private.public.stderr @@ -4,7 +4,7 @@ warning: public documentation for `DocMe` links to private item `DontDocMe` LL | /// docs [DontDocMe] | ^^^^^^^^^ this item is private | - = note: `#[warn(broken_intra_doc_links)]` on by default + = note: `#[warn(private_intra_doc_links)]` on by default = note: this link will resolve properly if you pass `--document-private-items` warning: 1 warning emitted diff --git a/src/test/rustdoc-ui/issue-74134.private.stderr b/src/test/rustdoc-ui/issue-74134.private.stderr index 58772109140ca..b802d7e12523a 100644 --- a/src/test/rustdoc-ui/issue-74134.private.stderr +++ b/src/test/rustdoc-ui/issue-74134.private.stderr @@ -4,7 +4,7 @@ warning: public documentation for `public_item` links to private item `PrivateTy LL | /// [`PrivateType`] | ^^^^^^^^^^^^^ this item is private | - = note: `#[warn(broken_intra_doc_links)]` on by default + = note: `#[warn(private_intra_doc_links)]` on by default = note: this link resolves only because you passed `--document-private-items`, but will break without warning: 1 warning emitted diff --git a/src/test/rustdoc-ui/issue-74134.public.stderr b/src/test/rustdoc-ui/issue-74134.public.stderr index b5bea190941e6..40aa2ece1a373 100644 --- a/src/test/rustdoc-ui/issue-74134.public.stderr +++ b/src/test/rustdoc-ui/issue-74134.public.stderr @@ -4,7 +4,7 @@ warning: public documentation for `public_item` links to private item `PrivateTy LL | /// [`PrivateType`] | ^^^^^^^^^^^^^ this item is private | - = note: `#[warn(broken_intra_doc_links)]` on by default + = note: `#[warn(private_intra_doc_links)]` on by default = note: this link will resolve properly if you pass `--document-private-items` warning: 1 warning emitted diff --git a/src/test/rustdoc/intra-doc-link-private.rs b/src/test/rustdoc/intra-doc-link-private.rs new file mode 100644 index 0000000000000..f86ca44403d93 --- /dev/null +++ b/src/test/rustdoc/intra-doc-link-private.rs @@ -0,0 +1,6 @@ +#![crate_name = "private"] +// compile-flags: --document-private-items +/// docs [DontDocMe] +// @has private/struct.DocMe.html '//*a[@href="../private/struct.DontDocMe.html"]' 'DontDocMe' +pub struct DocMe; +struct DontDocMe; From 80ffaed809aa9bf659acf146a26d851f594c0b25 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 27 Sep 2020 10:07:00 -0400 Subject: [PATCH 16/16] Add documentation for `private_intra_doc_links` --- compiler/rustc_session/src/lint/builtin.rs | 2 +- src/doc/rustdoc/src/lints.md | 40 ++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_session/src/lint/builtin.rs b/compiler/rustc_session/src/lint/builtin.rs index 8c3218b8e806a..0cc97fb4541d1 100644 --- a/compiler/rustc_session/src/lint/builtin.rs +++ b/compiler/rustc_session/src/lint/builtin.rs @@ -1831,7 +1831,7 @@ declare_lint! { /// a public item to a private one. This is a `rustdoc` only lint, see the /// documentation in the [rustdoc book]. /// - /// [rustdoc book]: ../../../rustdoc/lints.html#broken_intra_doc_links + /// [rustdoc book]: ../../../rustdoc/lints.html#private_intra_doc_links pub PRIVATE_INTRA_DOC_LINKS, Warn, "linking from a public item to a private one" diff --git a/src/doc/rustdoc/src/lints.md b/src/doc/rustdoc/src/lints.md index 9ff897710f650..3e632a0644a73 100644 --- a/src/doc/rustdoc/src/lints.md +++ b/src/doc/rustdoc/src/lints.md @@ -62,6 +62,46 @@ help: to link to the function, add parentheses ``` +## private_intra_doc_links + +This lint **warns by default**. This lint detects when [intra-doc links] from public to private items. +For example: + +```rust +/// [private] +pub fn public() {} +fn private() {} +``` + +This gives a warning that the link will be broken when it appears in your documentation: + +```text +warning: public documentation for `public` links to private item `private` + --> priv.rs:1:6 + | +1 | /// [private] + | ^^^^^^^ this item is private + | + = note: `#[warn(private_intra_doc_links)]` on by default + = note: this link will resolve properly if you pass `--document-private-items` +``` + +Note that this has different behavior depending on whether you pass `--document-private-items` or not! +If you document private items, then it will still generate a link, despite the warning: + +```text +warning: public documentation for `public` links to private item `private` + --> priv.rs:1:6 + | +1 | /// [private] + | ^^^^^^^ this item is private + | + = note: `#[warn(private_intra_doc_links)]` on by default + = note: this link resolves only because you passed `--document-private-items`, but will break without +``` + +[intra-doc links]: linking-to-items-by-name.html + ## missing_docs This lint is **allowed by default**. It detects items missing documentation.