diff --git a/src/doc/embedded-book b/src/doc/embedded-book index b2e1092bf67bd..b81ffb7a6f4c5 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit b2e1092bf67bd4d7686c4553f186edbb7f5f92db +Subproject commit b81ffb7a6f4c5aaed92786e770e99db116aa4ebd diff --git a/src/doc/nomicon b/src/doc/nomicon index 3e6e1001dc6e0..9f797e65e6bcc 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 3e6e1001dc6e095dbd5c88005e80969f60e384e1 +Subproject commit 9f797e65e6bcc79419975b17aff8e21c9adc039f diff --git a/src/doc/reference b/src/doc/reference index 64239df6d1735..559e09caa9661 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 64239df6d173562b9deb4f012e4c3e6e960c4754 +Subproject commit 559e09caa9661043744cf7af7bd88432d966f743 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 32facd5522ddb..db57f899ea2a5 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 32facd5522ddbbf37baf01e4e4b6562bc55c071a +Subproject commit db57f899ea2a56a544c8d280cbf033438666273d diff --git a/src/doc/unstable-book/src/language-features/const-in-array-repeat-expressions.md b/src/doc/unstable-book/src/language-features/const-in-array-repeat-expressions.md index 09d1b19b4c3c3..940916944bdaa 100644 --- a/src/doc/unstable-book/src/language-features/const-in-array-repeat-expressions.md +++ b/src/doc/unstable-book/src/language-features/const-in-array-repeat-expressions.md @@ -2,7 +2,7 @@ The tracking issue for this feature is: [#49147] -[#44109]: https://github.com/rust-lang/rust/issues/49147 +[#49147]: https://github.com/rust-lang/rust/issues/49147 ------------------------ diff --git a/src/doc/unstable-book/src/language-features/impl-trait-in-bindings.md b/src/doc/unstable-book/src/language-features/impl-trait-in-bindings.md index 896465cf64978..5c6aa912c1b24 100644 --- a/src/doc/unstable-book/src/language-features/impl-trait-in-bindings.md +++ b/src/doc/unstable-book/src/language-features/impl-trait-in-bindings.md @@ -1,8 +1,8 @@ # `impl_trait_in_bindings` -The tracking issue for this feature is: [#34511] +The tracking issue for this feature is: [#63065] -[#34511]: https://github.com/rust-lang/rust/issues/34511 +[#63065]: https://github.com/rust-lang/rust/issues/63065 ------------------------ diff --git a/src/doc/unstable-book/src/language-features/link-cfg.md b/src/doc/unstable-book/src/language-features/link-cfg.md new file mode 100644 index 0000000000000..ee0fd5bf8698c --- /dev/null +++ b/src/doc/unstable-book/src/language-features/link-cfg.md @@ -0,0 +1,5 @@ +# `link_cfg` + +This feature is internal to the Rust compiler and is not intended for general use. + +------------------------ diff --git a/src/doc/unstable-book/src/language-features/trait-alias.md b/src/doc/unstable-book/src/language-features/trait-alias.md index 4f2db040160c3..f1be053ddc42e 100644 --- a/src/doc/unstable-book/src/language-features/trait-alias.md +++ b/src/doc/unstable-book/src/language-features/trait-alias.md @@ -2,7 +2,7 @@ The tracking issue for this feature is: [#41517] -[#41417]: https://github.com/rust-lang/rust/issues/41517 +[#41517]: https://github.com/rust-lang/rust/issues/41517 ------------------------ diff --git a/src/doc/unstable-book/src/language-features/transparent-unions.md b/src/doc/unstable-book/src/language-features/transparent-unions.md index b731c9ea6d012..9b39b8971644f 100644 --- a/src/doc/unstable-book/src/language-features/transparent-unions.md +++ b/src/doc/unstable-book/src/language-features/transparent-unions.md @@ -2,7 +2,7 @@ The tracking issue for this feature is [#60405] -[60405]: https://github.com/rust-lang/rust/issues/60405 +[#60405]: https://github.com/rust-lang/rust/issues/60405 ---- diff --git a/src/doc/unstable-book/src/library-features/read-initializer.md b/src/doc/unstable-book/src/library-features/read-initializer.md deleted file mode 100644 index 898fe58eeee53..0000000000000 --- a/src/doc/unstable-book/src/library-features/read-initializer.md +++ /dev/null @@ -1,7 +0,0 @@ -# `read_initializer` - -The tracking issue for this feature is: [#42788] - -[#0]: https://github.com/rust-lang/rust/issues/42788 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/tidy-test-never-used-anywhere-else.md b/src/doc/unstable-book/src/library-features/tidy-test-never-used-anywhere-else.md new file mode 100644 index 0000000000000..c194d79a19d3e --- /dev/null +++ b/src/doc/unstable-book/src/library-features/tidy-test-never-used-anywhere-else.md @@ -0,0 +1,5 @@ +# `tidy_test_never_used_anywhere_else` + +This feature is internal to the Rust compiler and is not intended for general use. + +------------------------ diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index 8b9ffdfb49b46..9da324ba2d4f1 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -1477,6 +1477,14 @@ impl Drop for IntoIter { // Continue the same loop we perform below. This only runs when unwinding, so we // don't have to care about panics this time (they'll abort). while let Some(_) = self.0.next() {} + + // No need to avoid the shared root, because the tree was definitely not empty. + unsafe { + let mut node = ptr::read(&self.0.front).into_node().forget_type(); + while let Some(parent) = node.deallocate_and_ascend() { + node = parent.into_node().forget_type(); + } + } } } @@ -1491,7 +1499,8 @@ impl Drop for IntoIter { if node.is_shared_root() { return; } - + // Most of the nodes have been deallocated while traversing + // but one pile from a leaf up to the root is left standing. while let Some(parent) = node.deallocate_and_ascend() { node = parent.into_node().forget_type(); } diff --git a/src/liballoc/tests/btree/map.rs b/src/liballoc/tests/btree/map.rs index fd07a4d3926c3..d05eec19346de 100644 --- a/src/liballoc/tests/btree/map.rs +++ b/src/liballoc/tests/btree/map.rs @@ -1021,7 +1021,7 @@ fn test_split_off_large_random_sorted() { } #[test] -fn test_into_iter_drop_leak() { +fn test_into_iter_drop_leak_1() { static DROPS: AtomicU32 = AtomicU32::new(0); struct D; @@ -1045,3 +1045,27 @@ fn test_into_iter_drop_leak() { assert_eq!(DROPS.load(Ordering::SeqCst), 5); } + +#[test] +fn test_into_iter_drop_leak_2() { + let size = 12; // to obtain tree with 2 levels (having edges to leaf nodes) + static DROPS: AtomicU32 = AtomicU32::new(0); + static PANIC_POINT: AtomicU32 = AtomicU32::new(0); + + struct D; + impl Drop for D { + fn drop(&mut self) { + if DROPS.fetch_add(1, Ordering::SeqCst) == PANIC_POINT.load(Ordering::SeqCst) { + panic!("panic in `drop`"); + } + } + } + + for panic_point in vec![0, 1, size - 2, size - 1] { + DROPS.store(0, Ordering::SeqCst); + PANIC_POINT.store(panic_point, Ordering::SeqCst); + let map: BTreeMap<_, _> = (0..size).map(|i| (i, D)).collect(); + catch_unwind(move || drop(map.into_iter())).ok(); + assert_eq!(DROPS.load(Ordering::SeqCst), size); + } +} diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index 1cfe5bcbc0884..87a912bd89efb 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -99,6 +99,9 @@ declare_features! ( // no-tracking-issue-start + /// Allows using `rustc_*` attributes (RFC 572). + (active, rustc_attrs, "1.0.0", None, None), + /// Allows using compiler's own crates. (active, rustc_private, "1.0.0", Some(27812), None), @@ -128,9 +131,6 @@ declare_features! ( /// Allows using `#[link_name="llvm.*"]`. (active, link_llvm_intrinsics, "1.0.0", Some(29602), None), - /// Allows using `rustc_*` attributes (RFC 572). - (active, rustc_attrs, "1.0.0", Some(29642), None), - /// Allows using the `box $expr` syntax. (active, box_syntax, "1.0.0", Some(49733), None), diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 4f99bfe8a852a..84717cbeaa9c4 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -306,23 +306,127 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M Ok(()) } - fn visit_primitive(&mut self, value: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> { + /// Check a reference or `Box`. + fn check_safe_pointer( + &mut self, + value: OpTy<'tcx, M::PointerTag>, + kind: &str, + ) -> InterpResult<'tcx> { let value = self.ecx.read_immediate(value)?; + // Handle wide pointers. + // Check metadata early, for better diagnostics + let place = try_validation!(self.ecx.ref_to_mplace(value), "undefined pointer", self.path); + if place.layout.is_unsized() { + self.check_wide_ptr_meta(place.meta, place.layout)?; + } + // Make sure this is dereferenceable and all. + let (size, align) = self + .ecx + .size_and_align_of(place.meta, place.layout)? + // for the purpose of validity, consider foreign types to have + // alignment and size determined by the layout (size will be 0, + // alignment should take attributes into account). + .unwrap_or_else(|| (place.layout.size, place.layout.align.abi)); + let ptr: Option<_> = match self.ecx.memory.check_ptr_access_align( + place.ptr, + size, + Some(align), + CheckInAllocMsg::InboundsTest, + ) { + Ok(ptr) => ptr, + Err(err) => { + info!( + "{:?} did not pass access check for size {:?}, align {:?}", + place.ptr, size, align + ); + match err.kind { + err_unsup!(InvalidNullPointerUsage) => { + throw_validation_failure!(format_args!("a NULL {}", kind), self.path) + } + err_unsup!(AlignmentCheckFailed { required, has }) => { + throw_validation_failure!( + format_args!( + "an unaligned {} \ + (required {} byte alignment but found {})", + kind, + required.bytes(), + has.bytes() + ), + self.path + ) + } + err_unsup!(ReadBytesAsPointer) => throw_validation_failure!( + format_args!("a dangling {} (created from integer)", kind), + self.path + ), + _ => throw_validation_failure!( + format_args!("a dangling {} (not entirely in bounds)", kind), + self.path + ), + } + } + }; + // Recursive checking + if let Some(ref mut ref_tracking) = self.ref_tracking_for_consts { + if let Some(ptr) = ptr { + // not a ZST + // Skip validation entirely for some external statics + let alloc_kind = self.ecx.tcx.alloc_map.lock().get(ptr.alloc_id); + if let Some(GlobalAlloc::Static(did)) = alloc_kind { + // `extern static` cannot be validated as they have no body. + // FIXME: Statics from other crates are also skipped. + // They might be checked at a different type, but for now we + // want to avoid recursing too deeply. This is not sound! + if !did.is_local() || self.ecx.tcx.is_foreign_item(did) { + return Ok(()); + } + } + } + // Proceed recursively even for ZST, no reason to skip them! + // `!` is a ZST and we want to validate it. + // Normalize before handing `place` to tracking because that will + // check for duplicates. + let place = if size.bytes() > 0 { + self.ecx.force_mplace_ptr(place).expect("we already bounds-checked") + } else { + place + }; + let path = &self.path; + ref_tracking.track(place, || { + // We need to clone the path anyway, make sure it gets created + // with enough space for the additional `Deref`. + let mut new_path = Vec::with_capacity(path.len() + 1); + new_path.clone_from(path); + new_path.push(PathElem::Deref); + new_path + }); + } + Ok(()) + } + + /// Check if this is a value of primitive type, and if yes check the validity of the value + /// at that type. Return `true` if the type is indeed primitive. + fn try_visit_primitive( + &mut self, + value: OpTy<'tcx, M::PointerTag>, + ) -> InterpResult<'tcx, bool> { // Go over all the primitive types let ty = value.layout.ty; match ty.kind { ty::Bool => { - let value = value.to_scalar_or_undef(); + let value = self.ecx.read_scalar(value)?; try_validation!(value.to_bool(), value, self.path, "a boolean"); + Ok(true) } ty::Char => { - let value = value.to_scalar_or_undef(); + let value = self.ecx.read_scalar(value)?; try_validation!(value.to_char(), value, self.path, "a valid unicode codepoint"); + Ok(true) } ty::Float(_) | ty::Int(_) | ty::Uint(_) => { + let value = self.ecx.read_scalar(value)?; // NOTE: Keep this in sync with the array optimization for int/float // types below! - let value = value.to_scalar_or_undef(); if self.ref_tracking_for_consts.is_some() { // Integers/floats in CTFE: Must be scalar bits, pointers are dangerous let is_bits = value.not_undef().map_or(false, |v| v.is_bits()); @@ -337,108 +441,31 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M // At run-time, for now, we accept *anything* for these types, including // undef. We should fix that, but let's start low. } + Ok(true) } ty::RawPtr(..) => { // We are conservative with undef for integers, but try to // actually enforce our current rules for raw pointers. - let place = - try_validation!(self.ecx.ref_to_mplace(value), "undefined pointer", self.path); + let place = try_validation!( + self.ecx.ref_to_mplace(self.ecx.read_immediate(value)?), + "undefined pointer", + self.path + ); if place.layout.is_unsized() { self.check_wide_ptr_meta(place.meta, place.layout)?; } + Ok(true) } - _ if ty.is_box() || ty.is_region_ptr() => { - // Handle wide pointers. - // Check metadata early, for better diagnostics - let place = - try_validation!(self.ecx.ref_to_mplace(value), "undefined pointer", self.path); - if place.layout.is_unsized() { - self.check_wide_ptr_meta(place.meta, place.layout)?; - } - // Make sure this is dereferenceable and all. - let (size, align) = self - .ecx - .size_and_align_of(place.meta, place.layout)? - // for the purpose of validity, consider foreign types to have - // alignment and size determined by the layout (size will be 0, - // alignment should take attributes into account). - .unwrap_or_else(|| (place.layout.size, place.layout.align.abi)); - let ptr: Option<_> = match self.ecx.memory.check_ptr_access_align( - place.ptr, - size, - Some(align), - CheckInAllocMsg::InboundsTest, - ) { - Ok(ptr) => ptr, - Err(err) => { - info!( - "{:?} did not pass access check for size {:?}, align {:?}", - place.ptr, size, align - ); - match err.kind { - err_unsup!(InvalidNullPointerUsage) => { - throw_validation_failure!("a NULL reference", self.path) - } - err_unsup!(AlignmentCheckFailed { required, has }) => { - throw_validation_failure!( - format_args!( - "an unaligned reference \ - (required {} byte alignment but found {})", - required.bytes(), - has.bytes() - ), - self.path - ) - } - err_unsup!(ReadBytesAsPointer) => throw_validation_failure!( - "a dangling reference (created from integer)", - self.path - ), - _ => throw_validation_failure!( - "a dangling reference (not entirely in bounds)", - self.path - ), - } - } - }; - // Recursive checking - if let Some(ref mut ref_tracking) = self.ref_tracking_for_consts { - if let Some(ptr) = ptr { - // not a ZST - // Skip validation entirely for some external statics - let alloc_kind = self.ecx.tcx.alloc_map.lock().get(ptr.alloc_id); - if let Some(GlobalAlloc::Static(did)) = alloc_kind { - // `extern static` cannot be validated as they have no body. - // FIXME: Statics from other crates are also skipped. - // They might be checked at a different type, but for now we - // want to avoid recursing too deeply. This is not sound! - if !did.is_local() || self.ecx.tcx.is_foreign_item(did) { - return Ok(()); - } - } - } - // Proceed recursively even for ZST, no reason to skip them! - // `!` is a ZST and we want to validate it. - // Normalize before handing `place` to tracking because that will - // check for duplicates. - let place = if size.bytes() > 0 { - self.ecx.force_mplace_ptr(place).expect("we already bounds-checked") - } else { - place - }; - let path = &self.path; - ref_tracking.track(place, || { - // We need to clone the path anyway, make sure it gets created - // with enough space for the additional `Deref`. - let mut new_path = Vec::with_capacity(path.len() + 1); - new_path.clone_from(path); - new_path.push(PathElem::Deref); - new_path - }); - } + ty::Ref(..) => { + self.check_safe_pointer(value, "reference")?; + Ok(true) + } + ty::Adt(def, ..) if def.is_box() => { + self.check_safe_pointer(value, "box")?; + Ok(true) } ty::FnPtr(_sig) => { - let value = value.to_scalar_or_undef(); + let value = self.ecx.read_scalar(value)?; let _fn = try_validation!( value.not_undef().and_then(|ptr| self.ecx.memory.get_fn(ptr)), value, @@ -446,11 +473,36 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M "a function pointer" ); // FIXME: Check if the signature matches + Ok(true) } - // This should be all the (inhabited) primitive types - _ => bug!("Unexpected primitive type {}", value.layout.ty), + ty::Never => throw_validation_failure!("a value of the never type `!`", self.path), + ty::Foreign(..) | ty::FnDef(..) => { + // Nothing to check. + Ok(true) + } + // The above should be all the (inhabited) primitive types. The rest is compound, we + // check them by visiting their fields/variants. + // (`Str` UTF-8 check happens in `visit_aggregate`, too.) + ty::Adt(..) + | ty::Tuple(..) + | ty::Array(..) + | ty::Slice(..) + | ty::Str + | ty::Dynamic(..) + | ty::Closure(..) + | ty::Generator(..) => Ok(false), + // Some types only occur during typechecking, they have no layout. + // We should not see them here and we could not check them anyway. + ty::Error + | ty::Infer(..) + | ty::Placeholder(..) + | ty::Bound(..) + | ty::Param(..) + | ty::Opaque(..) + | ty::UnnormalizedProjection(..) + | ty::Projection(..) + | ty::GeneratorWitness(..) => bug!("Encountered invalid type {:?}", ty), } - Ok(()) } fn visit_scalar( @@ -558,11 +610,10 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> } #[inline(always)] - fn visit_union(&mut self, _v: Self::V, fields: usize) -> InterpResult<'tcx> { - // Empty unions are not accepted by rustc. That's great, it means we can - // use that as a signal for detecting primitives. Make sure - // we did not miss any primitive. - assert!(fields > 0); + fn visit_union(&mut self, op: OpTy<'tcx, M::PointerTag>, fields: usize) -> InterpResult<'tcx> { + // Empty unions are not accepted by rustc. But uninhabited enums + // claim to be unions, so allow them, too. + assert!(op.layout.abi.is_uninhabited() || fields > 0); Ok(()) } @@ -570,29 +621,12 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> fn visit_value(&mut self, op: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> { trace!("visit_value: {:?}, {:?}", *op, op.layout); - if op.layout.abi.is_uninhabited() { - // Uninhabited types do not have sensible layout, stop right here. - throw_validation_failure!( - format_args!("a value of uninhabited type {:?}", op.layout.ty), - self.path - ) - } - - // Check primitive types. We do this after checking for uninhabited types, - // to exclude fieldless enums (that also appear as fieldless unions here). - // Primitives can have varying layout, so we check them separately and before aggregate - // handling. - // It is CRITICAL that we get this check right, or we might be validating the wrong thing! - let primitive = match op.layout.fields { - // Primitives appear as Union with 0 fields - except for Boxes and fat pointers. - // (Fieldless enums also appear here, but they are uninhabited and thus handled above.) - layout::FieldPlacement::Union(0) => true, - _ => op.layout.ty.builtin_deref(true).is_some(), - }; - if primitive { - // No need to recurse further or check scalar layout, this is a leaf type. - return self.visit_primitive(op); + // Check primitive types -- the leafs of our recursive descend. + if self.try_visit_primitive(op)? { + return Ok(()); } + // Sanity check: `builtin_deref` does not know any pointers that are not primitive. + assert!(op.layout.ty.builtin_deref(true).is_none()); // Recursively walk the type. Translate some possible errors to something nicer. match self.walk_value(op) { @@ -619,7 +653,12 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> // scalars, we do the same check on every "level" (e.g., first we check // MyNewtype and then the scalar in there). match op.layout.abi { - layout::Abi::Uninhabited => unreachable!(), // checked above + layout::Abi::Uninhabited => { + throw_validation_failure!( + format_args!("a value of uninhabited type {:?}", op.layout.ty), + self.path + ); + } layout::Abi::Scalar(ref scalar_layout) => { self.visit_scalar(op, scalar_layout)?; } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 43cfe05ac230e..ec5a8c4a0b896 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -6,8 +6,7 @@ //! Imports are also considered items and placed into modules here, but not resolved yet. use crate::def_collector::collect_definitions; -use crate::imports::ImportDirective; -use crate::imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport}; +use crate::imports::{Import, ImportKind}; use crate::macros::{LegacyBinding, LegacyScope}; use crate::Namespace::{self, MacroNS, TypeNS, ValueNS}; use crate::{CrateLint, Determinacy, PathResult, ResolutionError, VisResolutionError}; @@ -308,11 +307,11 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { }) } - // Add an import directive to the current module. - fn add_import_directive( + // Add an import to the current module. + fn add_import( &mut self, module_path: Vec, - subclass: ImportDirectiveSubclass<'a>, + kind: ImportKind<'a>, span: Span, id: NodeId, item: &ast::Item, @@ -321,11 +320,11 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { vis: ty::Visibility, ) { let current_module = self.parent_scope.module; - let directive = self.r.arenas.alloc_import_directive(ImportDirective { + let import = self.r.arenas.alloc_import(Import { + kind, parent_scope: self.parent_scope, module_path, imported_module: Cell::new(None), - subclass, span, id, use_span: item.span, @@ -337,25 +336,25 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { used: Cell::new(false), }); - debug!("add_import_directive({:?})", directive); + debug!("add_import({:?})", import); - self.r.indeterminate_imports.push(directive); - match directive.subclass { + self.r.indeterminate_imports.push(import); + match import.kind { // Don't add unresolved underscore imports to modules - SingleImport { target: Ident { name: kw::Underscore, .. }, .. } => {} - SingleImport { target, type_ns_only, .. } => { + ImportKind::Single { target: Ident { name: kw::Underscore, .. }, .. } => {} + ImportKind::Single { target, type_ns_only, .. } => { self.r.per_ns(|this, ns| { if !type_ns_only || ns == TypeNS { let key = this.new_key(target, ns); let mut resolution = this.resolution(current_module, key).borrow_mut(); - resolution.add_single_import(directive); + resolution.add_single_import(import); } }); } // We don't add prelude imports to the globs since they only affect lexical scopes, // which are not relevant to import resolution. - GlobImport { is_prelude: true, .. } => {} - GlobImport { .. } => current_module.globs.borrow_mut().push(directive), + ImportKind::Glob { is_prelude: true, .. } => {} + ImportKind::Glob { .. } => current_module.globs.borrow_mut().push(import), _ => unreachable!(), } } @@ -480,7 +479,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { ); } - let subclass = SingleImport { + let kind = ImportKind::Single { source: source.ident, target: ident, source_bindings: PerNS { @@ -496,9 +495,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { type_ns_only, nested, }; - self.add_import_directive( + self.add_import( module_path, - subclass, + kind, use_tree.span, id, item, @@ -508,20 +507,11 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { ); } ast::UseTreeKind::Glob => { - let subclass = GlobImport { + let kind = ImportKind::Glob { is_prelude: attr::contains_name(&item.attrs, sym::prelude_import), max_vis: Cell::new(ty::Visibility::Invisible), }; - self.add_import_directive( - prefix, - subclass, - use_tree.span, - id, - item, - root_span, - item.id, - vis, - ); + self.add_import(prefix, kind, use_tree.span, id, item, root_span, item.id, vis); } ast::UseTreeKind::Nested(ref items) => { // Ensure there is at most one `self` in the list @@ -637,15 +627,12 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { let used = self.process_legacy_macro_imports(item, module); let binding = (module, ty::Visibility::Public, sp, expansion).to_name_binding(self.r.arenas); - let directive = self.r.arenas.alloc_import_directive(ImportDirective { + let import = self.r.arenas.alloc_import(Import { + kind: ImportKind::ExternCrate { source: orig_name, target: ident }, root_id: item.id, id: item.id, parent_scope: self.parent_scope, imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))), - subclass: ImportDirectiveSubclass::ExternCrate { - source: orig_name, - target: ident, - }, has_attributes: !item.attrs.is_empty(), use_span_with_attributes: item.span_with_attributes(), use_span: item.span, @@ -655,8 +642,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { vis: Cell::new(vis), used: Cell::new(used), }); - self.r.potentially_unused_imports.push(directive); - let imported_binding = self.r.import(binding, directive); + self.r.potentially_unused_imports.push(import); + let imported_binding = self.r.import(binding, import); if ptr::eq(parent, self.r.graph_root) { if let Some(entry) = self.r.extern_prelude.get(&ident.modern()) { if expansion != ExpnId::root() @@ -992,13 +979,13 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } } - let macro_use_directive = |this: &Self, span| { - this.r.arenas.alloc_import_directive(ImportDirective { + let macro_use_import = |this: &Self, span| { + this.r.arenas.alloc_import(Import { + kind: ImportKind::MacroUse, root_id: item.id, id: item.id, parent_scope: this.parent_scope, imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))), - subclass: ImportDirectiveSubclass::MacroUse, use_span_with_attributes: item.span_with_attributes(), has_attributes: !item.attrs.is_empty(), use_span: item.span, @@ -1012,11 +999,11 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { let allow_shadowing = self.parent_scope.expansion == ExpnId::root(); if let Some(span) = import_all { - let directive = macro_use_directive(self, span); - self.r.potentially_unused_imports.push(directive); + let import = macro_use_import(self, span); + self.r.potentially_unused_imports.push(import); module.for_each_child(self, |this, ident, ns, binding| { if ns == MacroNS { - let imported_binding = this.r.import(binding, directive); + let imported_binding = this.r.import(binding, import); this.legacy_import_macro(ident.name, imported_binding, span, allow_shadowing); } }); @@ -1031,9 +1018,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { ident.span, ); if let Ok(binding) = result { - let directive = macro_use_directive(self, ident.span); - self.r.potentially_unused_imports.push(directive); - let imported_binding = self.r.import(binding, directive); + let import = macro_use_import(self, ident.span); + self.r.potentially_unused_imports.push(import); + let imported_binding = self.r.import(binding, import); self.legacy_import_macro( ident.name, imported_binding, diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index 659a54b169b39..722f843ab6e7e 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -3,7 +3,7 @@ // // Although this is mostly a lint pass, it lives in here because it depends on // resolve data structures and because it finalises the privacy information for -// `use` directives. +// `use` items. // // Unused trait imports can't be checked until the method resolution. We save // candidates here, and do the actual check in librustc_typeck/check_unused.rs. @@ -23,7 +23,7 @@ // - `check_crate` finally emits the diagnostics based on the data generated // in the last step -use crate::imports::ImportDirectiveSubclass; +use crate::imports::ImportKind; use crate::Resolver; use rustc::{lint, ty}; @@ -58,7 +58,7 @@ struct UnusedImportCheckVisitor<'a, 'b> { } impl<'a, 'b> UnusedImportCheckVisitor<'a, 'b> { - // We have information about whether `use` (import) directives are actually + // We have information about whether `use` (import) items are actually // used now. If an import is not used at all, we signal a lint error. fn check_import(&mut self, id: ast::NodeId) { let mut used = false; @@ -223,33 +223,33 @@ fn calc_unused_spans( impl Resolver<'_> { crate fn check_unused(&mut self, krate: &ast::Crate) { - for directive in self.potentially_unused_imports.iter() { - match directive.subclass { - _ if directive.used.get() - || directive.vis.get() == ty::Visibility::Public - || directive.span.is_dummy() => + for import in self.potentially_unused_imports.iter() { + match import.kind { + _ if import.used.get() + || import.vis.get() == ty::Visibility::Public + || import.span.is_dummy() => { - if let ImportDirectiveSubclass::MacroUse = directive.subclass { - if !directive.span.is_dummy() { + if let ImportKind::MacroUse = import.kind { + if !import.span.is_dummy() { self.lint_buffer.buffer_lint( lint::builtin::MACRO_USE_EXTERN_CRATE, - directive.id, - directive.span, - "deprecated `#[macro_use]` directive used to \ + import.id, + import.span, + "deprecated `#[macro_use]` attribute used to \ import macros should be replaced at use sites \ - with a `use` statement to import the macro \ + with a `use` item to import the macro \ instead", ); } } } - ImportDirectiveSubclass::ExternCrate { .. } => { - self.maybe_unused_extern_crates.push((directive.id, directive.span)); + ImportKind::ExternCrate { .. } => { + self.maybe_unused_extern_crates.push((import.id, import.span)); } - ImportDirectiveSubclass::MacroUse => { + ImportKind::MacroUse => { let lint = lint::builtin::UNUSED_IMPORTS; let msg = "unused `#[macro_use]` import"; - self.lint_buffer.buffer_lint(lint, directive.id, directive.span, msg); + self.lint_buffer.buffer_lint(lint, import.id, import.span, msg); } _ => {} } diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 3b747a56499f5..47a05ec90d42f 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -18,7 +18,7 @@ use rustc_span::source_map::SourceMap; use rustc_span::symbol::{kw, Symbol}; use rustc_span::{BytePos, MultiSpan, Span}; -use crate::imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver}; +use crate::imports::{Import, ImportKind, ImportResolver}; use crate::path_names_to_string; use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind}; use crate::{BindingError, CrateLint, HasGenericParams, LegacyScope, Module, ModuleOrUniformRoot}; @@ -1125,7 +1125,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { /// ``` pub(crate) fn check_for_module_export_macro( &mut self, - directive: &'b ImportDirective<'b>, + import: &'b Import<'b>, module: ModuleOrUniformRoot<'b>, ident: Ident, ) -> Option<(Option, Vec)> { @@ -1150,28 +1150,26 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let binding = resolution.borrow().binding()?; if let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() { let module_name = crate_module.kind.name().unwrap(); - let import = match directive.subclass { - ImportDirectiveSubclass::SingleImport { source, target, .. } - if source != target => - { + let import_snippet = match import.kind { + ImportKind::Single { source, target, .. } if source != target => { format!("{} as {}", source, target) } _ => format!("{}", ident), }; let mut corrections: Vec<(Span, String)> = Vec::new(); - if !directive.is_nested() { + if !import.is_nested() { // Assume this is the easy case of `use issue_59764::foo::makro;` and just remove // intermediate segments. - corrections.push((directive.span, format!("{}::{}", module_name, import))); + corrections.push((import.span, format!("{}::{}", module_name, import_snippet))); } else { // Find the binding span (and any trailing commas and spaces). // ie. `use a::b::{c, d, e};` // ^^^ let (found_closing_brace, binding_span) = find_span_of_binding_until_next_binding( self.r.session, - directive.span, - directive.use_span, + import.span, + import.use_span, ); debug!( "check_for_module_export_macro: found_closing_brace={:?} binding_span={:?}", @@ -1208,7 +1206,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let (has_nested, after_crate_name) = find_span_immediately_after_crate_name( self.r.session, module_name, - directive.use_span, + import.use_span, ); debug!( "check_for_module_export_macro: has_nested={:?} after_crate_name={:?}", @@ -1224,11 +1222,11 @@ impl<'a, 'b> ImportResolver<'a, 'b> { start_point, if has_nested { // In this case, `start_snippet` must equal '{'. - format!("{}{}, ", start_snippet, import) + format!("{}{}, ", start_snippet, import_snippet) } else { // In this case, add a `{`, then the moved import, then whatever // was there before. - format!("{{{}, {}", import, start_snippet) + format!("{{{}, {}", import_snippet, start_snippet) }, )); } diff --git a/src/librustc_resolve/imports.rs b/src/librustc_resolve/imports.rs index 5d4df992b949a..485b86636a0ba 100644 --- a/src/librustc_resolve/imports.rs +++ b/src/librustc_resolve/imports.rs @@ -1,7 +1,5 @@ //! A bunch of methods and structures more or less related to resolving imports. -use ImportDirectiveSubclass::*; - use crate::diagnostics::Suggestion; use crate::Determinacy::{self, *}; use crate::Namespace::{self, MacroNS, TypeNS}; @@ -36,10 +34,10 @@ use std::{mem, ptr}; type Res = def::Res; -/// Contains data for specific types of import directives. +/// Contains data for specific kinds of imports. #[derive(Clone, Debug)] -pub enum ImportDirectiveSubclass<'a> { - SingleImport { +pub enum ImportKind<'a> { + Single { /// `source` in `use prefix::source as target`. source: Ident, /// `target` in `use prefix::source as target`. @@ -53,7 +51,7 @@ pub enum ImportDirectiveSubclass<'a> { /// Did this import result from a nested import? ie. `use foo::{bar, baz};` nested: bool, }, - GlobImport { + Glob { is_prelude: bool, max_vis: Cell, // The visibility of the greatest re-export. // n.b. `max_vis` is only used in `finalize_import` to check for re-export errors. @@ -65,19 +63,21 @@ pub enum ImportDirectiveSubclass<'a> { MacroUse, } -/// One import directive. +/// One import. #[derive(Debug, Clone)] -crate struct ImportDirective<'a> { - /// The ID of the `extern crate`, `UseTree` etc that imported this `ImportDirective`. +crate struct Import<'a> { + pub kind: ImportKind<'a>, + + /// The ID of the `extern crate`, `UseTree` etc that imported this `Import`. /// - /// In the case where the `ImportDirective` was expanded from a "nested" use tree, + /// In the case where the `Import` was expanded from a "nested" use tree, /// this id is the ID of the leaf tree. For example: /// /// ```ignore (pacify the mercilous tidy) /// use foo::bar::{a, b} /// ``` /// - /// If this is the import directive for `foo::bar::a`, we would have the ID of the `UseTree` + /// If this is the import for `foo::bar::a`, we would have the ID of the `UseTree` /// for `a` in this field. pub id: NodeId, @@ -107,22 +107,21 @@ crate struct ImportDirective<'a> { pub module_path: Vec, /// The resolution of `module_path`. pub imported_module: Cell>>, - pub subclass: ImportDirectiveSubclass<'a>, pub vis: Cell, pub used: Cell, } -impl<'a> ImportDirective<'a> { +impl<'a> Import<'a> { pub fn is_glob(&self) -> bool { - match self.subclass { - ImportDirectiveSubclass::GlobImport { .. } => true, + match self.kind { + ImportKind::Glob { .. } => true, _ => false, } } pub fn is_nested(&self) -> bool { - match self.subclass { - ImportDirectiveSubclass::SingleImport { nested, .. } => nested, + match self.kind { + ImportKind::Single { nested, .. } => nested, _ => false, } } @@ -136,8 +135,8 @@ impl<'a> ImportDirective<'a> { /// Records information about the resolution of a name in a namespace of a module. pub struct NameResolution<'a> { /// Single imports that may define the name in the namespace. - /// Import directives are arena-allocated, so it's ok to use pointers as keys. - single_imports: FxHashSet>>, + /// Imports are arena-allocated, so it's ok to use pointers as keys. + single_imports: FxHashSet>>, /// The least shadowable known binding for this name, or None if there are no known bindings. pub binding: Option<&'a NameBinding<'a>>, shadowed_glob: Option<&'a NameBinding<'a>>, @@ -155,8 +154,8 @@ impl<'a> NameResolution<'a> { }) } - crate fn add_single_import(&mut self, directive: &'a ImportDirective<'a>) { - self.single_imports.insert(PtrKey(directive)); + crate fn add_single_import(&mut self, import: &'a Import<'a>) { + self.single_imports.insert(PtrKey(import)); } } @@ -348,8 +347,8 @@ impl<'a> Resolver<'a> { single_import.imported_module.get(), return Err((Undetermined, Weak::No)) ); - let ident = match single_import.subclass { - SingleImport { source, .. } => source, + let ident = match single_import.kind { + ImportKind::Single { source, .. } => source, _ => unreachable!(), }; match self.resolve_ident_in_module( @@ -451,34 +450,34 @@ impl<'a> Resolver<'a> { Err((Determined, Weak::No)) } - // Given a binding and an import directive that resolves to it, - // return the corresponding binding defined by the import directive. + // Given a binding and an import that resolves to it, + // return the corresponding binding defined by the import. crate fn import( &self, binding: &'a NameBinding<'a>, - directive: &'a ImportDirective<'a>, + import: &'a Import<'a>, ) -> &'a NameBinding<'a> { - let vis = if binding.pseudo_vis().is_at_least(directive.vis.get(), self) || + let vis = if binding.pseudo_vis().is_at_least(import.vis.get(), self) || // cf. `PUB_USE_OF_PRIVATE_EXTERN_CRATE` - !directive.is_glob() && binding.is_extern_crate() + !import.is_glob() && binding.is_extern_crate() { - directive.vis.get() + import.vis.get() } else { binding.pseudo_vis() }; - if let GlobImport { ref max_vis, .. } = directive.subclass { - if vis == directive.vis.get() || vis.is_at_least(max_vis.get(), self) { + if let ImportKind::Glob { ref max_vis, .. } = import.kind { + if vis == import.vis.get() || vis.is_at_least(max_vis.get(), self) { max_vis.set(vis) } } self.arenas.alloc_name_binding(NameBinding { - kind: NameBindingKind::Import { binding, directive, used: Cell::new(false) }, + kind: NameBindingKind::Import { binding, import, used: Cell::new(false) }, ambiguity: None, - span: directive.span, + span: import.span, vis, - expansion: directive.parent_scope.expansion, + expansion: import.parent_scope.expansion, }) } @@ -577,17 +576,17 @@ impl<'a> Resolver<'a> { }; // Define `binding` in `module`s glob importers. - for directive in module.glob_importers.borrow_mut().iter() { + for import in module.glob_importers.borrow_mut().iter() { let mut ident = key.ident; - let scope = match ident.span.reverse_glob_adjust(module.expansion, directive.span) { + let scope = match ident.span.reverse_glob_adjust(module.expansion, import.span) { Some(Some(def)) => self.macro_def_scope(def), - Some(None) => directive.parent_scope.module, + Some(None) => import.parent_scope.module, None => continue, }; if self.is_accessible_from(binding.vis, scope) { - let imported_binding = self.import(binding, directive); + let imported_binding = self.import(binding, import); let key = BindingKey { ident, ..key }; - let _ = self.try_define(directive.parent_scope.module, key, imported_binding); + let _ = self.try_define(import.parent_scope.module, key, imported_binding); } } @@ -596,13 +595,13 @@ impl<'a> Resolver<'a> { // Define a "dummy" resolution containing a Res::Err as a placeholder for a // failed resolution - fn import_dummy_binding(&mut self, directive: &'a ImportDirective<'a>) { - if let SingleImport { target, .. } = directive.subclass { + fn import_dummy_binding(&mut self, import: &'a Import<'a>) { + if let ImportKind::Single { target, .. } = import.kind { let dummy_binding = self.dummy_binding; - let dummy_binding = self.import(dummy_binding, directive); + let dummy_binding = self.import(dummy_binding, import); self.per_ns(|this, ns| { let key = this.new_key(target, ns); - let _ = this.try_define(directive.parent_scope.module, key, dummy_binding); + let _ = this.try_define(import.parent_scope.module, key, dummy_binding); // Consider erroneous imports used to avoid duplicate diagnostics. this.record_use(target, ns, dummy_binding, false); }); @@ -671,7 +670,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { .chain(indeterminate_imports.into_iter().map(|i| (true, i))) { if let Some(err) = self.finalize_import(import) { - if let SingleImport { source, ref source_bindings, .. } = import.subclass { + if let ImportKind::Single { source, ref source_bindings, .. } = import.kind { if source.name == kw::SelfLower { // Silence `unresolved import` error if E0429 is already emitted if let Err(Determined) = source_bindings.value_ns.get() { @@ -695,7 +694,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { if seen_spans.insert(err.span) { let path = import_path_to_string( &import.module_path.iter().map(|seg| seg.ident).collect::>(), - &import.subclass, + &import.kind, err.span, ); errors.push((path, err)); @@ -706,7 +705,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { self.r.used_imports.insert((import.id, TypeNS)); let path = import_path_to_string( &import.module_path.iter().map(|seg| seg.ident).collect::>(), - &import.subclass, + &import.kind, import.span, ); let err = UnresolvedImportError { @@ -767,28 +766,28 @@ impl<'a, 'b> ImportResolver<'a, 'b> { /// Attempts to resolve the given import, returning true if its resolution is determined. /// If successful, the resolved bindings are written into the module. - fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool { + fn resolve_import(&mut self, import: &'b Import<'b>) -> bool { debug!( "(resolving import for module) resolving import `{}::...` in `{}`", - Segment::names_to_string(&directive.module_path), - module_to_string(directive.parent_scope.module).unwrap_or_else(|| "???".to_string()), + Segment::names_to_string(&import.module_path), + module_to_string(import.parent_scope.module).unwrap_or_else(|| "???".to_string()), ); - let module = if let Some(module) = directive.imported_module.get() { + let module = if let Some(module) = import.imported_module.get() { module } else { // For better failure detection, pretend that the import will // not define any names while resolving its module path. - let orig_vis = directive.vis.replace(ty::Visibility::Invisible); + let orig_vis = import.vis.replace(ty::Visibility::Invisible); let path_res = self.r.resolve_path( - &directive.module_path, + &import.module_path, None, - &directive.parent_scope, + &import.parent_scope, false, - directive.span, - directive.crate_lint(), + import.span, + import.crate_lint(), ); - directive.vis.set(orig_vis); + import.vis.set(orig_vis); match path_res { PathResult::Module(module) => module, @@ -797,23 +796,22 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } }; - directive.imported_module.set(Some(module)); - let (source, target, source_bindings, target_bindings, type_ns_only) = - match directive.subclass { - SingleImport { - source, - target, - ref source_bindings, - ref target_bindings, - type_ns_only, - .. - } => (source, target, source_bindings, target_bindings, type_ns_only), - GlobImport { .. } => { - self.resolve_glob_import(directive); - return true; - } - _ => unreachable!(), - }; + import.imported_module.set(Some(module)); + let (source, target, source_bindings, target_bindings, type_ns_only) = match import.kind { + ImportKind::Single { + source, + target, + ref source_bindings, + ref target_bindings, + type_ns_only, + .. + } => (source, target, source_bindings, target_bindings, type_ns_only), + ImportKind::Glob { .. } => { + self.resolve_glob_import(import); + return true; + } + _ => unreachable!(), + }; let mut indeterminate = false; self.r.per_ns(|this, ns| { @@ -821,23 +819,23 @@ impl<'a, 'b> ImportResolver<'a, 'b> { if let Err(Undetermined) = source_bindings[ns].get() { // For better failure detection, pretend that the import will // not define any names while resolving its module path. - let orig_vis = directive.vis.replace(ty::Visibility::Invisible); + let orig_vis = import.vis.replace(ty::Visibility::Invisible); let binding = this.resolve_ident_in_module( module, source, ns, - &directive.parent_scope, + &import.parent_scope, false, - directive.span, + import.span, ); - directive.vis.set(orig_vis); + import.vis.set(orig_vis); source_bindings[ns].set(binding); } else { return; }; - let parent = directive.parent_scope.module; + let parent = import.parent_scope.module; match source_bindings[ns].get() { Err(Undetermined) => indeterminate = true, // Don't update the resolution, because it was never added. @@ -845,20 +843,20 @@ impl<'a, 'b> ImportResolver<'a, 'b> { Err(Determined) => { let key = this.new_key(target, ns); this.update_resolution(parent, key, |_, resolution| { - resolution.single_imports.remove(&PtrKey(directive)); + resolution.single_imports.remove(&PtrKey(import)); }); } Ok(binding) if !binding.is_importable() => { let msg = format!("`{}` is not directly importable", target); - struct_span_err!(this.session, directive.span, E0253, "{}", &msg) - .span_label(directive.span, "cannot be imported directly") + struct_span_err!(this.session, import.span, E0253, "{}", &msg) + .span_label(import.span, "cannot be imported directly") .emit(); // Do not import this illegal binding. Import a dummy binding and pretend // everything is fine - this.import_dummy_binding(directive); + this.import_dummy_binding(import); } Ok(binding) => { - let imported_binding = this.import(binding, directive); + let imported_binding = this.import(binding, import); target_bindings[ns].set(Some(imported_binding)); this.define(parent, target, ns, imported_binding); } @@ -873,38 +871,35 @@ impl<'a, 'b> ImportResolver<'a, 'b> { /// /// Optionally returns an unresolved import error. This error is buffered and used to /// consolidate multiple unresolved import errors into a single diagnostic. - fn finalize_import( - &mut self, - directive: &'b ImportDirective<'b>, - ) -> Option { - let orig_vis = directive.vis.replace(ty::Visibility::Invisible); + fn finalize_import(&mut self, import: &'b Import<'b>) -> Option { + let orig_vis = import.vis.replace(ty::Visibility::Invisible); let prev_ambiguity_errors_len = self.r.ambiguity_errors.len(); let path_res = self.r.resolve_path( - &directive.module_path, + &import.module_path, None, - &directive.parent_scope, + &import.parent_scope, true, - directive.span, - directive.crate_lint(), + import.span, + import.crate_lint(), ); let no_ambiguity = self.r.ambiguity_errors.len() == prev_ambiguity_errors_len; - directive.vis.set(orig_vis); + import.vis.set(orig_vis); if let PathResult::Failed { .. } | PathResult::NonModule(..) = path_res { // Consider erroneous imports used to avoid duplicate diagnostics. - self.r.used_imports.insert((directive.id, TypeNS)); + self.r.used_imports.insert((import.id, TypeNS)); } let module = match path_res { PathResult::Module(module) => { // Consistency checks, analogous to `finalize_macro_resolutions`. - if let Some(initial_module) = directive.imported_module.get() { + if let Some(initial_module) = import.imported_module.get() { if !ModuleOrUniformRoot::same_def(module, initial_module) && no_ambiguity { - span_bug!(directive.span, "inconsistent resolution for an import"); + span_bug!(import.span, "inconsistent resolution for an import"); } } else { if self.r.privacy_errors.is_empty() { let msg = "cannot determine resolution for the import"; let msg_note = "import resolution is stuck, try simplifying other imports"; - self.r.session.struct_span_err(directive.span, msg).note(msg_note).emit(); + self.r.session.struct_span_err(import.span, msg).note(msg_note).emit(); } } @@ -912,7 +907,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } PathResult::Failed { is_error_from_last_segment: false, span, label, suggestion } => { if no_ambiguity { - assert!(directive.imported_module.get().is_none()); + assert!(import.imported_module.get().is_none()); self.r .report_error(span, ResolutionError::FailedToResolve { label, suggestion }); } @@ -920,11 +915,11 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } PathResult::Failed { is_error_from_last_segment: true, span, label, suggestion } => { if no_ambiguity { - assert!(directive.imported_module.get().is_none()); + assert!(import.imported_module.get().is_none()); let err = match self.make_path_suggestion( span, - directive.module_path.clone(), - &directive.parent_scope, + import.module_path.clone(), + &import.parent_scope, ) { Some((suggestion, note)) => UnresolvedImportError { span, @@ -949,7 +944,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } PathResult::NonModule(path_res) if path_res.base_res() == Res::Err => { if no_ambiguity { - assert!(directive.imported_module.get().is_none()); + assert!(import.imported_module.get().is_none()); } // The error was already reported earlier. return None; @@ -957,10 +952,8 @@ impl<'a, 'b> ImportResolver<'a, 'b> { PathResult::Indeterminate | PathResult::NonModule(..) => unreachable!(), }; - let (ident, target, source_bindings, target_bindings, type_ns_only) = match directive - .subclass - { - SingleImport { + let (ident, target, source_bindings, target_bindings, type_ns_only) = match import.kind { + ImportKind::Single { source, target, ref source_bindings, @@ -968,25 +961,25 @@ impl<'a, 'b> ImportResolver<'a, 'b> { type_ns_only, .. } => (source, target, source_bindings, target_bindings, type_ns_only), - GlobImport { is_prelude, ref max_vis } => { - if directive.module_path.len() <= 1 { + ImportKind::Glob { is_prelude, ref max_vis } => { + if import.module_path.len() <= 1 { // HACK(eddyb) `lint_if_path_starts_with_module` needs at least // 2 segments, so the `resolve_path` above won't trigger it. - let mut full_path = directive.module_path.clone(); + let mut full_path = import.module_path.clone(); full_path.push(Segment::from_ident(Ident::invalid())); self.r.lint_if_path_starts_with_module( - directive.crate_lint(), + import.crate_lint(), &full_path, - directive.span, + import.span, None, ); } if let ModuleOrUniformRoot::Module(module) = module { - if module.def_id() == directive.parent_scope.module.def_id() { + if module.def_id() == import.parent_scope.module.def_id() { // Importing a module into itself is not allowed. return Some(UnresolvedImportError { - span: directive.span, + span: import.span, label: Some(String::from("cannot glob-import a module into itself")), note: Vec::new(), suggestion: None, @@ -995,15 +988,10 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } if !is_prelude && max_vis.get() != ty::Visibility::Invisible && // Allow empty globs. - !max_vis.get().is_at_least(directive.vis.get(), &*self) + !max_vis.get().is_at_least(import.vis.get(), &*self) { let msg = "glob import doesn't reexport anything because no candidate is public enough"; - self.r.lint_buffer.buffer_lint( - UNUSED_IMPORTS, - directive.id, - directive.span, - msg, - ); + self.r.lint_buffer.buffer_lint(UNUSED_IMPORTS, import.id, import.span, msg); } return None; } @@ -1013,7 +1001,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let mut all_ns_err = true; self.r.per_ns(|this, ns| { if !type_ns_only || ns == TypeNS { - let orig_vis = directive.vis.replace(ty::Visibility::Invisible); + let orig_vis = import.vis.replace(ty::Visibility::Invisible); let orig_blacklisted_binding = mem::replace(&mut this.blacklisted_binding, target_bindings[ns].get()); let orig_last_import_segment = mem::replace(&mut this.last_import_segment, true); @@ -1021,13 +1009,13 @@ impl<'a, 'b> ImportResolver<'a, 'b> { module, ident, ns, - &directive.parent_scope, + &import.parent_scope, true, - directive.span, + import.span, ); this.last_import_segment = orig_last_import_segment; this.blacklisted_binding = orig_blacklisted_binding; - directive.vis.set(orig_vis); + import.vis.set(orig_vis); match binding { Ok(binding) => { @@ -1044,7 +1032,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { ident, ns, target_binding, - directive.module_path.is_empty(), + import.module_path.is_empty(), ); } } @@ -1053,7 +1041,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let res = binding.res(); if let Ok(initial_res) = initial_res { if res != initial_res && this.ambiguity_errors.is_empty() { - span_bug!(directive.span, "inconsistent resolution for an import"); + span_bug!(import.span, "inconsistent resolution for an import"); } } else { if res != Res::Err @@ -1064,7 +1052,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let msg_note = "import resolution is stuck, try simplifying other imports"; this.session - .struct_span_err(directive.span, msg) + .struct_span_err(import.span, msg) .note(msg_note) .emit(); } @@ -1090,9 +1078,9 @@ impl<'a, 'b> ImportResolver<'a, 'b> { module, ident, ns, - &directive.parent_scope, + &import.parent_scope, true, - directive.span, + import.span, ); if binding.is_ok() { all_ns_failed = false; @@ -1143,7 +1131,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { }); let (suggestion, note) = - match self.check_for_module_export_macro(directive, module, ident) { + match self.check_for_module_export_macro(import, module, ident) { Some((suggestion, note)) => (suggestion.or(lev_suggestion), note), _ => (lev_suggestion, Vec::new()), }; @@ -1169,14 +1157,14 @@ impl<'a, 'b> ImportResolver<'a, 'b> { }; Some(UnresolvedImportError { - span: directive.span, + span: import.span, label: Some(label), note, suggestion, }) } else { // `resolve_ident_in_module` reported a privacy error. - self.r.import_dummy_binding(directive); + self.r.import_dummy_binding(import); None }; } @@ -1185,7 +1173,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let mut any_successful_reexport = false; self.r.per_ns(|this, ns| { if let Ok(binding) = source_bindings[ns].get() { - let vis = directive.vis.get(); + let vis = import.vis.get(); if !binding.pseudo_vis().is_at_least(vis, &*this) { reexport_error = Some((ns, binding)); } else { @@ -1206,42 +1194,42 @@ impl<'a, 'b> ImportResolver<'a, 'b> { ); self.r.lint_buffer.buffer_lint( PUB_USE_OF_PRIVATE_EXTERN_CRATE, - directive.id, - directive.span, + import.id, + import.span, &msg, ); } else if ns == TypeNS { struct_span_err!( self.r.session, - directive.span, + import.span, E0365, "`{}` is private, and cannot be re-exported", ident ) - .span_label(directive.span, format!("re-export of private `{}`", ident)) + .span_label(import.span, format!("re-export of private `{}`", ident)) .note(&format!("consider declaring type or module `{}` with `pub`", ident)) .emit(); } else { let msg = format!("`{}` is private, and cannot be re-exported", ident); let note_msg = format!("consider marking `{}` as `pub` in the imported module", ident,); - struct_span_err!(self.r.session, directive.span, E0364, "{}", &msg) - .span_note(directive.span, ¬e_msg) + struct_span_err!(self.r.session, import.span, E0364, "{}", &msg) + .span_note(import.span, ¬e_msg) .emit(); } } - if directive.module_path.len() <= 1 { + if import.module_path.len() <= 1 { // HACK(eddyb) `lint_if_path_starts_with_module` needs at least // 2 segments, so the `resolve_path` above won't trigger it. - let mut full_path = directive.module_path.clone(); + let mut full_path = import.module_path.clone(); full_path.push(Segment::from_ident(ident)); self.r.per_ns(|this, ns| { if let Ok(binding) = source_bindings[ns].get() { this.lint_if_path_starts_with_module( - directive.crate_lint(), + import.crate_lint(), &full_path, - directive.span, + import.span, Some(binding), ); } @@ -1253,17 +1241,11 @@ impl<'a, 'b> ImportResolver<'a, 'b> { // purposes it's good enough to just favor one over the other. self.r.per_ns(|this, ns| { if let Ok(binding) = source_bindings[ns].get() { - this.import_res_map.entry(directive.id).or_default()[ns] = Some(binding.res()); + this.import_res_map.entry(import.id).or_default()[ns] = Some(binding.res()); } }); - self.check_for_redundant_imports( - ident, - directive, - source_bindings, - target_bindings, - target, - ); + self.check_for_redundant_imports(ident, import, source_bindings, target_bindings, target); debug!("(resolving single import) successfully resolved import"); None @@ -1272,19 +1254,19 @@ impl<'a, 'b> ImportResolver<'a, 'b> { fn check_for_redundant_imports( &mut self, ident: Ident, - directive: &'b ImportDirective<'b>, + import: &'b Import<'b>, source_bindings: &PerNS, Determinacy>>>, target_bindings: &PerNS>>>, target: Ident, ) { // Skip if the import was produced by a macro. - if directive.parent_scope.expansion != ExpnId::root() { + if import.parent_scope.expansion != ExpnId::root() { return; } // Skip if we are inside a named module (in contrast to an anonymous // module defined by a block). - if let ModuleKind::Def(..) = directive.parent_scope.module.kind { + if let ModuleKind::Def(..) = import.parent_scope.module.kind { return; } @@ -1304,10 +1286,10 @@ impl<'a, 'b> ImportResolver<'a, 'b> { match this.early_resolve_ident_in_lexical_scope( target, ScopeSet::All(ns, false), - &directive.parent_scope, + &import.parent_scope, false, false, - directive.span, + import.span, ) { Ok(other_binding) => { is_redundant[ns] = Some( @@ -1329,35 +1311,35 @@ impl<'a, 'b> ImportResolver<'a, 'b> { redundant_spans.dedup(); self.r.lint_buffer.buffer_lint_with_diagnostic( UNUSED_IMPORTS, - directive.id, - directive.span, + import.id, + import.span, &format!("the item `{}` is imported redundantly", ident), BuiltinLintDiagnostics::RedundantImport(redundant_spans, ident), ); } } - fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) { - let module = match directive.imported_module.get().unwrap() { + fn resolve_glob_import(&mut self, import: &'b Import<'b>) { + let module = match import.imported_module.get().unwrap() { ModuleOrUniformRoot::Module(module) => module, _ => { - self.r.session.span_err(directive.span, "cannot glob-import all possible crates"); + self.r.session.span_err(import.span, "cannot glob-import all possible crates"); return; } }; if module.is_trait() { - self.r.session.span_err(directive.span, "items in traits are not importable."); + self.r.session.span_err(import.span, "items in traits are not importable."); return; - } else if module.def_id() == directive.parent_scope.module.def_id() { + } else if module.def_id() == import.parent_scope.module.def_id() { return; - } else if let GlobImport { is_prelude: true, .. } = directive.subclass { + } else if let ImportKind::Glob { is_prelude: true, .. } = import.kind { self.r.prelude = Some(module); return; } // Add to module's glob_importers - module.glob_importers.borrow_mut().push(directive); + module.glob_importers.borrow_mut().push(import); // Ensure that `resolutions` isn't borrowed during `try_define`, // since it might get updated via a glob cycle. @@ -1371,19 +1353,19 @@ impl<'a, 'b> ImportResolver<'a, 'b> { }) .collect::>(); for (mut key, binding) in bindings { - let scope = match key.ident.span.reverse_glob_adjust(module.expansion, directive.span) { + let scope = match key.ident.span.reverse_glob_adjust(module.expansion, import.span) { Some(Some(def)) => self.r.macro_def_scope(def), - Some(None) => directive.parent_scope.module, + Some(None) => import.parent_scope.module, None => continue, }; if self.r.is_accessible_from(binding.pseudo_vis(), scope) { - let imported_binding = self.r.import(binding, directive); - let _ = self.r.try_define(directive.parent_scope.module, key, imported_binding); + let imported_binding = self.r.import(binding, import); + let _ = self.r.try_define(import.parent_scope.module, key, imported_binding); } } // Record the destination of this import - self.r.record_partial_res(directive.id, PartialRes::new(module.res().unwrap())); + self.r.record_partial_res(import.id, PartialRes::new(module.res().unwrap())); } // Miscellaneous post-processing, including recording re-exports, @@ -1407,16 +1389,16 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } } - if let NameBindingKind::Import { binding: orig_binding, directive, .. } = binding.kind { + if let NameBindingKind::Import { binding: orig_binding, import, .. } = binding.kind { if ns == TypeNS && orig_binding.is_variant() && !orig_binding.vis.is_at_least(binding.vis, &*this) { - let msg = match directive.subclass { - ImportDirectiveSubclass::SingleImport { .. } => { + let msg = match import.kind { + ImportKind::Single { .. } => { format!("variant `{}` is private and cannot be re-exported", ident) } - ImportDirectiveSubclass::GlobImport { .. } => { + ImportKind::Glob { .. } => { let msg = "enum is private and its variants \ cannot be re-exported" .to_owned(); @@ -1432,18 +1414,18 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } msg } - ref s => bug!("unexpected import subclass {:?}", s), + ref s => bug!("unexpected import kind {:?}", s), }; let mut err = this.session.struct_span_err(binding.span, &msg); - let imported_module = match directive.imported_module.get() { + let imported_module = match import.imported_module.get() { Some(ModuleOrUniformRoot::Module(module)) => module, _ => bug!("module should exist"), }; let parent_module = imported_module.parent.expect("parent should exist"); let resolutions = this.resolutions(parent_module).borrow(); - let enum_path_segment_index = directive.module_path.len() - 1; - let enum_ident = directive.module_path[enum_path_segment_index].ident; + let enum_path_segment_index = import.module_path.len() - 1; + let enum_ident = import.module_path[enum_path_segment_index].ident; let key = this.new_key(enum_ident, TypeNS); let enum_resolution = resolutions.get(&key).expect("resolution should exist"); @@ -1481,11 +1463,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } } -fn import_path_to_string( - names: &[Ident], - subclass: &ImportDirectiveSubclass<'_>, - span: Span, -) -> String { +fn import_path_to_string(names: &[Ident], import_kind: &ImportKind<'_>, span: Span) -> String { let pos = names.iter().position(|p| span == p.span && p.name != kw::PathRoot); let global = !names.is_empty() && names[0].name == kw::PathRoot; if let Some(pos) = pos { @@ -1494,22 +1472,22 @@ fn import_path_to_string( } else { let names = if global { &names[1..] } else { names }; if names.is_empty() { - import_directive_subclass_to_string(subclass) + import_kind_to_string(import_kind) } else { format!( "{}::{}", names_to_string(&names.iter().map(|ident| ident.name).collect::>()), - import_directive_subclass_to_string(subclass), + import_kind_to_string(import_kind), ) } } } -fn import_directive_subclass_to_string(subclass: &ImportDirectiveSubclass<'_>) -> String { - match *subclass { - SingleImport { source, .. } => source.to_string(), - GlobImport { .. } => "*".to_string(), - ExternCrate { .. } => "".to_string(), - MacroUse => "#[macro_use]".to_string(), +fn import_kind_to_string(import_kind: &ImportKind<'_>) -> String { + match import_kind { + ImportKind::Single { source, .. } => source.to_string(), + ImportKind::Glob { .. } => "*".to_string(), + ImportKind::ExternCrate { .. } => "".to_string(), + ImportKind::MacroUse => "#[macro_use]".to_string(), } } diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 3481beec42a84..97d60e1a23d8d 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -2189,10 +2189,10 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { trait_name: Ident, ) -> SmallVec<[NodeId; 1]> { let mut import_ids = smallvec![]; - while let NameBindingKind::Import { directive, binding, .. } = kind { - self.r.maybe_unused_trait_imports.insert(directive.id); - self.r.add_to_glob_map(&directive, trait_name); - import_ids.push(directive.id); + while let NameBindingKind::Import { import, binding, .. } = kind { + self.r.maybe_unused_trait_imports.insert(import.id); + self.r.add_to_glob_map(&import, trait_name); + import_ids.push(import.id); kind = &binding.kind; } import_ids diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 44eba0d533d3a..492ac6ed83977 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -56,7 +56,7 @@ use std::{cmp, fmt, iter, ptr}; use diagnostics::{extend_span_to_previous_binding, find_span_of_binding_until_next_binding}; use diagnostics::{ImportSuggestion, Suggestion}; -use imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver, NameResolution}; +use imports::{Import, ImportKind, ImportResolver, NameResolution}; use late::{HasGenericParams, PathSource, Rib, RibKind::*}; use macros::{LegacyBinding, LegacyScope}; @@ -456,8 +456,8 @@ pub struct ModuleData<'a> { no_implicit_prelude: bool, - glob_importers: RefCell>>, - globs: RefCell>>, + glob_importers: RefCell>>, + globs: RefCell>>, // Used to memoize the traits in this module for faster searches through all traits in scope. traits: RefCell)]>>>, @@ -584,7 +584,7 @@ impl<'a> ToNameBinding<'a> for &'a NameBinding<'a> { enum NameBindingKind<'a> { Res(Res, /* is_macro_export */ bool), Module(Module<'a>), - Import { binding: &'a NameBinding<'a>, directive: &'a ImportDirective<'a>, used: Cell }, + Import { binding: &'a NameBinding<'a>, import: &'a Import<'a>, used: Cell }, } impl<'a> NameBindingKind<'a> { @@ -713,8 +713,7 @@ impl<'a> NameBinding<'a> { fn is_extern_crate(&self) -> bool { match self.kind { NameBindingKind::Import { - directive: - &ImportDirective { subclass: ImportDirectiveSubclass::ExternCrate { .. }, .. }, + import: &Import { kind: ImportKind::ExternCrate { .. }, .. }, .. } => true, NameBindingKind::Module(&ModuleData { @@ -734,7 +733,7 @@ impl<'a> NameBinding<'a> { fn is_glob_import(&self) -> bool { match self.kind { - NameBindingKind::Import { directive, .. } => directive.is_glob(), + NameBindingKind::Import { import, .. } => import.is_glob(), _ => false, } } @@ -839,10 +838,10 @@ pub struct Resolver<'a> { field_names: FxHashMap>>, /// All imports known to succeed or fail. - determined_imports: Vec<&'a ImportDirective<'a>>, + determined_imports: Vec<&'a Import<'a>>, /// All non-determined imports. - indeterminate_imports: Vec<&'a ImportDirective<'a>>, + indeterminate_imports: Vec<&'a Import<'a>>, /// FIXME: Refactor things so that these fields are passed through arguments and not resolver. /// We are resolving a last import segment during import validation. @@ -947,7 +946,7 @@ pub struct Resolver<'a> { /// Avoid duplicated errors for "name already defined". name_already_seen: FxHashMap, - potentially_unused_imports: Vec<&'a ImportDirective<'a>>, + potentially_unused_imports: Vec<&'a Import<'a>>, /// Table for mapping struct IDs into struct constructor IDs, /// it's not used during normal resolution, only for better error reporting. @@ -971,7 +970,7 @@ pub struct ResolverArenas<'a> { modules: arena::TypedArena>, local_modules: RefCell>>, name_bindings: arena::TypedArena>, - import_directives: arena::TypedArena>, + imports: arena::TypedArena>, name_resolutions: arena::TypedArena>>, legacy_bindings: arena::TypedArena>, ast_paths: arena::TypedArena, @@ -991,11 +990,8 @@ impl<'a> ResolverArenas<'a> { fn alloc_name_binding(&'a self, name_binding: NameBinding<'a>) -> &'a NameBinding<'a> { self.name_bindings.alloc(name_binding) } - fn alloc_import_directive( - &'a self, - import_directive: ImportDirective<'a>, - ) -> &'a ImportDirective<'_> { - self.import_directives.alloc(import_directive) + fn alloc_import(&'a self, import: Import<'a>) -> &'a Import<'_> { + self.imports.alloc(import) } fn alloc_name_resolution(&'a self) -> &'a RefCell> { self.name_resolutions.alloc(Default::default()) @@ -1410,7 +1406,7 @@ impl<'a> Resolver<'a> { misc2: AmbiguityErrorMisc::None, }); } - if let NameBindingKind::Import { directive, binding, ref used } = used_binding.kind { + if let NameBindingKind::Import { import, binding, ref used } = used_binding.kind { // Avoid marking `extern crate` items that refer to a name from extern prelude, // but not introduce it, as used if they are accessed from lexical scope. if is_lexical_scope { @@ -1423,17 +1419,17 @@ impl<'a> Resolver<'a> { } } used.set(true); - directive.used.set(true); - self.used_imports.insert((directive.id, ns)); - self.add_to_glob_map(&directive, ident); + import.used.set(true); + self.used_imports.insert((import.id, ns)); + self.add_to_glob_map(&import, ident); self.record_use(ident, ns, binding, false); } } #[inline] - fn add_to_glob_map(&mut self, directive: &ImportDirective<'_>, ident: Ident) { - if directive.is_glob() { - self.glob_map.entry(directive.id).or_default().insert(ident.name); + fn add_to_glob_map(&mut self, import: &Import<'_>, ident: Ident) { + if import.is_glob() { + self.glob_map.entry(import.id).or_default().insert(ident.name); } } @@ -2258,10 +2254,9 @@ impl<'a> Resolver<'a> { // `ExternCrate` (also used for `crate::...`) then no need to issue a // warning, this looks all good! if let Some(binding) = second_binding { - if let NameBindingKind::Import { directive: d, .. } = binding.kind { - // Careful: we still want to rewrite paths from - // renamed extern crates. - if let ImportDirectiveSubclass::ExternCrate { source: None, .. } = d.subclass { + if let NameBindingKind::Import { import, .. } = binding.kind { + // Careful: we still want to rewrite paths from renamed extern crates. + if let ImportKind::ExternCrate { source: None, .. } = import.kind { return; } } @@ -2564,10 +2559,10 @@ impl<'a> Resolver<'a> { // See https://github.com/rust-lang/rust/issues/32354 use NameBindingKind::Import; - let directive = match (&new_binding.kind, &old_binding.kind) { + let import = match (&new_binding.kind, &old_binding.kind) { // If there are two imports where one or both have attributes then prefer removing the // import without attributes. - (Import { directive: new, .. }, Import { directive: old, .. }) + (Import { import: new, .. }, Import { import: old, .. }) if { !new_binding.span.is_dummy() && !old_binding.span.is_dummy() @@ -2581,11 +2576,11 @@ impl<'a> Resolver<'a> { } } // Otherwise prioritize the new binding. - (Import { directive, .. }, other) if !new_binding.span.is_dummy() => { - Some((directive, new_binding.span, other.is_import())) + (Import { import, .. }, other) if !new_binding.span.is_dummy() => { + Some((import, new_binding.span, other.is_import())) } - (other, Import { directive, .. }) if !old_binding.span.is_dummy() => { - Some((directive, old_binding.span, other.is_import())) + (other, Import { import, .. }) if !old_binding.span.is_dummy() => { + Some((import, old_binding.span, other.is_import())) } _ => None, }; @@ -2602,22 +2597,22 @@ impl<'a> Resolver<'a> { && !has_dummy_span && ((new_binding.is_extern_crate() || old_binding.is_extern_crate()) || from_item); - match directive { - Some((directive, span, true)) if should_remove_import && directive.is_nested() => { - self.add_suggestion_for_duplicate_nested_use(&mut err, directive, span) + match import { + Some((import, span, true)) if should_remove_import && import.is_nested() => { + self.add_suggestion_for_duplicate_nested_use(&mut err, import, span) } - Some((directive, _, true)) if should_remove_import && !directive.is_glob() => { + Some((import, _, true)) if should_remove_import && !import.is_glob() => { // Simple case - remove the entire import. Due to the above match arm, this can // only be a single use so just remove it entirely. err.tool_only_span_suggestion( - directive.use_span_with_attributes, + import.use_span_with_attributes, "remove unnecessary import", String::new(), Applicability::MaybeIncorrect, ); } - Some((directive, span, _)) => { - self.add_suggestion_for_rename_of_use(&mut err, name, directive, span) + Some((import, span, _)) => { + self.add_suggestion_for_rename_of_use(&mut err, name, import, span) } _ => {} } @@ -2639,7 +2634,7 @@ impl<'a> Resolver<'a> { &self, err: &mut DiagnosticBuilder<'_>, name: Name, - directive: &ImportDirective<'_>, + import: &Import<'_>, binding_span: Span, ) { let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() { @@ -2649,11 +2644,11 @@ impl<'a> Resolver<'a> { }; let mut suggestion = None; - match directive.subclass { - ImportDirectiveSubclass::SingleImport { type_ns_only: true, .. } => { + match import.kind { + ImportKind::Single { type_ns_only: true, .. } => { suggestion = Some(format!("self as {}", suggested_name)) } - ImportDirectiveSubclass::SingleImport { source, .. } => { + ImportKind::Single { source, .. } => { if let Some(pos) = source.span.hi().0.checked_sub(binding_span.lo().0).map(|pos| pos as usize) { @@ -2669,7 +2664,7 @@ impl<'a> Resolver<'a> { } } } - ImportDirectiveSubclass::ExternCrate { source, target, .. } => { + ImportKind::ExternCrate { source, target, .. } => { suggestion = Some(format!( "extern crate {} as {};", source.unwrap_or(target.name), @@ -2711,27 +2706,27 @@ impl<'a> Resolver<'a> { /// If the nested use contains only one import then the suggestion will remove the entire /// line. /// - /// It is expected that the directive provided is a nested import - this isn't checked by the + /// It is expected that the provided import is nested - this isn't checked by the /// function. If this invariant is not upheld, this function's behaviour will be unexpected /// as characters expected by span manipulations won't be present. fn add_suggestion_for_duplicate_nested_use( &self, err: &mut DiagnosticBuilder<'_>, - directive: &ImportDirective<'_>, + import: &Import<'_>, binding_span: Span, ) { - assert!(directive.is_nested()); + assert!(import.is_nested()); let message = "remove unnecessary import"; // Two examples will be used to illustrate the span manipulations we're doing: // // - Given `use issue_52891::{d, a, e};` where `a` is a duplicate then `binding_span` is - // `a` and `directive.use_span` is `issue_52891::{d, a, e};`. + // `a` and `import.use_span` is `issue_52891::{d, a, e};`. // - Given `use issue_52891::{d, e, a};` where `a` is a duplicate then `binding_span` is - // `a` and `directive.use_span` is `issue_52891::{d, e, a};`. + // `a` and `import.use_span` is `issue_52891::{d, e, a};`. let (found_closing_brace, span) = - find_span_of_binding_until_next_binding(self.session, binding_span, directive.use_span); + find_span_of_binding_until_next_binding(self.session, binding_span, import.use_span); // If there was a closing brace then identify the span to remove any trailing commas from // previous imports. @@ -2747,7 +2742,7 @@ impl<'a> Resolver<'a> { // Remove the entire line if we cannot extend the span back, this indicates a // `issue_52891::{self}` case. err.span_suggestion( - directive.use_span_with_attributes, + import.use_span_with_attributes, message, String::new(), Applicability::MaybeIncorrect, diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index ec251c224b690..88bfe7661e203 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -532,13 +532,16 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { match self.tables.expr_ty_adjusted(&hir_node).kind { ty::Adt(def, _) if !def.is_enum() => { let variant = &def.non_enum_variant(); - let index = self.tcx.find_field_index(ident, variant).unwrap(); filter!(self.span_utils, ident.span); let span = self.span_from_span(ident.span); return Some(Data::RefData(Ref { kind: RefKind::Variable, span, - ref_id: id_from_def_id(variant.fields[index].did), + ref_id: self + .tcx + .find_field_index(ident, variant) + .map(|index| id_from_def_id(variant.fields[index].did)) + .unwrap_or_else(|| null_id()), })); } ty::Tuple(..) => None, diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index e9bb94ca49050..a3a9b5427678d 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -872,7 +872,7 @@ impl Niche { #[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct LayoutDetails { /// Says where the fields are located within the layout. - /// Primitives and fieldless enums appear as unions without fields. + /// Primitives and uninhabited enums appear as unions without fields. pub fields: FieldPlacement, /// Encodes information about multi-variant layouts. diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 29c124eb3a998..84854dff85165 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -577,8 +577,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let var_ty = self.resolve_vars_with_obligations(var_ty); let msg = format!("first introduced with type `{}` here", var_ty); err.span_label(hir.span(var_id), msg); - let in_arm = hir.parent_iter(var_id).any(|(_, n)| matches!(n, hir::Node::Arm(..))); - let pre = if in_arm { "in the same arm, " } else { "" }; + let in_match = hir.parent_iter(var_id).any(|(_, n)| { + matches!( + n, + hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Match(.., hir::MatchSource::Normal), + .. + }) + ) + }); + let pre = if in_match { "in the same arm, " } else { "" }; err.note(&format!("{}a binding must have the same type in all alternatives", pre)); err.emit(); } diff --git a/src/test/ui/assign-to-method.rs b/src/test/ui/assign-to-method.rs deleted file mode 100644 index 95f066c382c8d..0000000000000 --- a/src/test/ui/assign-to-method.rs +++ /dev/null @@ -1,22 +0,0 @@ -struct Cat { - meows : usize, - - how_hungry : isize, -} - -impl Cat { - pub fn speak(&self) { self.meows += 1; } -} - -fn cat(in_x : usize, in_y : isize) -> Cat { - Cat { - meows: in_x, - how_hungry: in_y - } -} - -fn main() { - let nyan : Cat = cat(52, 99); - nyan.speak = || println!("meow"); //~ ERROR attempted to take value of method - nyan.speak += || println!("meow"); //~ ERROR attempted to take value of method -} diff --git a/src/test/ui/consts/const-eval/ub-enum.rs b/src/test/ui/consts/const-eval/ub-enum.rs index 483285aa4e123..499be5107f97b 100644 --- a/src/test/ui/consts/const-eval/ub-enum.rs +++ b/src/test/ui/consts/const-eval/ub-enum.rs @@ -1,34 +1,37 @@ +// ignore-tidy-linelength +#![feature(const_transmute, never_type)] #![allow(const_err)] // make sure we cannot allow away the errors tested here +use std::mem; #[repr(transparent)] #[derive(Copy, Clone)] struct Wrap(T); +#[derive(Copy, Clone)] +enum Never {} + +// # simple enum with discriminant 0 + #[repr(usize)] #[derive(Copy, Clone)] enum Enum { A = 0, } -#[repr(C)] -union TransmuteEnum { - in1: &'static u8, - in2: usize, - out1: Enum, - out2: Wrap, -} -const GOOD_ENUM: Enum = unsafe { TransmuteEnum { in2: 0 }.out1 }; +const GOOD_ENUM: Enum = unsafe { mem::transmute(0usize) }; -const BAD_ENUM: Enum = unsafe { TransmuteEnum { in2: 1 }.out1 }; +const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; //~^ ERROR is undefined behavior -const BAD_ENUM_PTR: Enum = unsafe { TransmuteEnum { in1: &1 }.out1 }; +const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; //~^ ERROR is undefined behavior -const BAD_ENUM_WRAPPED: Wrap = unsafe { TransmuteEnum { in1: &1 }.out2 }; +const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) }; //~^ ERROR is undefined behavior +// # simple enum with discriminant 2 + // (Potentially) invalid enum discriminant #[repr(usize)] #[derive(Copy, Clone)] @@ -36,39 +39,58 @@ enum Enum2 { A = 2, } -#[repr(C)] -union TransmuteEnum2 { - in1: usize, - in2: &'static u8, - in3: (), - out1: Enum2, - out2: Wrap, // something wrapping the enum so that we test layout first, not enum - out3: Option, -} -const BAD_ENUM2: Enum2 = unsafe { TransmuteEnum2 { in1: 0 }.out1 }; +const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; //~^ ERROR is undefined behavior -const BAD_ENUM2_PTR: Enum2 = unsafe { TransmuteEnum2 { in2: &0 }.out1 }; +const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; //~^ ERROR is undefined behavior -const BAD_ENUM2_WRAPPED: Wrap = unsafe { TransmuteEnum2 { in2: &0 }.out2 }; +// something wrapping the enum so that we test layout first, not enum +const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; //~^ ERROR is undefined behavior // Undef enum discriminant. -const BAD_ENUM2_UNDEF : Enum2 = unsafe { TransmuteEnum2 { in3: () }.out1 }; +#[repr(C)] +union MaybeUninit { + uninit: (), + init: T, +} +const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init }; //~^ ERROR is undefined behavior // Pointer value in an enum with a niche that is not just 0. -const BAD_ENUM2_OPTION_PTR: Option = unsafe { TransmuteEnum2 { in2: &0 }.out3 }; +const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; //~^ ERROR is undefined behavior +// # valid discriminant for uninhabited variant + +// An enum with 3 variants of which some are uninhabited -- so the uninhabited variants *do* +// have a discriminant. +enum UninhDiscriminant { + A, + B(!), + C, + D(Never), +} + +const GOOD_INHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(0u8) }; // variant A +const GOOD_INHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(2u8) }; // variant C + +const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) }; +//~^ ERROR is undefined behavior +const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) }; +//~^ ERROR is undefined behavior + +// # other + // Invalid enum field content (mostly to test printing of paths for enum tuple // variants and tuples). -#[repr(C)] -union TransmuteChar { - a: u32, - b: char, -} // Need to create something which does not clash with enum layout optimizations. -const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b })); +const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) })); +//~^ ERROR is undefined behavior + +// All variants are uninhabited but also have data. +const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(1usize) }; +//~^ ERROR is undefined behavior +const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(1usize) }; //~^ ERROR is undefined behavior fn main() { diff --git a/src/test/ui/consts/const-eval/ub-enum.stderr b/src/test/ui/consts/const-eval/ub-enum.stderr index 8c47d68e9686b..e0cf2cd610fd6 100644 --- a/src/test/ui/consts/const-eval/ub-enum.stderr +++ b/src/test/ui/consts/const-eval/ub-enum.stderr @@ -1,55 +1,55 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:23:1 + --> $DIR/ub-enum.rs:24:1 | -LL | const BAD_ENUM: Enum = unsafe { TransmuteEnum { in2: 1 }.out1 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 1, but expected a valid enum discriminant +LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 1, but expected a valid enum discriminant | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:26:1 + --> $DIR/ub-enum.rs:27:1 | -LL | const BAD_ENUM_PTR: Enum = unsafe { TransmuteEnum { in1: &1 }.out1 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes +LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:29:1 + --> $DIR/ub-enum.rs:30:1 | -LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { TransmuteEnum { in1: &1 }.out2 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0., but expected initialized plain (non-pointer) bytes +LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0., but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:48:1 + --> $DIR/ub-enum.rs:42:1 | -LL | const BAD_ENUM2: Enum2 = unsafe { TransmuteEnum2 { in1: 0 }.out1 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected a valid enum discriminant +LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected a valid enum discriminant | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:50:1 + --> $DIR/ub-enum.rs:44:1 | -LL | const BAD_ENUM2_PTR: Enum2 = unsafe { TransmuteEnum2 { in2: &0 }.out1 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes +LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:52:1 + --> $DIR/ub-enum.rs:47:1 | -LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { TransmuteEnum2 { in2: &0 }.out2 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0., but expected initialized plain (non-pointer) bytes +LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0., but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:56:1 | -LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { TransmuteEnum2 { in3: () }.out1 }; +LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at ., but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -57,19 +57,51 @@ LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { TransmuteEnum2 { in3: () }.out1 }; error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:60:1 | -LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { TransmuteEnum2 { in2: &0 }.out3 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes +LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:71:1 + --> $DIR/ub-enum.rs:77:1 | -LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b })); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at ..0.1, but expected a valid unicode codepoint +LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at ..0 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. -error: aborting due to 9 previous errors +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-enum.rs:79:1 + | +LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Never at ..0 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-enum.rs:87:1 + | +LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at ..0.1, but expected a valid unicode codepoint + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-enum.rs:91:1 + | +LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(1usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at ..0.1 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-enum.rs:93:1 + | +LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(1usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Never at ..0.1 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error: aborting due to 13 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/ub-nonnull.rs b/src/test/ui/consts/const-eval/ub-nonnull.rs index 8ce64ced7dff4..1f46b6c98ad2f 100644 --- a/src/test/ui/consts/const-eval/ub-nonnull.rs +++ b/src/test/ui/consts/const-eval/ub-nonnull.rs @@ -25,11 +25,11 @@ const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; //~^ ERROR it is undefined behavior to use this value #[repr(C)] -union Transmute { +union MaybeUninit { uninit: (), - out: NonZeroU8, + init: T, } -const UNINIT: NonZeroU8 = unsafe { Transmute { uninit: () }.out }; +const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init }; //~^ ERROR it is undefined behavior to use this value // Also test other uses of rustc_layout_scalar_valid_range_start diff --git a/src/test/ui/consts/const-eval/ub-nonnull.stderr b/src/test/ui/consts/const-eval/ub-nonnull.stderr index ec0561870576f..edfc7ac837fc7 100644 --- a/src/test/ui/consts/const-eval/ub-nonnull.stderr +++ b/src/test/ui/consts/const-eval/ub-nonnull.stderr @@ -43,8 +43,8 @@ LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; error[E0080]: it is undefined behavior to use this value --> $DIR/ub-nonnull.rs:32:1 | -LL | const UNINIT: NonZeroU8 = unsafe { Transmute { uninit: () }.out }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at .0, but expected initialized plain (non-pointer) bytes +LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at .0, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/const-eval/ub-ref.rs b/src/test/ui/consts/const-eval/ub-ref.rs index 889579ca1ecef..562ec99111b69 100644 --- a/src/test/ui/consts/const-eval/ub-ref.rs +++ b/src/test/ui/consts/const-eval/ub-ref.rs @@ -8,9 +8,16 @@ const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; //~^ ERROR it is undefined behavior to use this value //~^^ type validation failed: encountered an unaligned reference (required 2 byte alignment but found 1) +const UNALIGNED_BOX: Box = unsafe { mem::transmute(&[0u8; 4]) }; +//~^ ERROR it is undefined behavior to use this value +//~^^ type validation failed: encountered an unaligned box (required 2 byte alignment but found 1) + const NULL: &u16 = unsafe { mem::transmute(0usize) }; //~^ ERROR it is undefined behavior to use this value +const NULL_BOX: Box = unsafe { mem::transmute(0usize) }; +//~^ ERROR it is undefined behavior to use this value + // It is very important that we reject this: We do promote `&(4 * REF_AS_USIZE)`, // but that would fail to compile; so we ended up breaking user code that would // have worked fine had we not promoted. @@ -20,7 +27,13 @@ const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; //~^ ERROR it is undefined behavior to use this value +const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) }; +//~^ ERROR it is undefined behavior to use this value + const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) }; //~^ ERROR it is undefined behavior to use this value +const USIZE_AS_BOX: Box = unsafe { mem::transmute(1337usize) }; +//~^ ERROR it is undefined behavior to use this value + fn main() {} diff --git a/src/test/ui/consts/const-eval/ub-ref.stderr b/src/test/ui/consts/const-eval/ub-ref.stderr index 5cef0a488ebd7..fb3df8ace4e15 100644 --- a/src/test/ui/consts/const-eval/ub-ref.stderr +++ b/src/test/ui/consts/const-eval/ub-ref.stderr @@ -9,13 +9,29 @@ LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref.rs:11:1 | +LL | const UNALIGNED_BOX: Box = unsafe { mem::transmute(&[0u8; 4]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered an unaligned box (required 2 byte alignment but found 1) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-ref.rs:15:1 + | LL | const NULL: &u16 = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a NULL reference | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-ref.rs:17:1 + --> $DIR/ub-ref.rs:18:1 + | +LL | const NULL_BOX: Box = unsafe { mem::transmute(0usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a NULL box + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-ref.rs:24:1 | LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes @@ -23,7 +39,7 @@ LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-ref.rs:20:1 + --> $DIR/ub-ref.rs:27:1 | LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected plain (non-pointer) bytes @@ -31,13 +47,29 @@ LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-ref.rs:23:1 + --> $DIR/ub-ref.rs:30:1 + | +LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected plain (non-pointer) bytes + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-ref.rs:33:1 | LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (created from integer) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. -error: aborting due to 5 previous errors +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-ref.rs:36:1 + | +LL | const USIZE_AS_BOX: Box = unsafe { mem::transmute(1337usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (created from integer) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.rs b/src/test/ui/consts/const-eval/ub-uninhabit.rs index d2745d71bdb2f..e7350ae271673 100644 --- a/src/test/ui/consts/const-eval/ub-uninhabit.rs +++ b/src/test/ui/consts/const-eval/ub-uninhabit.rs @@ -7,18 +7,18 @@ use std::mem; enum Bar {} #[repr(C)] -union TransmuteUnion { - a: A, - b: B, +union MaybeUninit { + uninit: (), + init: T, } -const BAD_BAD_BAD: Bar = unsafe { (TransmuteUnion::<(), Bar> { a: () }).b }; +const BAD_BAD_BAD: Bar = unsafe { MaybeUninit { uninit: () }.init }; //~^ ERROR it is undefined behavior to use this value const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; //~^ ERROR it is undefined behavior to use this value -const BAD_BAD_ARRAY: [Bar; 1] = unsafe { (TransmuteUnion::<(), [Bar; 1]> { a: () }).b }; +const BAD_BAD_ARRAY: [Bar; 1] = unsafe { MaybeUninit { uninit: () }.init }; //~^ ERROR it is undefined behavior to use this value fn main() {} diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.stderr b/src/test/ui/consts/const-eval/ub-uninhabit.stderr index 4fef9aa84ea19..8ce4279a8b7dd 100644 --- a/src/test/ui/consts/const-eval/ub-uninhabit.stderr +++ b/src/test/ui/consts/const-eval/ub-uninhabit.stderr @@ -1,8 +1,8 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-uninhabit.rs:15:1 | -LL | const BAD_BAD_BAD: Bar = unsafe { (TransmuteUnion::<(), Bar> { a: () }).b }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar +LL | const BAD_BAD_BAD: Bar = unsafe { MaybeUninit { uninit: () }.init }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -17,8 +17,8 @@ LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; error[E0080]: it is undefined behavior to use this value --> $DIR/ub-uninhabit.rs:21:1 | -LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { (TransmuteUnion::<(), [Bar; 1]> { a: () }).b }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type [Bar; 1] +LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { MaybeUninit { uninit: () }.init }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar at [0] | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs index a5c2a57c6c886..26d378847462d 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.rs +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs @@ -1,72 +1,18 @@ // ignore-tidy-linelength +#![feature(const_transmute)] #![allow(unused)] #![allow(const_err)] // make sure we cannot allow away the errors tested here +use std::mem; + // normalize-stderr-test "offset \d+" -> "offset N" // normalize-stderr-test "allocation \d+" -> "allocation N" // normalize-stderr-test "size \d+" -> "size N" #[repr(C)] -union BoolTransmute { - val: u8, - bl: bool, -} - -#[repr(C)] -#[derive(Copy, Clone)] -struct SliceRepr { - ptr: *const u8, - len: usize, -} - -#[repr(C)] -#[derive(Copy, Clone)] -struct BadSliceRepr { - ptr: *const u8, - len: &'static u8, -} - -#[repr(C)] -union SliceTransmute { - repr: SliceRepr, - bad: BadSliceRepr, - addr: usize, - slice: &'static [u8], - raw_slice: *const [u8], - str: &'static str, - my_str: &'static MyStr, - my_slice: &'static MySliceBool, -} - -#[repr(C)] -#[derive(Copy, Clone)] -struct DynRepr { - ptr: *const u8, - vtable: *const u8, -} - -#[repr(C)] -#[derive(Copy, Clone)] -struct DynRepr2 { - ptr: *const u8, - vtable: *const u64, -} - -#[repr(C)] -#[derive(Copy, Clone)] -struct BadDynRepr { - ptr: *const u8, - vtable: usize, -} - -#[repr(C)] -union DynTransmute { - repr: DynRepr, - repr2: DynRepr2, - bad: BadDynRepr, - addr: usize, - rust: &'static dyn Trait, - raw_rust: *const dyn Trait, +union MaybeUninit { + uninit: (), + init: T, } trait Trait {} @@ -81,90 +27,99 @@ type MySliceBool = MySlice<[bool]>; // # str // OK -const STR_VALID: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.str}; +const STR_VALID: &str = unsafe { mem::transmute((&42u8, 1usize)) }; // bad str -const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str}; +const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) }; //~^ ERROR it is undefined behavior to use this value // bad str -const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str}; +const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) }; //~^ ERROR it is undefined behavior to use this value // bad str in user-defined unsized type -const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str}; +const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) }; //~^ ERROR it is undefined behavior to use this value // invalid UTF-8 -const STR_NO_UTF8: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; +const STR_NO_UTF8: &str = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) }; //~^ ERROR it is undefined behavior to use this value // invalid UTF-8 in user-defined str-like -const MYSTR_NO_UTF8: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str }; +const MYSTR_NO_UTF8: &MyStr = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) }; //~^ ERROR it is undefined behavior to use this value // # slice // OK -const SLICE_VALID: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.slice}; +const SLICE_VALID: &[u8] = unsafe { mem::transmute((&42u8, 1usize)) }; // bad slice: length uninit -const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.slice}; +const SLICE_LENGTH_UNINIT: &[u8] = unsafe { //~^ ERROR it is undefined behavior to use this value + let uninit_len = MaybeUninit:: { uninit: () }; + mem::transmute((42, uninit_len)) +}; // bad slice: length too big -const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice}; +const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) }; //~^ ERROR it is undefined behavior to use this value // bad slice: length not an int -const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice}; +const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) }; +//~^ ERROR it is undefined behavior to use this value +// bad slice box: length too big +const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) }; +//~^ ERROR it is undefined behavior to use this value +// bad slice box: length not an int +const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) }; //~^ ERROR it is undefined behavior to use this value // bad data *inside* the slice -const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }]; +const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; //~^ ERROR it is undefined behavior to use this value // good MySliceBool const MYSLICE_GOOD: &MySliceBool = &MySlice(true, [false]); // bad: sized field is not okay -const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]); +const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); //~^ ERROR it is undefined behavior to use this value // bad: unsized part is not okay -const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]); +const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); //~^ ERROR it is undefined behavior to use this value // # raw slice -const RAW_SLICE_VALID: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.raw_slice}; // ok -const RAW_SLICE_TOO_LONG: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.raw_slice}; // ok because raw -const RAW_SLICE_MUCH_TOO_LONG: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: usize::max_value() } }.raw_slice}; // ok because raw -const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr: 42 }.raw_slice}; +const RAW_SLICE_VALID: *const [u8] = unsafe { mem::transmute((&42u8, 1usize)) }; // ok +const RAW_SLICE_TOO_LONG: *const [u8] = unsafe { mem::transmute((&42u8, 999usize)) }; // ok because raw +const RAW_SLICE_MUCH_TOO_LONG: *const [u8] = unsafe { mem::transmute((&42u8, usize::max_value())) }; // ok because raw +const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { //~^ ERROR it is undefined behavior to use this value + let uninit_len = MaybeUninit:: { uninit: () }; + mem::transmute((42, uninit_len)) +}; // # trait object // bad trait object -const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; +const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { mem::transmute((&92u8, &3u8)) }; //~^ ERROR it is undefined behavior to use this value // bad trait object -const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; +const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; //~^ ERROR it is undefined behavior to use this value // bad trait object -const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; +const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, 4usize)) }; //~^ ERROR it is undefined behavior to use this value // bad data *inside* the trait object -const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; +const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) }; //~^ ERROR it is undefined behavior to use this value // # raw trait object -const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.raw_rust}; +const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; //~^ ERROR it is undefined behavior to use this value -const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust}; +const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; //~^ ERROR it is undefined behavior to use this value -const RAW_TRAIT_OBJ_CONTENT_INVALID: *const dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl } as *const _; // ok because raw +const RAW_TRAIT_OBJ_CONTENT_INVALID: *const dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) } as *const dyn Trait; // ok because raw // Const eval fails for these, so they need to be statics to error. static mut RAW_TRAIT_OBJ_VTABLE_NULL_THROUGH_REF: *const dyn Trait = unsafe { - DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust + mem::transmute::<_, &dyn Trait>((&92u8, 0usize)) //~^ ERROR could not evaluate static initializer }; static mut RAW_TRAIT_OBJ_VTABLE_INVALID_THROUGH_REF: *const dyn Trait = unsafe { - DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust + mem::transmute::<_, &dyn Trait>((&92u8, &3u64)) //~^ ERROR could not evaluate static initializer }; -fn main() { - let _ = RAW_TRAIT_OBJ_VTABLE_NULL; - let _ = RAW_TRAIT_OBJ_VTABLE_INVALID; -} +fn main() {} diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr index 4da9ad6c3327c..22adf0e55ee8c 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr @@ -1,159 +1,183 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:86:1 + --> $DIR/ub-wide-ptr.rs:32:1 | -LL | const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (not entirely in bounds) +LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (not entirely in bounds) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:89:1 + --> $DIR/ub-wide-ptr.rs:35:1 | -LL | const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer +LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:92:1 + --> $DIR/ub-wide-ptr.rs:38:1 | -LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer +LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:96:1 + --> $DIR/ub-wide-ptr.rs:42:1 | -LL | const STR_NO_UTF8: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at . +LL | const STR_NO_UTF8: &str = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at . | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:99:1 + --> $DIR/ub-wide-ptr.rs:45:1 | -LL | const MYSTR_NO_UTF8: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at ..0 +LL | const MYSTR_NO_UTF8: &MyStr = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at ..0 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:106:1 + --> $DIR/ub-wide-ptr.rs:52:1 | -LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.slice}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered undefined pointer +LL | / const SLICE_LENGTH_UNINIT: &[u8] = unsafe { +LL | | +LL | | let uninit_len = MaybeUninit:: { uninit: () }; +LL | | mem::transmute((42, uninit_len)) +LL | | }; + | |__^ type validation failed: encountered undefined pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:109:1 + --> $DIR/ub-wide-ptr.rs:58:1 + | +LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (not entirely in bounds) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:61:1 | -LL | const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (not entirely in bounds) +LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:112:1 + --> $DIR/ub-wide-ptr.rs:64:1 | -LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer +LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (not entirely in bounds) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:116:1 + --> $DIR/ub-wide-ptr.rs:67:1 | -LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .[0], but expected a boolean +LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:122:1 + --> $DIR/ub-wide-ptr.rs:71:1 | -LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..0, but expected a boolean +LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .[0], but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:125:1 + --> $DIR/ub-wide-ptr.rs:77:1 | -LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..1[0], but expected a boolean +LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..0, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:132:1 + --> $DIR/ub-wide-ptr.rs:80:1 | -LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr: 42 }.raw_slice}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered undefined pointer +LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..1[0], but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:137:1 + --> $DIR/ub-wide-ptr.rs:87:1 | -LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable +LL | / const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { +LL | | +LL | | let uninit_len = MaybeUninit:: { uninit: () }; +LL | | mem::transmute((42, uninit_len)) +LL | | }; + | |__^ type validation failed: encountered undefined pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:140:1 + --> $DIR/ub-wide-ptr.rs:95:1 | -LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable +LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { mem::transmute((&92u8, &3u8)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:143:1 + --> $DIR/ub-wide-ptr.rs:98:1 | -LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable +LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:147:1 + --> $DIR/ub-wide-ptr.rs:101:1 | -LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .., but expected a boolean +LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, 4usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:151:1 + --> $DIR/ub-wide-ptr.rs:105:1 + | +LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .., but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:109:1 | -LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.raw_rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable +LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:153:1 + --> $DIR/ub-wide-ptr.rs:111:1 | -LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable +LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: could not evaluate static initializer - --> $DIR/ub-wide-ptr.rs:159:5 + --> $DIR/ub-wide-ptr.rs:117:5 | -LL | DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid use of NULL pointer +LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid use of NULL pointer error[E0080]: could not evaluate static initializer - --> $DIR/ub-wide-ptr.rs:163:5 + --> $DIR/ub-wide-ptr.rs:121:5 | -LL | DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocation N which has size N +LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocation N which has size N -error: aborting due to 20 previous errors +error: aborting due to 22 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr index 2a338e276402c..d0e35615dab42 100644 --- a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr +++ b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr @@ -20,7 +20,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_uninhabited_zsts.rs:17:1 | LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type [Empty; 3] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Empty at [0] | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. 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 c8d060f5cdcfe..7794cc7583dfc 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 @@ -4,7 +4,6 @@ error[E0658]: internal implementation detail LL | #[rustc_allow_const_fn_ptr] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #29642 for more information = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable error: aborting due to previous error diff --git a/src/test/ui/consts/validate_never_arrays.stderr b/src/test/ui/consts/validate_never_arrays.stderr index 203620a771b8f..77f0a2ebd4021 100644 --- a/src/test/ui/consts/validate_never_arrays.stderr +++ b/src/test/ui/consts/validate_never_arrays.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_never_arrays.rs:3:1 | LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type [!; 1] at . + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .[0] | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -10,7 +10,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_never_arrays.rs:6:1 | LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type ! at .[0] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .[0] | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -18,7 +18,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_never_arrays.rs:7:1 | LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type ! at .[0] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .[0] | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/drop/dynamic-drop.rs b/src/test/ui/drop/dynamic-drop.rs index 451686d9ae21c..d31736f142c3f 100644 --- a/src/test/ui/drop/dynamic-drop.rs +++ b/src/test/ui/drop/dynamic-drop.rs @@ -3,6 +3,7 @@ #![feature(generators, generator_trait, untagged_unions)] #![feature(move_ref_pattern)] +#![feature(bindings_after_at)] #![allow(unused_assignments)] #![allow(unused_variables)] @@ -291,6 +292,44 @@ fn subslice_mixed_min_lengths(a: &Allocator, c: i32) { } } +fn bindings_after_at_dynamic_init_move(a: &Allocator, c: bool) { + let foo = if c { Some(a.alloc()) } else { None }; + let _x; + + if let bar @ Some(_) = foo { + _x = bar; + } +} + +fn bindings_after_at_dynamic_init_ref(a: &Allocator, c: bool) { + let foo = if c { Some(a.alloc()) } else { None }; + let _x; + + if let bar @ Some(_baz) = &foo { + _x = bar; + } +} + +fn bindings_after_at_dynamic_drop_move(a: &Allocator, c: bool) { + let foo = if c { Some(a.alloc()) } else { None }; + + if let bar @ Some(_) = foo { + bar + } else { + None + }; +} + +fn bindings_after_at_dynamic_drop_ref(a: &Allocator, c: bool) { + let foo = if c { Some(a.alloc()) } else { None }; + + if let bar @ Some(_baz) = &foo { + bar + } else { + &None + }; +} + fn move_ref_pattern(a: &Allocator) { let mut tup = (a.alloc(), a.alloc(), a.alloc(), a.alloc()); let (ref _a, ref mut _b, _c, mut _d) = tup; @@ -471,5 +510,14 @@ fn main() { run_test(|a| panic_after_init_temp(a)); run_test(|a| panic_after_init_by_loop(a)); + run_test(|a| bindings_after_at_dynamic_init_move(a, true)); + run_test(|a| bindings_after_at_dynamic_init_move(a, false)); + run_test(|a| bindings_after_at_dynamic_init_ref(a, true)); + run_test(|a| bindings_after_at_dynamic_init_ref(a, false)); + run_test(|a| bindings_after_at_dynamic_drop_move(a, true)); + run_test(|a| bindings_after_at_dynamic_drop_move(a, false)); + run_test(|a| bindings_after_at_dynamic_drop_ref(a, true)); + run_test(|a| bindings_after_at_dynamic_drop_ref(a, false)); + run_test_nopanic(|a| union1(a)); } diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr b/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr index 082d897c01dc1..82dec1fd4cf21 100644 --- a/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr +++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr @@ -4,7 +4,6 @@ error[E0658]: the `#[rustc_variance]` attribute is just used for rustc unit test LL | #[rustc_variance] | ^^^^^^^^^^^^^^^^^ | - = note: see issue #29642 for more information = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable error[E0658]: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable @@ -13,7 +12,6 @@ error[E0658]: the `#[rustc_error]` attribute is just used for rustc unit tests a LL | #[rustc_error] | ^^^^^^^^^^^^^^ | - = note: see issue #29642 for more information = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable error[E0658]: the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable niche optimizations in libcore and will never be stable @@ -22,7 +20,6 @@ error[E0658]: the `#[rustc_nonnull_optimization_guaranteed]` attribute is just u LL | #[rustc_nonnull_optimization_guaranteed] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #29642 for more information = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable error: aborting due to 3 previous errors diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr b/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr index 58f8b4e703513..1e039f17a0d11 100644 --- a/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr +++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr @@ -4,7 +4,6 @@ error[E0658]: attributes starting with `rustc` are reserved for use by the `rust LL | #[rustc::unknown] | ^^^^^ | - = note: see issue #29642 for more information = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable error: expected attribute, found macro `rustc::unknown` @@ -19,7 +18,6 @@ error[E0658]: attributes starting with `rustc` are reserved for use by the `rust LL | #[unknown::rustc] | ^^^^^ | - = note: see issue #29642 for more information = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable error: expected attribute, found macro `unknown::rustc` @@ -34,7 +32,6 @@ error[E0658]: attributes starting with `rustc` are reserved for use by the `rust LL | #[rustc_unknown] | ^^^^^^^^^^^^^ | - = note: see issue #29642 for more information = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable error: cannot find attribute `rustc_unknown` in this scope @@ -49,7 +46,6 @@ error[E0658]: the `#[rustc_dummy]` attribute is just used for rustc unit tests a LL | #[rustc_dummy] | ^^^^^^^^^^^^^^ | - = note: see issue #29642 for more information = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable error: aborting due to 7 previous errors diff --git a/src/test/ui/issues/issue-3763.rs b/src/test/ui/issues/issue-3763.rs index 5d17a30ab3624..3494df37fe7f1 100644 --- a/src/test/ui/issues/issue-3763.rs +++ b/src/test/ui/issues/issue-3763.rs @@ -1,3 +1,6 @@ +// compile-flags: -Zsave-analysis +// Also regression test for #69416 + mod my_mod { pub struct MyStruct { priv_field: isize diff --git a/src/test/ui/issues/issue-3763.stderr b/src/test/ui/issues/issue-3763.stderr index 50169286b1ceb..873f69d390e67 100644 --- a/src/test/ui/issues/issue-3763.stderr +++ b/src/test/ui/issues/issue-3763.stderr @@ -1,29 +1,29 @@ error[E0616]: field `priv_field` of struct `my_mod::MyStruct` is private - --> $DIR/issue-3763.rs:15:19 + --> $DIR/issue-3763.rs:18:19 | LL | let _woohoo = (&my_struct).priv_field; | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0616]: field `priv_field` of struct `my_mod::MyStruct` is private - --> $DIR/issue-3763.rs:18:19 + --> $DIR/issue-3763.rs:21:19 | LL | let _woohoo = (Box::new(my_struct)).priv_field; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0624]: method `happyfun` is private - --> $DIR/issue-3763.rs:21:18 + --> $DIR/issue-3763.rs:24:18 | LL | (&my_struct).happyfun(); | ^^^^^^^^ error[E0624]: method `happyfun` is private - --> $DIR/issue-3763.rs:23:27 + --> $DIR/issue-3763.rs:26:27 | LL | (Box::new(my_struct)).happyfun(); | ^^^^^^^^ error[E0616]: field `priv_field` of struct `my_mod::MyStruct` is private - --> $DIR/issue-3763.rs:24:16 + --> $DIR/issue-3763.rs:27:16 | LL | let nope = my_struct.priv_field; | ^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/methods/assign-to-method.rs b/src/test/ui/methods/assign-to-method.rs new file mode 100644 index 0000000000000..85beaee8df0a1 --- /dev/null +++ b/src/test/ui/methods/assign-to-method.rs @@ -0,0 +1,24 @@ +// compile-flags: -Zsave-analysis +// Also regression test for #69409 + +struct Cat { + meows : usize, + how_hungry : isize, +} + +impl Cat { + pub fn speak(&self) { self.meows += 1; } +} + +fn cat(in_x : usize, in_y : isize) -> Cat { + Cat { + meows: in_x, + how_hungry: in_y + } +} + +fn main() { + let nyan : Cat = cat(52, 99); + nyan.speak = || println!("meow"); //~ ERROR attempted to take value of method + nyan.speak += || println!("meow"); //~ ERROR attempted to take value of method +} diff --git a/src/test/ui/assign-to-method.stderr b/src/test/ui/methods/assign-to-method.stderr similarity index 65% rename from src/test/ui/assign-to-method.stderr rename to src/test/ui/methods/assign-to-method.stderr index feceadb67220b..c0dd529b6818f 100644 --- a/src/test/ui/assign-to-method.stderr +++ b/src/test/ui/methods/assign-to-method.stderr @@ -1,16 +1,16 @@ error[E0615]: attempted to take value of method `speak` on type `Cat` - --> $DIR/assign-to-method.rs:20:8 + --> $DIR/assign-to-method.rs:22:10 | -LL | nyan.speak = || println!("meow"); - | ^^^^^ +LL | nyan.speak = || println!("meow"); + | ^^^^^ | = help: methods are immutable and cannot be assigned to error[E0615]: attempted to take value of method `speak` on type `Cat` - --> $DIR/assign-to-method.rs:21:8 + --> $DIR/assign-to-method.rs:23:10 | -LL | nyan.speak += || println!("meow"); - | ^^^^^ +LL | nyan.speak += || println!("meow"); + | ^^^^^ | = help: methods are immutable and cannot be assigned to diff --git a/src/test/ui/on-unimplemented/feature-gate-on-unimplemented.stderr b/src/test/ui/on-unimplemented/feature-gate-on-unimplemented.stderr index 71baf92b2d409..a4b33963fb0b9 100644 --- a/src/test/ui/on-unimplemented/feature-gate-on-unimplemented.stderr +++ b/src/test/ui/on-unimplemented/feature-gate-on-unimplemented.stderr @@ -4,7 +4,6 @@ error[E0658]: this is an internal attribute that will never be stable LL | #[rustc_on_unimplemented = "test error `{Self}` with `{Bar}`"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #29642 for more information = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable error: aborting due to previous error diff --git a/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr b/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr index d5e029d668d47..1dabb7c975430 100644 --- a/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr +++ b/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr @@ -101,7 +101,7 @@ LL | if let Blah::A(_, x, y) | Blah::B(x, y) = Blah::A(1, 1, 2) { | | expected `usize`, found `isize` | first introduced with type `usize` here | - = note: in the same arm, a binding must have the same type in all alternatives + = note: a binding must have the same type in all alternatives error[E0308]: mismatched types --> $DIR/or-patterns-binding-type-mismatch.rs:38:47 @@ -112,7 +112,7 @@ LL | if let Some(Blah::A(_, x, y) | Blah::B(x, y)) = Some(Blah::A(1, 1, 2)) | | expected `usize`, found `isize` | first introduced with type `usize` here | - = note: in the same arm, a binding must have the same type in all alternatives + = note: a binding must have the same type in all alternatives error[E0308]: mismatched types --> $DIR/or-patterns-binding-type-mismatch.rs:42:22 @@ -123,7 +123,7 @@ LL | if let (x, y) | (y, x) = (0u8, 1u16) { | | expected `u16`, found `u8` | first introduced with type `u16` here | - = note: in the same arm, a binding must have the same type in all alternatives + = note: a binding must have the same type in all alternatives error[E0308]: mismatched types --> $DIR/or-patterns-binding-type-mismatch.rs:42:25 @@ -134,7 +134,7 @@ LL | if let (x, y) | (y, x) = (0u8, 1u16) { | | expected `u8`, found `u16` | first introduced with type `u8` here | - = note: in the same arm, a binding must have the same type in all alternatives + = note: a binding must have the same type in all alternatives error[E0308]: mismatched types --> $DIR/or-patterns-binding-type-mismatch.rs:47:44 @@ -147,7 +147,7 @@ LL | if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) LL | = Some((0u8, Some((1u16, 2u32)))) | ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>` | - = note: in the same arm, a binding must have the same type in all alternatives + = note: a binding must have the same type in all alternatives error[E0308]: mismatched types --> $DIR/or-patterns-binding-type-mismatch.rs:47:53 @@ -160,7 +160,7 @@ LL | if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) LL | = Some((0u8, Some((1u16, 2u32)))) | ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>` | - = note: in the same arm, a binding must have the same type in all alternatives + = note: a binding must have the same type in all alternatives error[E0308]: mismatched types --> $DIR/or-patterns-binding-type-mismatch.rs:47:62 @@ -173,7 +173,7 @@ LL | if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) LL | = Some((0u8, Some((1u16, 2u32)))) | ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>` | - = note: in the same arm, a binding must have the same type in all alternatives + = note: a binding must have the same type in all alternatives error[E0308]: mismatched types --> $DIR/or-patterns-binding-type-mismatch.rs:47:65 @@ -184,7 +184,7 @@ LL | if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) LL | = Some((0u8, Some((1u16, 2u32)))) | ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>` | - = note: in the same arm, a binding must have the same type in all alternatives + = note: a binding must have the same type in all alternatives error[E0308]: mismatched types --> $DIR/or-patterns-binding-type-mismatch.rs:55:39 diff --git a/src/test/ui/proc-macro/expand-to-unstable-2.stderr b/src/test/ui/proc-macro/expand-to-unstable-2.stderr index ff2e3af3777a1..19144b210a127 100644 --- a/src/test/ui/proc-macro/expand-to-unstable-2.stderr +++ b/src/test/ui/proc-macro/expand-to-unstable-2.stderr @@ -4,7 +4,6 @@ error[E0658]: attributes starting with `rustc` are reserved for use by the `rust LL | #[derive(Unstable)] | ^^^^^^^^ | - = note: see issue #29642 for more information = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/reserved/reserved-attr-on-macro.stderr b/src/test/ui/reserved/reserved-attr-on-macro.stderr index 2870cb57e9caf..c387bba0a1310 100644 --- a/src/test/ui/reserved/reserved-attr-on-macro.stderr +++ b/src/test/ui/reserved/reserved-attr-on-macro.stderr @@ -4,7 +4,6 @@ error[E0658]: attributes starting with `rustc` are reserved for use by the `rust LL | #[rustc_attribute_should_be_reserved] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #29642 for more information = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable error: cannot determine resolution for the macro `foo` diff --git a/src/test/ui/rust-2018/macro-use-warned-against.rs b/src/test/ui/rust-2018/macro-use-warned-against.rs index 6cd54aa68aedd..65400163ddd86 100644 --- a/src/test/ui/rust-2018/macro-use-warned-against.rs +++ b/src/test/ui/rust-2018/macro-use-warned-against.rs @@ -4,7 +4,7 @@ #![warn(macro_use_extern_crate, unused)] -#[macro_use] //~ WARN should be replaced at use sites with a `use` statement +#[macro_use] //~ WARN should be replaced at use sites with a `use` item extern crate macro_use_warned_against; #[macro_use] //~ WARN unused `#[macro_use]` extern crate macro_use_warned_against2; diff --git a/src/test/ui/rust-2018/macro-use-warned-against.stderr b/src/test/ui/rust-2018/macro-use-warned-against.stderr index 611b9d5dac9fd..ef00b865815c0 100644 --- a/src/test/ui/rust-2018/macro-use-warned-against.stderr +++ b/src/test/ui/rust-2018/macro-use-warned-against.stderr @@ -1,4 +1,4 @@ -warning: deprecated `#[macro_use]` directive used to import macros should be replaced at use sites with a `use` statement to import the macro instead +warning: deprecated `#[macro_use]` attribute used to import macros should be replaced at use sites with a `use` item to import the macro instead --> $DIR/macro-use-warned-against.rs:7:1 | LL | #[macro_use] diff --git a/src/test/ui/suggestions/attribute-typos.stderr b/src/test/ui/suggestions/attribute-typos.stderr index 10a119a628c70..c7c257ba5fe53 100644 --- a/src/test/ui/suggestions/attribute-typos.stderr +++ b/src/test/ui/suggestions/attribute-typos.stderr @@ -4,7 +4,6 @@ error[E0658]: attributes starting with `rustc` are reserved for use by the `rust LL | #[rustc_err] | ^^^^^^^^^ | - = note: see issue #29642 for more information = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable error: cannot find attribute `rustc_err` in this scope diff --git a/src/test/ui/tool-attributes/diagnostic_item.stderr b/src/test/ui/tool-attributes/diagnostic_item.stderr index d12834084e714..743e4b658c6b7 100644 --- a/src/test/ui/tool-attributes/diagnostic_item.stderr +++ b/src/test/ui/tool-attributes/diagnostic_item.stderr @@ -4,7 +4,6 @@ error[E0658]: diagnostic items compiler internal support for linting LL | #[rustc_diagnostic_item = "foomp"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #29642 for more information = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable error: aborting due to previous error diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index 12f93a87cb172..d9320e9147cff 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -63,20 +63,6 @@ pub struct CollectedFeatures { pub fn collect_lib_features(base_src_path: &Path) -> Features { let mut lib_features = Features::new(); - // This library feature is defined in the `compiler_builtins` crate, which - // has been moved out-of-tree. Now it can no longer be auto-discovered by - // `tidy`, because we need to filter out its (submodule) directory. Manually - // add it to the set of known library features so we can still generate docs. - lib_features.insert( - "compiler_builtins_lib".to_owned(), - Feature { - level: Status::Unstable, - since: None, - has_gate_test: false, - tracking_issue: None, - }, - ); - map_lib_features(base_src_path, &mut |res, _, _| { if let Ok((name, feature)) = res { lib_features.insert(name.to_owned(), feature); diff --git a/src/tools/tidy/src/unstable_book.rs b/src/tools/tidy/src/unstable_book.rs index 472d66459d724..7dfb6224d240a 100644 --- a/src/tools/tidy/src/unstable_book.rs +++ b/src/tools/tidy/src/unstable_book.rs @@ -1,4 +1,4 @@ -use crate::features::{CollectedFeatures, Feature, Features, Status}; +use crate::features::{CollectedFeatures, Features, Status}; use std::collections::BTreeSet; use std::fs; use std::path::{Path, PathBuf}; @@ -73,26 +73,12 @@ fn collect_unstable_book_lib_features_section_file_names(base_src_path: &Path) - pub fn check(path: &Path, features: CollectedFeatures, bad: &mut bool) { let lang_features = features.lang; - let mut lib_features = features + let lib_features = features .lib .into_iter() .filter(|&(ref name, _)| !lang_features.contains_key(name)) .collect::(); - // This library feature is defined in the `compiler_builtins` crate, which - // has been moved out-of-tree. Now it can no longer be auto-discovered by - // `tidy`, because we need to filter out its (submodule) directory. Manually - // add it to the set of known library features so we can still generate docs. - lib_features.insert( - "compiler_builtins_lib".to_owned(), - Feature { - level: Status::Unstable, - since: None, - has_gate_test: false, - tracking_issue: None, - }, - ); - // Library features let unstable_lib_feature_names = collect_unstable_feature_names(&lib_features); let unstable_book_lib_features_section_file_names =