target: self.target,
mode: "ui",
suite: "rustdoc-ui",
- path: None,
+ path: Some("src/test/rustdoc-ui"),
compare_mode: None,
})
}
///
/// # Examples
///
-/// Basic usage with `i32`:
+/// Basic usage with `f64`:
///
/// ```
/// let x = 42.0; // 42.0 is '4.2e1' in scientific notation
///
/// # Examples
///
-/// Basic usage with `f32`:
+/// Basic usage with `f64`:
///
/// ```
/// let x = 42.0; // 42.0 is '4.2E1' in scientific notation
self.sess.diagnostic()
}
- fn str_to_ident(&self, s: &'static str) -> Ident {
- Ident::with_empty_ctxt(Symbol::gensym(s))
- }
-
fn with_anonymous_lifetime_mode<R>(
&mut self,
anonymous_lifetime_mode: AnonymousLifetimeMode,
);
head.span = desugared_span;
- let iter = self.str_to_ident("iter");
+ let iter = Ident::with_empty_ctxt(sym::iter);
- let next_ident = self.str_to_ident("__next");
+ let next_ident = Ident::with_empty_ctxt(sym::__next);
let (next_pat, next_pat_hid) = self.pat_ident_binding_mode(
desugared_span,
next_ident,
hir::BindingAnnotation::Mutable,
);
- // `::std::option::Option::Some(val) => next = val`
+ // `::std::option::Option::Some(val) => __next = val`
let pat_arm = {
- let val_ident = self.str_to_ident("val");
+ let val_ident = Ident::with_empty_ctxt(sym::val);
let (val_pat, val_pat_hid) = self.pat_ident(pat.span, val_ident);
let val_expr = P(self.expr_ident(pat.span, val_ident, val_pat_hid));
let next_expr = P(self.expr_ident(pat.span, next_ident, next_pat_hid));
let unstable_span = self.sess.source_map().mark_span_with_reason(
CompilerDesugaringKind::QuestionMark,
e.span,
- Some(vec![
- Symbol::intern("try_trait")
- ].into()),
+ Some(vec![sym::try_trait].into()),
);
let try_span = self.sess.source_map().end_point(e.span);
let try_span = self.sess.source_map().mark_span_with_reason(
CompilerDesugaringKind::QuestionMark,
try_span,
- Some(vec![
- Symbol::intern("try_trait")
- ].into()),
+ Some(vec![sym::try_trait].into()),
);
// `Try::into_result(<expr>)`
// `allow(unreachable_code)`
let allow = {
let allow_ident = Ident::with_empty_ctxt(sym::allow).with_span_pos(e.span);
- let uc_ident = Ident::from_str("unreachable_code").with_span_pos(e.span);
+ let uc_ident = Ident::with_empty_ctxt(sym::unreachable_code)
+ .with_span_pos(e.span);
let uc_nested = attr::mk_nested_word_item(uc_ident);
attr::mk_list_item(e.span, allow_ident, vec![uc_nested])
};
// `Ok(val) => #[allow(unreachable_code)] val,`
let ok_arm = {
- let val_ident = self.str_to_ident("val");
+ let val_ident = Ident::with_empty_ctxt(sym::val);
let (val_pat, val_pat_nid) = self.pat_ident(e.span, val_ident);
let val_expr = P(self.expr_ident_with_attrs(
e.span,
// `Err(err) => #[allow(unreachable_code)]
// return Try::from_error(From::from(err)),`
let err_arm = {
- let err_ident = self.str_to_ident("err");
+ let err_ident = Ident::with_empty_ctxt(sym::err);
let (err_local, err_local_nid) = self.pat_ident(try_span, err_ident);
let from_expr = {
let from_path = &[sym::convert, sym::From, sym::from];
// match ::std::future::poll_with_tls_context(unsafe {
// ::std::pin::Pin::new_unchecked(&mut pinned)
// }) {
- // ::std::task::Poll::Ready(x) => break x,
+ // ::std::task::Poll::Ready(result) => break result,
// ::std::task::Poll::Pending => {},
// }
// yield ();
let gen_future_span = self.sess.source_map().mark_span_with_reason(
CompilerDesugaringKind::Await,
await_span,
- Some(vec![Symbol::intern("gen_future")].into()),
+ Some(vec![sym::gen_future].into()),
);
// let mut pinned = <expr>;
let expr = P(self.lower_expr(expr));
- let pinned_ident = self.str_to_ident("pinned");
+ let pinned_ident = Ident::with_empty_ctxt(sym::pinned);
let (pinned_pat, pinned_pat_hid) = self.pat_ident_binding_mode(
span,
pinned_ident,
))
};
- // `::std::task::Poll::Ready(x) => break x`
+ // `::std::task::Poll::Ready(result) => break result`
let loop_node_id = self.sess.next_node_id();
let loop_hir_id = self.lower_node_id(loop_node_id);
let ready_arm = {
- let x_ident = self.str_to_ident("x");
+ let x_ident = Ident::with_empty_ctxt(sym::result);
let (x_pat, x_pat_hid) = self.pat_ident(span, x_ident);
let x_expr = P(self.expr_ident(span, x_ident, x_pat_hid));
let ready_pat = self.pat_std_enum(
let push = builder.levels.push(&krate.attrs);
builder.levels.register_id(hir::CRATE_HIR_ID);
+ for macro_def in &krate.exported_macros {
+ builder.levels.register_id(macro_def.hir_id);
+ }
intravisit::walk_crate(&mut builder, krate);
builder.levels.pop(push);
return
}
// The x86 ABI seems to require that leading underscores are added to symbol
- // names, so we need an extra underscore on 32-bit. There's also a leading
+ // names, so we need an extra underscore on x86. There's also a leading
// '\x01' here which disables LLVM's symbol mangling (e.g., no extra
// underscores added in front).
- let prefix = if cgcx.target_pointer_width == "32" {
+ let prefix = if cgcx.target_arch == "x86" {
"\x01__imp__"
} else {
"\x01__imp_"
pub tm_factory: TargetMachineFactory<B>,
pub msvc_imps_needed: bool,
pub target_pointer_width: String,
+ pub target_arch: String,
pub debuginfo: config::DebugInfo,
// Number of cgus excluding the allocator/metadata modules
total_cgus,
msvc_imps_needed: msvc_imps_needed(tcx),
target_pointer_width: tcx.sess.target.target.target_pointer_width.clone(),
+ target_arch: tcx.sess.target.target.arch.clone(),
debuginfo: tcx.sess.opts.debuginfo,
assembler_cmd,
};
}
}
}
+
+ fn should_const_prop(&self) -> bool {
+ self.tcx.sess.opts.debugging_opts.mir_opt_level >= 2
+ }
}
fn type_size_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
assert!(self.places[local].is_none());
self.places[local] = Some(value);
- if self.tcx.sess.opts.debugging_opts.mir_opt_level >= 2 {
+ if self.should_const_prop() {
self.replace_with_const(rval, value, statement.source_info.span);
}
}
location: Location,
) {
self.super_terminator(terminator, location);
- let source_info = terminator.source_info;;
- if let TerminatorKind::Assert { expected, msg, cond, .. } = &terminator.kind {
- if let Some(value) = self.eval_operand(&cond, source_info) {
- trace!("assertion on {:?} should be {:?}", value, expected);
- let expected = ScalarMaybeUndef::from(Scalar::from_bool(*expected));
- if expected != self.ecx.read_scalar(value).unwrap() {
- // poison all places this operand references so that further code
- // doesn't use the invalid value
- match cond {
- Operand::Move(ref place) | Operand::Copy(ref place) => {
- let mut place = place;
- while let Place::Projection(ref proj) = *place {
- place = &proj.base;
- }
- if let Place::Base(PlaceBase::Local(local)) = *place {
- self.places[local] = None;
+ let source_info = terminator.source_info;
+ match &mut terminator.kind {
+ TerminatorKind::Assert { expected, msg, ref mut cond, .. } => {
+ if let Some(value) = self.eval_operand(&cond, source_info) {
+ trace!("assertion on {:?} should be {:?}", value, expected);
+ let expected = ScalarMaybeUndef::from(Scalar::from_bool(*expected));
+ let value_const = self.ecx.read_scalar(value).unwrap();
+ if expected != value_const {
+ // poison all places this operand references so that further code
+ // doesn't use the invalid value
+ match cond {
+ Operand::Move(ref place) | Operand::Copy(ref place) => {
+ let mut place = place;
+ while let Place::Projection(ref proj) = *place {
+ place = &proj.base;
+ }
+ if let Place::Base(PlaceBase::Local(local)) = *place {
+ self.places[local] = None;
+ }
+ },
+ Operand::Constant(_) => {}
+ }
+ let span = terminator.source_info.span;
+ let hir_id = self
+ .tcx
+ .hir()
+ .as_local_hir_id(self.source.def_id())
+ .expect("some part of a failing const eval must be local");
+ use rustc::mir::interpret::InterpError::*;
+ let msg = match msg {
+ Overflow(_) |
+ OverflowNeg |
+ DivisionByZero |
+ RemainderByZero => msg.description().to_owned(),
+ BoundsCheck { ref len, ref index } => {
+ let len = self
+ .eval_operand(len, source_info)
+ .expect("len must be const");
+ let len = match self.ecx.read_scalar(len) {
+ Ok(ScalarMaybeUndef::Scalar(Scalar::Bits {
+ bits, ..
+ })) => bits,
+ other => bug!("const len not primitive: {:?}", other),
+ };
+ let index = self
+ .eval_operand(index, source_info)
+ .expect("index must be const");
+ let index = match self.ecx.read_scalar(index) {
+ Ok(ScalarMaybeUndef::Scalar(Scalar::Bits {
+ bits, ..
+ })) => bits,
+ other => bug!("const index not primitive: {:?}", other),
+ };
+ format!(
+ "index out of bounds: \
+ the len is {} but the index is {}",
+ len,
+ index,
+ )
+ },
+ // Need proper const propagator for these
+ _ => return,
+ };
+ self.tcx.lint_hir(
+ ::rustc::lint::builtin::CONST_ERR,
+ hir_id,
+ span,
+ &msg,
+ );
+ } else {
+ if self.should_const_prop() {
+ if let ScalarMaybeUndef::Scalar(scalar) = value_const {
+ *cond = self.operand_from_scalar(
+ scalar,
+ self.tcx.types.bool,
+ source_info.span,
+ );
}
- },
- Operand::Constant(_) => {}
+ }
}
- let span = terminator.source_info.span;
- let hir_id = self
- .tcx
- .hir()
- .as_local_hir_id(self.source.def_id())
- .expect("some part of a failing const eval must be local");
- use rustc::mir::interpret::InterpError::*;
- let msg = match msg {
- Overflow(_) |
- OverflowNeg |
- DivisionByZero |
- RemainderByZero => msg.description().to_owned(),
- BoundsCheck { ref len, ref index } => {
- let len = self
- .eval_operand(len, source_info)
- .expect("len must be const");
- let len = match self.ecx.read_scalar(len) {
- Ok(ScalarMaybeUndef::Scalar(Scalar::Bits {
- bits, ..
- })) => bits,
- other => bug!("const len not primitive: {:?}", other),
- };
- let index = self
- .eval_operand(index, source_info)
- .expect("index must be const");
- let index = match self.ecx.read_scalar(index) {
- Ok(ScalarMaybeUndef::Scalar(Scalar::Bits {
- bits, ..
- })) => bits,
- other => bug!("const index not primitive: {:?}", other),
- };
- format!(
- "index out of bounds: \
- the len is {} but the index is {}",
- len,
- index,
- )
- },
- // Need proper const propagator for these
- _ => return,
- };
- self.tcx.lint_hir(
- ::rustc::lint::builtin::CONST_ERR,
- hir_id,
- span,
- &msg,
- );
}
- }
+ },
+ TerminatorKind::SwitchInt { ref mut discr, switch_ty, .. } => {
+ if self.should_const_prop() {
+ if let Some(value) = self.eval_operand(&discr, source_info) {
+ if let ScalarMaybeUndef::Scalar(scalar) =
+ self.ecx.read_scalar(value).unwrap() {
+ *discr = self.operand_from_scalar(scalar, switch_ty, source_info.span);
+ }
+ }
+ }
+ },
+ //none of these have Operands to const-propagate
+ TerminatorKind::Goto { .. } |
+ TerminatorKind::Resume |
+ TerminatorKind::Abort |
+ TerminatorKind::Return |
+ TerminatorKind::Unreachable |
+ TerminatorKind::Drop { .. } |
+ TerminatorKind::DropAndReplace { .. } |
+ TerminatorKind::Yield { .. } |
+ TerminatorKind::GeneratorDrop |
+ TerminatorKind::FalseEdges { .. } |
+ TerminatorKind::FalseUnwind { .. } => { }
+ //FIXME(wesleywiser) Call does have Operands that could be const-propagated
+ TerminatorKind::Call { .. } => { }
}
}
}
pub locol: usize,
pub hiline: usize,
pub hicol: usize,
+ pub original: syntax_pos::Span,
}
impl Span {
filename: FileName::Anon(0),
loline: 0, locol: 0,
hiline: 0, hicol: 0,
+ original: syntax_pos::DUMMY_SP,
}
}
+
+ pub fn span(&self) -> syntax_pos::Span {
+ self.original
+ }
}
impl Clean<Span> for syntax_pos::Span {
locol: lo.col.to_usize(),
hiline: hi.line,
hicol: hi.col.to_usize(),
+ original: *self,
}
}
}
if let Ok(res) = self.resolve(path_str, ns, ¤t_item, parent_node) {
res
} else {
- resolution_failure(cx, &item.attrs, path_str, &dox, link_range);
+ resolution_failure(cx, &item, path_str, &dox, link_range);
// This could just be a normal link or a broken link
// we could potentially check if something is
// "intra-doc-link-like" and warn in that case.
if let Ok(res) = self.resolve(path_str, ns, ¤t_item, parent_node) {
res
} else {
- resolution_failure(cx, &item.attrs, path_str, &dox, link_range);
+ resolution_failure(cx, &item, path_str, &dox, link_range);
// This could just be a normal link.
continue;
}
};
if candidates.is_empty() {
- resolution_failure(cx, &item.attrs, path_str, &dox, link_range);
+ resolution_failure(cx, &item, path_str, &dox, link_range);
// this could just be a normal link
continue;
}
} else {
ambiguity_error(
cx,
- &item.attrs,
+ &item,
path_str,
&dox,
link_range,
if let Some(res) = macro_resolve(cx, path_str) {
(res, None)
} else {
- resolution_failure(cx, &item.attrs, path_str, &dox, link_range);
+ resolution_failure(cx, &item, path_str, &dox, link_range);
continue
}
}
/// line containing the failure as a note as well.
fn resolution_failure(
cx: &DocContext<'_>,
- attrs: &Attributes,
+ item: &Item,
path_str: &str,
dox: &str,
link_range: Option<Range<usize>>,
) {
+ let hir_id = match cx.as_local_hir_id(item.def_id) {
+ Some(hir_id) => hir_id,
+ None => {
+ // If non-local, no need to check anything.
+ return;
+ }
+ };
+ let attrs = &item.attrs;
let sp = span_of_attrs(attrs);
let mut diag = cx.tcx.struct_span_lint_hir(
lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
- hir::CRATE_HIR_ID,
+ hir_id,
sp,
&format!("`[{}]` cannot be resolved, ignoring it...", path_str),
);
fn ambiguity_error(
cx: &DocContext<'_>,
- attrs: &Attributes,
+ item: &Item,
path_str: &str,
dox: &str,
link_range: Option<Range<usize>>,
candidates: PerNS<Option<Res>>,
) {
+ let hir_id = match cx.as_local_hir_id(item.def_id) {
+ Some(hir_id) => hir_id,
+ None => {
+ // If non-local, no need to check anything.
+ return;
+ }
+ };
+ let attrs = &item.attrs;
let sp = span_of_attrs(attrs);
let mut msg = format!("`{}` is ", path_str);
let mut diag = cx.tcx.struct_span_lint_hir(
lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
- hir::CRATE_HIR_ID,
+ hir_id,
sp,
&msg,
);
//! Contains information about "passes", used to modify crate information during the documentation
//! process.
-use rustc::hir;
use rustc::hir::def_id::DefId;
use rustc::lint as lint;
use rustc::middle::privacy::AccessLevels;
item: &Item,
check_missing_code: bool,
) {
- if cx.as_local_hir_id(item.def_id).is_none() {
- // If non-local, no need to check anything.
- return;
- }
+ let hir_id = match cx.as_local_hir_id(item.def_id) {
+ Some(hir_id) => hir_id,
+ None => {
+ // If non-local, no need to check anything.
+ return;
+ }
+ };
struct Tests {
found_tests: usize,
find_testable_code(&dox, &mut tests, ErrorCodes::No);
if check_missing_code == true && tests.found_tests == 0 {
+ let sp = span_of_attrs(&item.attrs).substitute_dummy(item.source.span());
let mut diag = cx.tcx.struct_span_lint_hir(
lint::builtin::MISSING_DOC_CODE_EXAMPLES,
- hir::CRATE_HIR_ID,
- span_of_attrs(&item.attrs),
+ hir_id,
+ sp,
"Missing code example in this documentation");
diag.emit();
} else if check_missing_code == false &&
!cx.renderinfo.borrow().access_levels.is_doc_reachable(item.def_id) {
let mut diag = cx.tcx.struct_span_lint_hir(
lint::builtin::PRIVATE_DOC_TESTS,
- hir::CRATE_HIR_ID,
+ hir_id,
span_of_attrs(&item.attrs),
"Documentation test in private item");
diag.emit();
eh_personality,
eh_unwind_resume,
enable,
+ err,
Err,
except,
exclusive_range_pattern,
fundamental,
future,
Future,
+ gen_future,
generators,
generic_associated_types,
generic_param_attrs,
never,
never_type,
next,
+ __next,
nll,
no_builtins,
no_core,
Pending,
pin,
Pin,
+ pinned,
platform_intrinsics,
plugin,
plugin_registrar,
trivial_bounds,
Try,
try_blocks,
+ try_trait,
tuple_indexing,
ty,
type_alias_enum_variants,
uniform_paths,
universal_impl_trait,
unmarked_api,
+ unreachable_code,
unrestricted_attribute_tokens,
unsafe_destructor_blind_to_params,
unsafe_no_drop_flag,
use_nested_groups,
usize,
v1,
+ val,
vis,
visible_private_types,
volatile,
use term;
// FIXME(#54291): rustc and/or LLVM don't yet support building with panic-unwind
-// on aarch64-pc-windows-msvc, so we don't link libtest against
-// libunwind (for the time being), even though it means that
-// libtest won't be fully functional on this platform.
+// on aarch64-pc-windows-msvc, or thumbv7a-pc-windows-msvc
+// so we don't link libtest against libunwind (for the time being)
+// even though it means that libtest won't be fully functional on
+// these platforms.
//
// See also: https://github.com/rust-lang/rust/issues/54190#issuecomment-422904437
-#[cfg(not(all(windows, target_arch = "aarch64")))]
+#[cfg(not(all(windows, any(target_arch = "aarch64", target_arch = "arm"))))]
extern crate panic_unwind;
pub use self::ColorConfig::*;
// bb0: {
// ...
// _5 = const true;
-// assert(move _5, "index out of bounds: the len is move _4 but the index is _3") -> bb1;
+// assert(const true, "index out of bounds: the len is move _4 but the index is _3") -> bb1;
// }
// bb1: {
// _1 = _2[_3];
// bb0: {
// ...
// _2 = (const 2u32, const false);
-// assert(!move (_2.1: bool), "attempt to add with overflow") -> bb1;
+// assert(!const false, "attempt to add with overflow") -> bb1;
// }
// END rustc.main.ConstProp.after.mir
--- /dev/null
+#[inline(never)]
+fn foo(_: i32) { }
+
+fn main() {
+ match 1 {
+ 1 => foo(0),
+ _ => foo(-1),
+ }
+}
+
+// END RUST SOURCE
+// START rustc.main.ConstProp.before.mir
+// bb0: {
+// ...
+// _1 = const 1i32;
+// switchInt(_1) -> [1i32: bb1, otherwise: bb2];
+// }
+// END rustc.main.ConstProp.before.mir
+// START rustc.main.ConstProp.after.mir
+// bb0: {
+// ...
+// switchInt(const 1i32) -> [1i32: bb1, otherwise: bb2];
+// }
+// END rustc.main.ConstProp.after.mir
+// START rustc.main.SimplifyBranches-after-const-prop.before.mir
+// bb0: {
+// ...
+// _1 = const 1i32;
+// switchInt(const 1i32) -> [1i32: bb1, otherwise: bb2];
+// }
+// END rustc.main.SimplifyBranches-after-const-prop.before.mir
+// START rustc.main.SimplifyBranches-after-const-prop.after.mir
+// bb0: {
+// ...
+// _1 = const 1i32;
+// goto -> bb1;
+// }
+// END rustc.main.SimplifyBranches-after-const-prop.after.mir
}
// END RUST SOURCE
-// START rustc.main.SimplifyBranches-after-copy-prop.before.mir
+// START rustc.main.SimplifyBranches-after-const-prop.before.mir
// bb0: {
// ...
// switchInt(const false) -> [false: bb3, otherwise: bb1];
// }
-// END rustc.main.SimplifyBranches-after-copy-prop.before.mir
-// START rustc.main.SimplifyBranches-after-copy-prop.after.mir
+// END rustc.main.SimplifyBranches-after-const-prop.before.mir
+// START rustc.main.SimplifyBranches-after-const-prop.after.mir
// bb0: {
// ...
// goto -> bb3;
// }
-// END rustc.main.SimplifyBranches-after-copy-prop.after.mir
+// END rustc.main.SimplifyBranches-after-const-prop.after.mir
--- /dev/null
+// run-pass
+#![allow(dead_code)]
+
+// Tests that unions aren't subject to unsafe non-zero/niche-filling optimizations.
+//
+// For example, if a union `U` can contain both a `&T` and a `*const T`, there's definitely no
+// bit-value that an `Option<U>` could reuse as `None`; this test makes sure that isn't done.
+//
+// Secondly, this tests the status quo (not a guarantee; subject to change!) to not apply such
+// optimizations to types containing unions even if they're theoretically possible. (discussion:
+// https://github.com/rust-lang/rust/issues/36394)
+//
+// Notably this nails down part of the behavior that `MaybeUninit` assumes: that a
+// `Option<MaybeUninit<&u8>>` does not take advantage of non-zero optimization, and thus is a safe
+// construct.
+
+use std::mem::{size_of, transmute};
+
+union U1<A: Copy> {
+ a: A,
+}
+
+union U2<A: Copy, B: Copy> {
+ a: A,
+ b: B,
+}
+
+// Option<E> uses a value other than 0 and 1 as None
+#[derive(Clone,Copy)]
+enum E {
+ A = 0,
+ B = 1,
+}
+
+fn main() {
+ // Unions do not participate in niche-filling/non-zero optimization...
+ assert!(size_of::<Option<U2<&u8, u8>>>() > size_of::<U2<&u8, u8>>());
+ assert!(size_of::<Option<U2<&u8, ()>>>() > size_of::<U2<&u8, ()>>());
+ assert!(size_of::<Option<U2<u8, E>>>() > size_of::<U2<u8, E>>());
+
+ // ...even when theoretically possible:
+ assert!(size_of::<Option<U1<&u8>>>() > size_of::<U1<&u8>>());
+ assert!(size_of::<Option<U2<&u8, &u8>>>() > size_of::<U2<&u8, &u8>>());
+
+ // The unused bits of the () variant can have any value.
+ let zeroed: U2<&u8, ()> = unsafe { transmute(std::ptr::null::<u8>()) };
+
+ if let None = Some(zeroed) {
+ panic!()
+ }
+}
-//~ ERROR Missing code example in this documentation
-
-#![deny(missing_doc_code_examples)]
+#![deny(missing_doc_code_examples)] //~ ERROR Missing code example in this documentation
/// Some docs.
//~^ ERROR Missing code example in this documentation
error: Missing code example in this documentation
+ --> $DIR/doc-without-codeblock.rs:1:1
+ |
+LL | / #![deny(missing_doc_code_examples)]
+LL | |
+LL | | /// Some docs.
+LL | |
+... |
+LL | | pub fn bar() {}
+LL | | }
+ | |_^
|
note: lint level defined here
- --> $DIR/doc-without-codeblock.rs:3:9
+ --> $DIR/doc-without-codeblock.rs:1:9
|
LL | #![deny(missing_doc_code_examples)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: Missing code example in this documentation
- --> $DIR/doc-without-codeblock.rs:5:1
+ --> $DIR/doc-without-codeblock.rs:3:1
|
LL | /// Some docs.
| ^^^^^^^^^^^^^^
error: Missing code example in this documentation
- --> $DIR/doc-without-codeblock.rs:9:1
+ --> $DIR/doc-without-codeblock.rs:7:1
|
LL | /// And then, the princess died.
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: Missing code example in this documentation
- --> $DIR/doc-without-codeblock.rs:12:5
+ --> $DIR/doc-without-codeblock.rs:10:5
|
LL | /// Or maybe not because she saved herself!
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
--- /dev/null
+#![deny(missing_docs)]
+#![deny(missing_doc_code_examples)]
+
+//! crate level doc
+//! ```
+//! println!("hello"):
+//! ```
+
+
+/// doc
+///
+/// ```
+/// println!("hello");
+/// ```
+fn test() {
+}
+
+#[allow(missing_docs)]
+mod module1 { //~ ERROR
+}
+
+#[allow(missing_doc_code_examples)]
+/// doc
+mod module2 {
+
+ /// doc
+ pub fn test() {}
+}
+
+/// doc
+///
+/// ```
+/// println!("hello");
+/// ```
+pub mod module3 {
+
+ /// doc
+ //~^ ERROR
+ pub fn test() {}
+}
--- /dev/null
+error: Missing code example in this documentation
+ --> $DIR/lint-missing-doc-code-example.rs:19:1
+ |
+LL | / mod module1 {
+LL | | }
+ | |_^
+ |
+note: lint level defined here
+ --> $DIR/lint-missing-doc-code-example.rs:2:9
+ |
+LL | #![deny(missing_doc_code_examples)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: Missing code example in this documentation
+ --> $DIR/lint-missing-doc-code-example.rs:37:3
+ |
+LL | /// doc
+ | ^^^^^^^
+
+error: aborting due to 2 previous errors
+
Four(D)
}
+pub union Union1<A: Copy> {
+ a: A,
+}
+
+pub union Union2<A: Copy, B: Copy> {
+ a: A,
+ b: B,
+}
+
#[start]
fn start(_: isize, _: *const *const u8) -> isize {
let _x: MyOption<NonZeroU32> = Default::default();
let _e: Enum4<(), char, (), ()> = Enum4::One(());
let _f: Enum4<(), (), bool, ()> = Enum4::One(());
let _g: Enum4<(), (), (), MyOption<u8>> = Enum4::One(());
+
+ // Unions do not currently participate in niche filling.
+ let _h: MyOption<Union2<NonZeroU32, u32>> = Default::default();
+
+ // ...even when theoretically possible.
+ let _i: MyOption<Union1<NonZeroU32>> = Default::default();
+ let _j: MyOption<Union2<NonZeroU32, NonZeroU32>> = Default::default();
+
0
}
print-type-size field `.pre`: 1 bytes
print-type-size variant `None`: 0 bytes
print-type-size end padding: 1 bytes
+print-type-size type: `MyOption<Union1<std::num::NonZeroU32>>`: 8 bytes, alignment: 4 bytes
+print-type-size discriminant: 4 bytes
+print-type-size variant `Some`: 4 bytes
+print-type-size field `.0`: 4 bytes
+print-type-size variant `None`: 0 bytes
+print-type-size type: `MyOption<Union2<std::num::NonZeroU32, std::num::NonZeroU32>>`: 8 bytes, alignment: 4 bytes
+print-type-size discriminant: 4 bytes
+print-type-size variant `Some`: 4 bytes
+print-type-size field `.0`: 4 bytes
+print-type-size variant `None`: 0 bytes
+print-type-size type: `MyOption<Union2<std::num::NonZeroU32, u32>>`: 8 bytes, alignment: 4 bytes
+print-type-size discriminant: 4 bytes
+print-type-size variant `Some`: 4 bytes
+print-type-size field `.0`: 4 bytes
+print-type-size variant `None`: 0 bytes
print-type-size type: `NestedNonZero`: 8 bytes, alignment: 4 bytes
print-type-size field `.val`: 4 bytes
print-type-size field `.post`: 2 bytes
print-type-size variant `Some`: 4 bytes
print-type-size field `.0`: 4 bytes
print-type-size variant `None`: 0 bytes
+print-type-size type: `Union1<std::num::NonZeroU32>`: 4 bytes, alignment: 4 bytes
+print-type-size variant `Union1`: 4 bytes
+print-type-size field `.a`: 4 bytes
+print-type-size type: `Union2<std::num::NonZeroU32, std::num::NonZeroU32>`: 4 bytes, alignment: 4 bytes
+print-type-size variant `Union2`: 4 bytes
+print-type-size field `.a`: 4 bytes
+print-type-size field `.b`: 4 bytes, offset: 0 bytes, alignment: 4 bytes
+print-type-size type: `Union2<std::num::NonZeroU32, u32>`: 4 bytes, alignment: 4 bytes
+print-type-size variant `Union2`: 4 bytes
+print-type-size field `.a`: 4 bytes
+print-type-size field `.b`: 4 bytes, offset: 0 bytes, alignment: 4 bytes
print-type-size type: `std::num::NonZeroU32`: 4 bytes, alignment: 4 bytes
print-type-size field `.0`: 4 bytes
print-type-size type: `Enum4<(), (), (), MyOption<u8>>`: 2 bytes, alignment: 1 bytes