about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-08-03 23:07:07 +0000
committerbors <bors@rust-lang.org>2021-08-03 23:07:07 +0000
commit2b8de6f21286d6dbd7dd692af7da7dc6937861d3 (patch)
tree7d2884267ffc5c435502cd9290bae1c3e5b55b78 /src
parenta6ece56152d8eb11e049e9fcce147b2859e12c92 (diff)
parent7c5588edf5e6b709f6ba6959bc50ffbc89468d3b (diff)
downloadrust-2b8de6f21286d6dbd7dd692af7da7dc6937861d3.tar.gz
rust-2b8de6f21286d6dbd7dd692af7da7dc6937861d3.zip
Auto merge of #87746 - JohnTitor:rollup-zaapqgl, r=JohnTitor
Rollup of 8 pull requests

Successful merges:

 - #81797 (Add `core::stream::from_iter`)
 - #87267 (Remove space after negative sign in Literal to_string)
 - #87663 (Rustdoc accessibility: use an icon for the [-]/[+] controls)
 - #87720 (don't use .into() to convert types to identical types (clippy::useless_conversion))
 - #87723 (Use .contains instead of manual reimplementation.)
 - #87729 (Remove the aarch64 `crypto` target_feature)
 - #87731 (Update cargo)
 - #87734 (Test dropping union fields more)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'src')
-rw-r--r--src/librustdoc/clean/mod.rs9
-rw-r--r--src/librustdoc/clean/types.rs2
-rw-r--r--src/librustdoc/formats/cache.rs2
-rw-r--r--src/librustdoc/html/format.rs4
-rw-r--r--src/librustdoc/html/render/cache.rs2
-rw-r--r--src/librustdoc/html/render/write_shared.rs40
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css66
-rw-r--r--src/librustdoc/html/static/css/themes/ayu.css5
-rw-r--r--src/librustdoc/html/static/css/themes/dark.css5
-rw-r--r--src/librustdoc/html/static/images/toggle-minus.svg1
-rw-r--r--src/librustdoc/html/static/images/toggle-plus.svg1
-rw-r--r--src/librustdoc/html/static_files.rs6
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs12
-rw-r--r--src/librustdoc/passes/collect_trait_impls.rs2
-rw-r--r--src/librustdoc/visit_ast.rs4
-rw-r--r--src/test/ui/proc-macro/auxiliary/api/parse.rs6
-rw-r--r--src/test/ui/union/union-drop.rs3
-rw-r--r--src/test/ui/union/union-drop.thirunsafeck.stderr22
-rw-r--r--src/test/ui/unsafe/union-assignop.mirunsafeck.stderr59
-rw-r--r--src/test/ui/unsafe/union-assignop.rs30
-rw-r--r--src/test/ui/unsafe/union-assignop.thirunsafeck.stderr59
m---------src/tools/cargo0
22 files changed, 286 insertions, 54 deletions
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 75ea30bb565..b3fc1e73f78 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -675,11 +675,10 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx
                         if let Some(((_, trait_did, name), rhs)) =
                             proj.as_ref().and_then(|(lhs, rhs)| Some((lhs.projection()?, rhs)))
                         {
-                            impl_trait_proj.entry(param_idx).or_default().push((
-                                trait_did.into(),
-                                name,
-                                rhs,
-                            ));
+                            impl_trait_proj
+                                .entry(param_idx)
+                                .or_default()
+                                .push((trait_did, name, rhs));
                         }
 
                         return None;
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 2460fa127f1..5c73d3de5b9 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -1614,7 +1614,7 @@ impl Type {
 impl Type {
     fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> {
         let t: PrimitiveType = match *self {
-            ResolvedPath { did, .. } => return Some(did.into()),
+            ResolvedPath { did, .. } => return Some(did),
             DynTrait(ref bounds, _) => return bounds[0].trait_.inner_def_id(cache),
             Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()),
             BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index 5ea2cdc2ad9..3d267ca5033 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -228,7 +228,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
                 if i.blanket_impl.is_none() {
                     self.cache
                         .implementors
-                        .entry(did.into())
+                        .entry(did)
                         .or_default()
                         .push(Impl { impl_item: item.clone() });
                 }
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 0291236abdf..8ab6aa775d2 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -688,7 +688,7 @@ crate fn anchor<'a, 'cx: 'a>(
     text: &'a str,
     cx: &'cx Context<'_>,
 ) -> impl fmt::Display + 'a {
-    let parts = href(did.into(), cx);
+    let parts = href(did, cx);
     display_fn(move |f| {
         if let Ok((url, short_ty, fqp)) = parts {
             write!(
@@ -921,7 +921,7 @@ fn fmt_type<'cx>(
                 //        everything comes in as a fully resolved QPath (hard to
                 //        look at).
                 box clean::ResolvedPath { did, .. } => {
-                    match href(did.into(), cx) {
+                    match href(did, cx) {
                         Ok((ref url, _, ref path)) if !f.alternate() => {
                             write!(
                                 f,
diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs
index 0734d2670cc..1c083522bea 100644
--- a/src/librustdoc/html/render/cache.rs
+++ b/src/librustdoc/html/render/cache.rs
@@ -42,7 +42,7 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt<
                 name: item.name.unwrap().to_string(),
                 path: fqp[..fqp.len() - 1].join("::"),
                 desc,
-                parent: Some(did.into()),
+                parent: Some(did),
                 parent_idx: None,
                 search_type: get_index_search_type(&item, tcx),
                 aliases: item.attrs.get_doc_aliases(),
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index 94a902a2d05..4411b7771ed 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -175,9 +175,45 @@ pub(super) fn write_shared(
         cx.write_shared(SharedResource::InvocationSpecific { basename: p }, content, &options.emit)
     };
 
+    fn add_background_image_to_css(
+        cx: &Context<'_>,
+        css: &mut String,
+        rule: &str,
+        file: &'static str,
+    ) {
+        css.push_str(&format!(
+            "{} {{ background-image: url({}); }}",
+            rule,
+            SharedResource::ToolchainSpecific { basename: file }
+                .path(cx)
+                .file_name()
+                .unwrap()
+                .to_str()
+                .unwrap()
+        ))
+    }
+
+    // Add all the static files. These may already exist, but we just
+    // overwrite them anyway to make sure that they're fresh and up-to-date.
+    let mut rustdoc_css = static_files::RUSTDOC_CSS.to_owned();
+    add_background_image_to_css(
+        cx,
+        &mut rustdoc_css,
+        "details.undocumented[open] > summary::before, \
+         details.rustdoc-toggle[open] > summary::before, \
+         details.rustdoc-toggle[open] > summary.hideme::before",
+        "toggle-minus.svg",
+    );
+    add_background_image_to_css(
+        cx,
+        &mut rustdoc_css,
+        "details.undocumented > summary::before, details.rustdoc-toggle > summary::before",
+        "toggle-plus.svg",
+    );
+    write_minify("rustdoc.css", &rustdoc_css)?;
+
     // Add all the static files. These may already exist, but we just
     // overwrite them anyway to make sure that they're fresh and up-to-date.
-    write_minify("rustdoc.css", static_files::RUSTDOC_CSS)?;
     write_minify("settings.css", static_files::SETTINGS_CSS)?;
     write_minify("noscript.css", static_files::NOSCRIPT_CSS)?;
 
@@ -217,6 +253,8 @@ pub(super) fn write_shared(
     write_toolchain("wheel.svg", static_files::WHEEL_SVG)?;
     write_toolchain("clipboard.svg", static_files::CLIPBOARD_SVG)?;
     write_toolchain("down-arrow.svg", static_files::DOWN_ARROW_SVG)?;
+    write_toolchain("toggle-minus.svg", static_files::TOGGLE_MINUS_PNG)?;
+    write_toolchain("toggle-plus.svg", static_files::TOGGLE_PLUS_PNG)?;
 
     let mut themes: Vec<&String> = themes.iter().collect();
     themes.sort();
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 91243a4086c..4e33eab5650 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -1508,11 +1508,35 @@ details.rustdoc-toggle > summary.hideme > span {
 }
 
 details.rustdoc-toggle > summary::before {
-	content: "[+]";
-	font-weight: 300;
-	font-size: 0.8em;
-	letter-spacing: 1px;
+	content: "";
 	cursor: pointer;
+	width: 17px;
+	height: max(17px, 1.1em);
+	background-repeat: no-repeat;
+	background-position: top left;
+	display: inline-block;
+	vertical-align: middle;
+	opacity: .5;
+}
+
+/* Screen readers see the text version at the end the line.
+	Visual readers see the icon at the start of the line, but small and transparent. */
+details.rustdoc-toggle > summary::after {
+	content: "Expand";
+	overflow: hidden;
+	width: 0;
+	height: 0;
+	position: absolute;
+}
+
+details.rustdoc-toggle > summary.hideme::after {
+	/* "hideme" toggles already have a description when they're contracted */
+	content: "";
+}
+
+details.rustdoc-toggle > summary:focus::before,
+details.rustdoc-toggle > summary:hover::before {
+	opacity: 1;
 }
 
 details.rustdoc-toggle.top-doc > summary,
@@ -1560,20 +1584,44 @@ details.rustdoc-toggle[open] > summary.hideme > span {
 	display: none;
 }
 
-details.rustdoc-toggle[open] > summary::before {
-	content: "[−]";
-	display: inline;
+details.rustdoc-toggle[open] > summary::before,
+details.rustdoc-toggle[open] > summary.hideme::before {
+	width: 17px;
+	height: max(17px, 1.1em);
+	background-repeat: no-repeat;
+	background-position: top left;
+	display: inline-block;
+	content: "";
+}
+
+details.rustdoc-toggle[open] > summary::after,
+details.rustdoc-toggle[open] > summary.hideme::after {
+	content: "Collapse";
 }
 
 details.undocumented > summary::before {
-	content: "[+] Show hidden undocumented items";
+	padding-left: 17px;
+	height: max(17px, 1.1em);
+	background-repeat: no-repeat;
+	background-position: top left;
+	content: "Show hidden undocumented items";
 	cursor: pointer;
 	font-size: 16px;
 	font-weight: 300;
+	opacity: .5;
+}
+
+details.undocumented > summary:focus::before,
+details.undocumented > summary:hover::before {
+	opacity: 1;
 }
 
 details.undocumented[open] > summary::before {
-	content: "[−] Hide undocumented items";
+	padding-left: 17px;
+	height: max(17px, 1.1em);
+	background-repeat: no-repeat
+	background-position: top left;
+	content: "Hide undocumented items";
 }
 
 /* Media Queries */
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
index df386fb66a3..849924ea550 100644
--- a/src/librustdoc/html/static/css/themes/ayu.css
+++ b/src/librustdoc/html/static/css/themes/ayu.css
@@ -229,6 +229,11 @@ details.undocumented > summary::before {
 	color: #999;
 }
 
+details.rustdoc-toggle > summary::before,
+details.undocumented > summary::before {
+	filter: invert(100%);
+}
+
 #crate-search {
 	color: #c5c5c5;
 	background-color: #141920;
diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css
index c8a5dbdc66a..c26122e4bff 100644
--- a/src/librustdoc/html/static/css/themes/dark.css
+++ b/src/librustdoc/html/static/css/themes/dark.css
@@ -194,6 +194,11 @@ details.undocumented > summary::before {
 	color: #999;
 }
 
+details.rustdoc-toggle > summary::before,
+details.undocumented > summary::before {
+	filter: invert(100%);
+}
+
 #crate-search {
 	color: #111;
 	background-color: #f0f0f0;
diff --git a/src/librustdoc/html/static/images/toggle-minus.svg b/src/librustdoc/html/static/images/toggle-minus.svg
new file mode 100644
index 00000000000..73154788a0e
--- /dev/null
+++ b/src/librustdoc/html/static/images/toggle-minus.svg
@@ -0,0 +1 @@
+<svg width="17" height="17" shape-rendering="crispEdges" stroke="#000" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M5 2.5H2.5v12H5m7-12h2.5v12H12M5 8.5h7"/></svg>
\ No newline at end of file
diff --git a/src/librustdoc/html/static/images/toggle-plus.svg b/src/librustdoc/html/static/images/toggle-plus.svg
new file mode 100644
index 00000000000..08b17033e16
--- /dev/null
+++ b/src/librustdoc/html/static/images/toggle-plus.svg
@@ -0,0 +1 @@
+<svg width="17" height="17" shape-rendering="crispEdges" stroke="#000" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M5 2.5H2.5v12H5m7-12h2.5v12H12M5 8.5h7M8.5 12V8.625v0V5"/></svg>
\ No newline at end of file
diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs
index 2ec7e66234d..6f3d08ea655 100644
--- a/src/librustdoc/html/static_files.rs
+++ b/src/librustdoc/html/static_files.rs
@@ -47,6 +47,12 @@ crate static CLIPBOARD_SVG: &[u8] = include_bytes!("static/images/clipboard.svg"
 /// The file contents of `down-arrow.svg`, the icon used for the crate choice combobox.
 crate static DOWN_ARROW_SVG: &[u8] = include_bytes!("static/images/down-arrow.svg");
 
+/// The file contents of `toggle-minus.svg`, the icon used for opened toggles.
+crate static TOGGLE_MINUS_PNG: &[u8] = include_bytes!("static/images/toggle-minus.svg");
+
+/// The file contents of `toggle-plus.svg`, the icon used for closed toggles.
+crate static TOGGLE_PLUS_PNG: &[u8] = include_bytes!("static/images/toggle-plus.svg");
+
 /// The contents of `COPYRIGHT.txt`, the license listing for files distributed with documentation
 /// output.
 crate static COPYRIGHT: &[u8] = include_bytes!("static/COPYRIGHT.txt");
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index ddb7b85d34a..b36be9541d2 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -293,7 +293,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
     ) -> Result<(Res, Option<String>), ErrorKind<'path>> {
         let tcx = self.cx.tcx;
         let no_res = || ResolutionFailure::NotResolved {
-            module_id: module_id.into(),
+            module_id: module_id,
             partial_res: None,
             unresolved: path_str.into(),
         };
@@ -521,7 +521,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                     // but the disambiguator logic expects the associated item.
                     // Store the kind in a side channel so that only the disambiguator logic looks at it.
                     if let Some((kind, id)) = side_channel {
-                        self.kind_side_channel.set(Some((kind, id.into())));
+                        self.kind_side_channel.set(Some((kind, id)));
                     }
                     Ok((res, Some(fragment)))
                 };
@@ -1268,7 +1268,7 @@ impl LinkCollector<'_, '_> {
                     // doesn't allow statements like `use str::trim;`, making this a (hopefully)
                     // valid omission. See https://github.com/rust-lang/rust/pull/80660#discussion_r551585677
                     // for discussion on the matter.
-                    verify(kind, id.into())?;
+                    verify(kind, id)?;
 
                     // FIXME: it would be nice to check that the feature gate was enabled in the original crate, not just ignore it altogether.
                     // However I'm not sure how to check that across crates.
@@ -1306,9 +1306,9 @@ impl LinkCollector<'_, '_> {
                 Some(ItemLink { link: ori_link.link, link_text, did: None, fragment })
             }
             Res::Def(kind, id) => {
-                verify(kind, id.into())?;
+                verify(kind, id)?;
                 let id = clean::register_res(self.cx, rustc_hir::def::Res::Def(kind, id));
-                Some(ItemLink { link: ori_link.link, link_text, did: Some(id.into()), fragment })
+                Some(ItemLink { link: ori_link.link, link_text, did: Some(id), fragment })
             }
         }
     }
@@ -1886,7 +1886,7 @@ fn resolution_failure(
                         name = start;
                         for ns in [TypeNS, ValueNS, MacroNS] {
                             if let Some(res) =
-                                collector.check_full_res(ns, &start, module_id.into(), &None)
+                                collector.check_full_res(ns, &start, module_id, &None)
                             {
                                 debug!("found partial_res={:?}", res);
                                 *partial_res = Some(res);
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
index 91c495a2bbc..eefe50caa34 100644
--- a/src/librustdoc/passes/collect_trait_impls.rs
+++ b/src/librustdoc/passes/collect_trait_impls.rs
@@ -45,7 +45,7 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
 
                 // FIXME(eddyb) is this `doc(hidden)` check needed?
                 if !cx.tcx.get_attrs(def_id).lists(sym::doc).has_word(sym::hidden) {
-                    let impls = get_auto_trait_and_blanket_impls(cx, def_id.into());
+                    let impls = get_auto_trait_and_blanket_impls(cx, def_id);
                     new_items.extend(impls.filter(|i| cx.inlined.insert(i.def_id)));
                 }
             });
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index d74b3b46272..e2891035535 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -192,7 +192,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                     } else {
                         // All items need to be handled here in case someone wishes to link
                         // to them with intra-doc links
-                        self.cx.cache.access_levels.map.insert(did.into(), AccessLevel::Public);
+                        self.cx.cache.access_levels.map.insert(did, AccessLevel::Public);
                     }
                 }
             }
@@ -204,7 +204,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             None => return false,
         };
 
-        let is_private = !self.cx.cache.access_levels.is_public(res_did.into());
+        let is_private = !self.cx.cache.access_levels.is_public(res_did);
         let is_hidden = inherits_doc_hidden(self.cx.tcx, res_hir_id);
 
         // Only inline if requested or if the item would otherwise be stripped.
diff --git a/src/test/ui/proc-macro/auxiliary/api/parse.rs b/src/test/ui/proc-macro/auxiliary/api/parse.rs
index a304c5e81a4..93551ebaf82 100644
--- a/src/test/ui/proc-macro/auxiliary/api/parse.rs
+++ b/src/test/ui/proc-macro/auxiliary/api/parse.rs
@@ -6,8 +6,8 @@ pub fn test() {
 }
 
 fn test_display_literal() {
-    assert_eq!(Literal::isize_unsuffixed(-10).to_string(), "- 10");
-    assert_eq!(Literal::isize_suffixed(-10).to_string(), "- 10isize");
+    assert_eq!(Literal::isize_unsuffixed(-10).to_string(), "-10");
+    assert_eq!(Literal::isize_suffixed(-10).to_string(), "-10isize");
 }
 
 fn test_parse_literal() {
@@ -18,7 +18,7 @@ fn test_parse_literal() {
     assert_eq!("b\"\"".parse::<Literal>().unwrap().to_string(), "b\"\"");
     assert_eq!("r##\"\"##".parse::<Literal>().unwrap().to_string(), "r##\"\"##");
     assert_eq!("10ulong".parse::<Literal>().unwrap().to_string(), "10ulong");
-    assert_eq!("-10ulong".parse::<Literal>().unwrap().to_string(), "- 10ulong");
+    assert_eq!("-10ulong".parse::<Literal>().unwrap().to_string(), "-10ulong");
 
     assert!("true".parse::<Literal>().is_err());
     assert!(".8".parse::<Literal>().is_err());
diff --git a/src/test/ui/union/union-drop.rs b/src/test/ui/union/union-drop.rs
index 9edf5827511..c3d7d41ca35 100644
--- a/src/test/ui/union/union-drop.rs
+++ b/src/test/ui/union/union-drop.rs
@@ -1,4 +1,7 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![allow(dead_code)]
 #![allow(unused_variables)]
 
diff --git a/src/test/ui/union/union-drop.thirunsafeck.stderr b/src/test/ui/union/union-drop.thirunsafeck.stderr
deleted file mode 100644
index 9766ae4e435..00000000000
--- a/src/test/ui/union/union-drop.thirunsafeck.stderr
+++ /dev/null
@@ -1,22 +0,0 @@
-warning: unnecessary `unsafe` block
-  --> $DIR/union-drop.rs:27:9
-   |
-LL |         unsafe { CHECK += 1; }
-   |         ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: `#[warn(unused_unsafe)]` on by default
-
-warning: unnecessary `unsafe` block
-  --> $DIR/union-drop.rs:33:9
-   |
-LL |         unsafe { CHECK += 1; }
-   |         ^^^^^^ unnecessary `unsafe` block
-
-warning: unnecessary `unsafe` block
-  --> $DIR/union-drop.rs:40:5
-   |
-LL |     unsafe {
-   |     ^^^^^^ unnecessary `unsafe` block
-
-warning: 3 warnings emitted
-
diff --git a/src/test/ui/unsafe/union-assignop.mirunsafeck.stderr b/src/test/ui/unsafe/union-assignop.mirunsafeck.stderr
new file mode 100644
index 00000000000..cd338ac9e3a
--- /dev/null
+++ b/src/test/ui/unsafe/union-assignop.mirunsafeck.stderr
@@ -0,0 +1,59 @@
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-assignop.rs:20:5
+   |
+LL |     foo.a += 5;
+   |     ^^^^^^^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-assignop.rs:21:5
+   |
+LL |     foo.b += Dropping;
+   |     ^^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: assignment to union field that might need dropping is unsafe and requires unsafe function or block
+  --> $DIR/union-assignop.rs:22:5
+   |
+LL |     foo.b = Dropping;
+   |     ^^^^^^^^^^^^^^^^ assignment to union field that might need dropping
+   |
+   = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-assignop.rs:23:5
+   |
+LL |     foo.a;
+   |     ^^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-assignop.rs:25:5
+   |
+LL |     foo.b;
+   |     ^^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-assignop.rs:27:13
+   |
+LL |     foo.b = foo.b;
+   |             ^^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: assignment to union field that might need dropping is unsafe and requires unsafe function or block
+  --> $DIR/union-assignop.rs:27:5
+   |
+LL |     foo.b = foo.b;
+   |     ^^^^^^^^^^^^^ assignment to union field that might need dropping
+   |
+   = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/union-assignop.rs b/src/test/ui/unsafe/union-assignop.rs
new file mode 100644
index 00000000000..c4be20aa567
--- /dev/null
+++ b/src/test/ui/unsafe/union-assignop.rs
@@ -0,0 +1,30 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
+#![feature(untagged_unions)]
+
+use std::ops::AddAssign;
+
+struct Dropping;
+impl AddAssign for Dropping {
+    fn add_assign(&mut self, _: Self) {}
+}
+
+union Foo {
+    a: u8, // non-dropping
+    b: Dropping, // treated as dropping
+}
+
+fn main() {
+    let mut foo = Foo { a: 42 };
+    foo.a += 5; //~ ERROR access to union field is unsafe
+    foo.b += Dropping; //~ ERROR access to union field is unsafe
+    foo.b = Dropping; //~ ERROR assignment to union field that might need dropping is unsafe
+    foo.a; //~ ERROR access to union field is unsafe
+    let foo = Foo { a: 42 };
+    foo.b; //~ ERROR access to union field is unsafe
+    let mut foo = Foo { a: 42 };
+    foo.b = foo.b;
+    //~^ ERROR access to union field is unsafe
+    //~| ERROR assignment to union field that might need dropping
+}
diff --git a/src/test/ui/unsafe/union-assignop.thirunsafeck.stderr b/src/test/ui/unsafe/union-assignop.thirunsafeck.stderr
new file mode 100644
index 00000000000..71de421a255
--- /dev/null
+++ b/src/test/ui/unsafe/union-assignop.thirunsafeck.stderr
@@ -0,0 +1,59 @@
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-assignop.rs:20:5
+   |
+LL |     foo.a += 5;
+   |     ^^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-assignop.rs:21:5
+   |
+LL |     foo.b += Dropping;
+   |     ^^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: assignment to union field that might need dropping is unsafe and requires unsafe function or block
+  --> $DIR/union-assignop.rs:22:5
+   |
+LL |     foo.b = Dropping;
+   |     ^^^^^^^^^^^^^^^^ assignment to union field that might need dropping
+   |
+   = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-assignop.rs:23:5
+   |
+LL |     foo.a;
+   |     ^^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-assignop.rs:25:5
+   |
+LL |     foo.b;
+   |     ^^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: assignment to union field that might need dropping is unsafe and requires unsafe function or block
+  --> $DIR/union-assignop.rs:27:5
+   |
+LL |     foo.b = foo.b;
+   |     ^^^^^^^^^^^^^ assignment to union field that might need dropping
+   |
+   = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-assignop.rs:27:13
+   |
+LL |     foo.b = foo.b;
+   |             ^^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject d21c22870e58499d6c31f1bef3bf1255eb02166
+Subproject cc17afbb0067b1f57d8882640f63b2168d5b762