about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-01-06 15:30:46 +0000
committerbors <bors@rust-lang.org>2022-01-06 15:30:46 +0000
commitcfa4ac66c194046f631ce076c75516ecfdeb77ee (patch)
tree10ace45fd5a86349c627f743747c097c5cdb7256 /src
parenta77cc64af491a31db224109a76b9b81cd26cd07c (diff)
parent26a90e4cd780175dd2d9dbf061eccd53eb9a2489 (diff)
downloadrust-cfa4ac66c194046f631ce076c75516ecfdeb77ee.tar.gz
rust-cfa4ac66c194046f631ce076c75516ecfdeb77ee.zip
Auto merge of #92609 - matthiaskrgr:rollup-ldp47ot, r=matthiaskrgr
Rollup of 7 pull requests

Successful merges:

 - #92058 (Make Run button visible on hover)
 - #92288 (Fix a pair of mistyped test cases in `std::net::ip`)
 - #92349 (Fix rustdoc::private_doc_tests lint for public re-exported items)
 - #92360 (Some cleanups around check_argument_types)
 - #92389 (Regression test for borrowck ICE #92015)
 - #92404 (Fix font size for [src] links in headers)
 - #92443 (Rustdoc: resolve associated traits for non-generic primitive types)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'src')
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css10
-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/css/themes/light.css5
-rw-r--r--src/librustdoc/passes/check_doc_test_visibility.rs2
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs92
-rw-r--r--src/test/rustdoc-gui/run-on-hover.goml7
-rw-r--r--src/test/rustdoc-gui/src-font-size.goml12
-rw-r--r--src/test/rustdoc-gui/src/test_docs/lib.rs1
-rw-r--r--src/test/rustdoc-ui/intra-doc/non-path-primitives.rs1
-rw-r--r--src/test/rustdoc-ui/intra-doc/non-path-primitives.stderr10
-rw-r--r--src/test/rustdoc-ui/private-public-item-doc-test.rs11
-rw-r--r--src/test/rustdoc-ui/private-public-item-doc-test.stderr18
-rw-r--r--src/test/rustdoc-ui/public-reexported-item-doc-test.rs16
-rw-r--r--src/test/rustdoc/intra-doc/prim-associated-traits.rs46
-rw-r--r--src/test/ui/borrowck/issue-92015.rs7
-rw-r--r--src/test/ui/borrowck/issue-92015.stderr11
-rw-r--r--src/test/ui/c-variadic/variadic-unreachable-arg-error.rs14
18 files changed, 228 insertions, 45 deletions
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index d82c65398b8..28cb8ae48e2 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -1080,8 +1080,11 @@ body.blur > :not(#help) {
 
 .impl-items .srclink, .impl .srclink, .methods .srclink {
 	/* Override header settings otherwise it's too bold */
-	font-size: 1.0625rem;
 	font-weight: normal;
+	font-size: 1rem;
+}
+.impl .srclink {
+	font-size: 1.0625rem;
 }
 
 .rightside {
@@ -1117,6 +1120,7 @@ pre.rust .question-mark {
 
 a.test-arrow {
 	display: inline-block;
+	visibility: hidden;
 	position: absolute;
 	padding: 5px 10px 5px 10px;
 	border-radius: 5px;
@@ -1125,10 +1129,12 @@ a.test-arrow {
 	right: 5px;
 	z-index: 1;
 }
+.example-wrap:hover .test-arrow {
+	visibility: visible;
+}
 a.test-arrow:hover{
 	text-decoration: none;
 }
-
 .section-header:hover a:before {
 	position: absolute;
 	left: -25px;
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
index 38040eeca52..6ed7845e83a 100644
--- a/src/librustdoc/html/static/css/themes/ayu.css
+++ b/src/librustdoc/html/static/css/themes/ayu.css
@@ -351,11 +351,8 @@ a.test-arrow:hover {
 	color: #999;
 }
 
-:target, :target > * {
-	background: rgba(255, 236, 164, 0.06);
-}
-
 :target {
+	background: rgba(255, 236, 164, 0.06);
 	border-right: 3px solid rgba(255, 180, 76, 0.85);
 }
 
diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css
index f4181e431c8..64b6eb6696b 100644
--- a/src/librustdoc/html/static/css/themes/dark.css
+++ b/src/librustdoc/html/static/css/themes/dark.css
@@ -295,11 +295,8 @@ a.test-arrow:hover{
 	color: #999;
 }
 
-:target, :target > * {
-	background-color: #494a3d;
-}
-
 :target {
+	background-color: #494a3d;
 	border-right: 3px solid #bb7410;
 }
 
diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css
index 176f63098a4..dbacc9f3073 100644
--- a/src/librustdoc/html/static/css/themes/light.css
+++ b/src/librustdoc/html/static/css/themes/light.css
@@ -284,11 +284,8 @@ a.test-arrow:hover{
 	color: #999;
 }
 
-:target, :target > * {
-	background: #FDFFD3;
-}
-
 :target {
+	background: #FDFFD3;
 	border-right: 3px solid #AD7C37;
 }
 
diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs
index b86ec8abefa..e8f8ff988c1 100644
--- a/src/librustdoc/passes/check_doc_test_visibility.rs
+++ b/src/librustdoc/passes/check_doc_test_visibility.rs
@@ -131,7 +131,7 @@ crate fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
             );
         }
     } else if tests.found_tests > 0
-        && !cx.cache.access_levels.is_public(item.def_id.expect_def_id())
+        && !cx.cache.access_levels.is_exported(item.def_id.expect_def_id())
     {
         cx.tcx.struct_span_lint_hir(
             crate::lint::PRIVATE_DOC_TESTS,
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 26ccdb1c87e..79530086282 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -13,7 +13,7 @@ use rustc_hir::def::{
     PerNS,
 };
 use rustc_hir::def_id::{CrateNum, DefId};
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{Ty, TyCtxt};
 use rustc_middle::{bug, span_bug, ty};
 use rustc_resolve::ParentScope;
 use rustc_session::lint::Lint;
@@ -618,6 +618,39 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
         })
     }
 
+    /// Convert a PrimitiveType to a Ty, where possible.
+    ///
+    /// This is used for resolving trait impls for primitives
+    fn primitive_type_to_ty(&mut self, prim: PrimitiveType) -> Option<Ty<'tcx>> {
+        use PrimitiveType::*;
+        let tcx = self.cx.tcx;
+
+        // FIXME: Only simple types are supported here, see if we can support
+        // other types such as Tuple, Array, Slice, etc.
+        // See https://github.com/rust-lang/rust/issues/90703#issuecomment-1004263455
+        Some(tcx.mk_ty(match prim {
+            Bool => ty::Bool,
+            Str => ty::Str,
+            Char => ty::Char,
+            Never => ty::Never,
+            I8 => ty::Int(ty::IntTy::I8),
+            I16 => ty::Int(ty::IntTy::I16),
+            I32 => ty::Int(ty::IntTy::I32),
+            I64 => ty::Int(ty::IntTy::I64),
+            I128 => ty::Int(ty::IntTy::I128),
+            Isize => ty::Int(ty::IntTy::Isize),
+            F32 => ty::Float(ty::FloatTy::F32),
+            F64 => ty::Float(ty::FloatTy::F64),
+            U8 => ty::Uint(ty::UintTy::U8),
+            U16 => ty::Uint(ty::UintTy::U16),
+            U32 => ty::Uint(ty::UintTy::U32),
+            U64 => ty::Uint(ty::UintTy::U64),
+            U128 => ty::Uint(ty::UintTy::U128),
+            Usize => ty::Uint(ty::UintTy::Usize),
+            _ => return None,
+        }))
+    }
+
     /// Returns:
     /// - None if no associated item was found
     /// - Some((_, _, Some(_))) if an item was found and should go through a side channel
@@ -632,7 +665,25 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
         let tcx = self.cx.tcx;
 
         match root_res {
-            Res::Primitive(prim) => self.resolve_primitive_associated_item(prim, ns, item_name),
+            Res::Primitive(prim) => {
+                self.resolve_primitive_associated_item(prim, ns, item_name).or_else(|| {
+                    let assoc_item = self
+                        .primitive_type_to_ty(prim)
+                        .map(|ty| {
+                            resolve_associated_trait_item(ty, module_id, item_name, ns, self.cx)
+                        })
+                        .flatten();
+
+                    assoc_item.map(|item| {
+                        let kind = item.kind;
+                        let fragment = UrlFragment::from_assoc_item(item_name, kind, false);
+                        // HACK(jynelson): `clean` expects the type, not the associated item
+                        // but the disambiguator logic expects the associated item.
+                        // Store the kind in a side channel so that only the disambiguator logic looks at it.
+                        (root_res, fragment, Some((kind.as_def_kind(), item.def_id)))
+                    })
+                })
+            }
             Res::Def(DefKind::TyAlias, did) => {
                 // Resolve the link on the type the alias points to.
                 // FIXME: if the associated item is defined directly on the type alias,
@@ -666,8 +717,13 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                     // To handle that properly resolve() would have to support
                     // something like [`ambi_fn`](<SomeStruct as SomeTrait>::ambi_fn)
                     .or_else(|| {
-                        let item =
-                            resolve_associated_trait_item(did, module_id, item_name, ns, self.cx);
+                        let item = resolve_associated_trait_item(
+                            tcx.type_of(did),
+                            module_id,
+                            item_name,
+                            ns,
+                            self.cx,
+                        );
                         debug!("got associated item {:?}", item);
                         item
                     });
@@ -767,12 +823,12 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
 /// Given `[std::io::Error::source]`, where `source` is unresolved, this would
 /// find `std::error::Error::source` and return
 /// `<io::Error as error::Error>::source`.
-fn resolve_associated_trait_item(
-    did: DefId,
+fn resolve_associated_trait_item<'a>(
+    ty: Ty<'a>,
     module: DefId,
     item_name: Symbol,
     ns: Namespace,
-    cx: &mut DocContext<'_>,
+    cx: &mut DocContext<'a>,
 ) -> Option<ty::AssocItem> {
     // FIXME: this should also consider blanket impls (`impl<T> X for T`). Unfortunately
     // `get_auto_trait_and_blanket_impls` is broken because the caching behavior is wrong. In the
@@ -780,7 +836,7 @@ fn resolve_associated_trait_item(
 
     // Next consider explicit impls: `impl MyTrait for MyType`
     // Give precedence to inherent impls.
-    let traits = traits_implemented_by(cx, did, module);
+    let traits = traits_implemented_by(cx, ty, module);
     debug!("considering traits {:?}", traits);
     let mut candidates = traits.iter().filter_map(|&trait_| {
         cx.tcx.associated_items(trait_).find_by_name_and_namespace(
@@ -799,7 +855,11 @@ fn resolve_associated_trait_item(
 ///
 /// NOTE: this cannot be a query because more traits could be available when more crates are compiled!
 /// So it is not stable to serialize cross-crate.
-fn traits_implemented_by(cx: &mut DocContext<'_>, type_: DefId, module: DefId) -> FxHashSet<DefId> {
+fn traits_implemented_by<'a>(
+    cx: &mut DocContext<'a>,
+    ty: Ty<'a>,
+    module: DefId,
+) -> FxHashSet<DefId> {
     let mut resolver = cx.resolver.borrow_mut();
     let in_scope_traits = cx.module_trait_cache.entry(module).or_insert_with(|| {
         resolver.access(|resolver| {
@@ -813,7 +873,6 @@ fn traits_implemented_by(cx: &mut DocContext<'_>, type_: DefId, module: DefId) -
     });
 
     let tcx = cx.tcx;
-    let ty = tcx.type_of(type_);
     let iter = in_scope_traits.iter().flat_map(|&trait_| {
         trace!("considering explicit impl for trait {:?}", trait_);
 
@@ -826,19 +885,10 @@ fn traits_implemented_by(cx: &mut DocContext<'_>, type_: DefId, module: DefId) -
                 "comparing type {} with kind {:?} against type {:?}",
                 impl_type,
                 impl_type.kind(),
-                type_
+                ty
             );
             // Fast path: if this is a primitive simple `==` will work
-            let saw_impl = impl_type == ty
-                || match impl_type.kind() {
-                    // Check if these are the same def_id
-                    ty::Adt(def, _) => {
-                        debug!("adt def_id: {:?}", def.did);
-                        def.did == type_
-                    }
-                    ty::Foreign(def_id) => *def_id == type_,
-                    _ => false,
-                };
+            let saw_impl = impl_type == ty;
 
             if saw_impl { Some(trait_) } else { None }
         })
diff --git a/src/test/rustdoc-gui/run-on-hover.goml b/src/test/rustdoc-gui/run-on-hover.goml
new file mode 100644
index 00000000000..b8efa8e302f
--- /dev/null
+++ b/src/test/rustdoc-gui/run-on-hover.goml
@@ -0,0 +1,7 @@
+// Example code blocks sometimes have a "Run" button to run them on the
+// Playground. That button is hidden until the user hovers over the code block.
+// This test checks that it is hidden, and that it shows on hover.
+goto: file://|DOC_PATH|/test_docs/fn.foo.html
+assert-css: (".test-arrow", {"visibility": "hidden"})
+move-cursor-to: ".example-wrap"
+assert-css: (".test-arrow", {"visibility": "visible"})
diff --git a/src/test/rustdoc-gui/src-font-size.goml b/src/test/rustdoc-gui/src-font-size.goml
new file mode 100644
index 00000000000..b0b2f122afd
--- /dev/null
+++ b/src/test/rustdoc-gui/src-font-size.goml
@@ -0,0 +1,12 @@
+// This test ensures that the "[src]" have the same font size as their headers
+// to avoid having some weird height difference in the background when the element
+// is selected.
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html
+show-text: true
+// Check the impl headers.
+assert-css: (".impl.has-srclink .srclink", {"font-size": "17px"}, ALL)
+// The ".6" part is because the font-size is actually "1.1em".
+assert-css: (".impl.has-srclink .code-header.in-band", {"font-size": "17.6px"}, ALL)
+// Check the impl items.
+assert-css: (".impl-items .has-srclink .srclink", {"font-size": "16px"}, ALL)
+assert-css: (".impl-items .has-srclink .code-header", {"font-size": "16px"}, ALL)
diff --git a/src/test/rustdoc-gui/src/test_docs/lib.rs b/src/test/rustdoc-gui/src/test_docs/lib.rs
index 9b37703dded..f75de949292 100644
--- a/src/test/rustdoc-gui/src/test_docs/lib.rs
+++ b/src/test/rustdoc-gui/src/test_docs/lib.rs
@@ -1,5 +1,6 @@
 //! The point of this crate is to be able to have enough different "kinds" of
 //! documentation generated so we can test each different features.
+#![doc(html_playground_url="https://play.rust-lang.org/")]
 
 #![crate_name = "test_docs"]
 #![feature(rustdoc_internals)]
diff --git a/src/test/rustdoc-ui/intra-doc/non-path-primitives.rs b/src/test/rustdoc-ui/intra-doc/non-path-primitives.rs
index 75159979e88..587cbad6848 100644
--- a/src/test/rustdoc-ui/intra-doc/non-path-primitives.rs
+++ b/src/test/rustdoc-ui/intra-doc/non-path-primitives.rs
@@ -28,7 +28,6 @@
 //! [unit::eq] //~ ERROR unresolved
 //! [tuple::eq] //~ ERROR unresolved
 //! [fn::eq] //~ ERROR unresolved
-//! [never::eq] //~ ERROR unresolved
 
 // FIXME(#78800): This breaks because it's a blanket impl
 // (I think? Might break for other reasons too.)
diff --git a/src/test/rustdoc-ui/intra-doc/non-path-primitives.stderr b/src/test/rustdoc-ui/intra-doc/non-path-primitives.stderr
index 610c8305605..4828a304463 100644
--- a/src/test/rustdoc-ui/intra-doc/non-path-primitives.stderr
+++ b/src/test/rustdoc-ui/intra-doc/non-path-primitives.stderr
@@ -53,17 +53,11 @@ error: unresolved link to `fn::eq`
 LL | //! [fn::eq]
    |      ^^^^^^ the builtin type `fn` has no associated item named `eq`
 
-error: unresolved link to `never::eq`
-  --> $DIR/non-path-primitives.rs:31:6
-   |
-LL | //! [never::eq]
-   |      ^^^^^^^^^ the builtin type `never` has no associated item named `eq`
-
 error: unresolved link to `reference::deref`
-  --> $DIR/non-path-primitives.rs:35:6
+  --> $DIR/non-path-primitives.rs:34:6
    |
 LL | //! [reference::deref]
    |      ^^^^^^^^^^^^^^^^ the builtin type `reference` has no associated item named `deref`
 
-error: aborting due to 9 previous errors
+error: aborting due to 8 previous errors
 
diff --git a/src/test/rustdoc-ui/private-public-item-doc-test.rs b/src/test/rustdoc-ui/private-public-item-doc-test.rs
new file mode 100644
index 00000000000..7cc62b38cc2
--- /dev/null
+++ b/src/test/rustdoc-ui/private-public-item-doc-test.rs
@@ -0,0 +1,11 @@
+#![deny(rustdoc::private_doc_tests)]
+
+mod foo {
+    /// private doc test
+    ///
+    /// ```
+    /// assert!(false);
+    /// ```
+    //~^^^^^ ERROR documentation test in private item
+    pub fn bar() {}
+}
diff --git a/src/test/rustdoc-ui/private-public-item-doc-test.stderr b/src/test/rustdoc-ui/private-public-item-doc-test.stderr
new file mode 100644
index 00000000000..f50dbd1844e
--- /dev/null
+++ b/src/test/rustdoc-ui/private-public-item-doc-test.stderr
@@ -0,0 +1,18 @@
+error: documentation test in private item
+  --> $DIR/private-public-item-doc-test.rs:4:5
+   |
+LL | /     /// private doc test
+LL | |     ///
+LL | |     /// ```
+LL | |     /// assert!(false);
+LL | |     /// ```
+   | |___________^
+   |
+note: the lint level is defined here
+  --> $DIR/private-public-item-doc-test.rs:1:9
+   |
+LL | #![deny(rustdoc::private_doc_tests)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/public-reexported-item-doc-test.rs b/src/test/rustdoc-ui/public-reexported-item-doc-test.rs
new file mode 100644
index 00000000000..b86a53305a1
--- /dev/null
+++ b/src/test/rustdoc-ui/public-reexported-item-doc-test.rs
@@ -0,0 +1,16 @@
+// check-pass
+
+#![deny(rustdoc::private_doc_tests)]
+
+pub fn foo() {}
+
+mod private {
+    /// re-exported doc test
+    ///
+    /// ```
+    /// assert!(true);
+    /// ```
+    pub fn bar() {}
+}
+
+pub use private::bar;
diff --git a/src/test/rustdoc/intra-doc/prim-associated-traits.rs b/src/test/rustdoc/intra-doc/prim-associated-traits.rs
new file mode 100644
index 00000000000..8639a24f7f3
--- /dev/null
+++ b/src/test/rustdoc/intra-doc/prim-associated-traits.rs
@@ -0,0 +1,46 @@
+#![feature(never_type)]
+use std::str::FromStr;
+
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.f64.html#method.from_str"]' 'f64::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.f32.html#method.from_str"]' 'f32::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.isize.html#method.from_str"]' 'isize::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.i8.html#method.from_str"]' 'i8::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.i16.html#method.from_str"]' 'i16::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.i32.html#method.from_str"]' 'i32::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.i64.html#method.from_str"]' 'i64::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.i128.html#method.from_str"]' 'i128::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.usize.html#method.from_str"]' 'usize::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.u8.html#method.from_str"]' 'u8::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.u16.html#method.from_str"]' 'u16::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.u32.html#method.from_str"]' 'u32::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.u64.html#method.from_str"]' 'u64::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.u128.html#method.from_str"]' 'u128::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.char.html#method.from_str"]' 'char::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.bool.html#method.from_str"]' 'bool::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.str.html#method.eq"]' 'str::eq()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.never.html#method.eq"]' 'never::eq()'
+/// [`f64::from_str()`] [`f32::from_str()`] [`isize::from_str()`] [`i8::from_str()`]
+/// [`i16::from_str()`] [`i32::from_str()`] [`i64::from_str()`] [`i128::from_str()`]
+/// [`u16::from_str()`] [`u32::from_str()`] [`u64::from_str()`] [`u128::from_str()`]
+/// [`usize::from_str()`] [`u8::from_str()`] [`char::from_str()`] [`bool::from_str()`]
+/// [`str::eq()`] [`never::eq()`]
+pub struct Number {
+    pub f_64: f64,
+    pub f_32: f32,
+    pub i_size: isize,
+    pub i_8: i8,
+    pub i_16: i16,
+    pub i_32: i32,
+    pub i_64: i64,
+    pub i_128: i128,
+    pub u_size: usize,
+    pub u_8: u8,
+    pub u_16: u16,
+    pub u_32: u32,
+    pub u_64: u64,
+    pub u_128: u128,
+    pub ch: char,
+    pub boolean: bool,
+    pub string: str,
+    pub n: !,
+}
diff --git a/src/test/ui/borrowck/issue-92015.rs b/src/test/ui/borrowck/issue-92015.rs
new file mode 100644
index 00000000000..16d651717ff
--- /dev/null
+++ b/src/test/ui/borrowck/issue-92015.rs
@@ -0,0 +1,7 @@
+// Regression test for #92105.
+// ICE when mutating immutable reference from last statement of a block.
+
+fn main() {
+    let foo = Some(&0).unwrap();
+    *foo = 1; //~ ERROR cannot assign
+}
diff --git a/src/test/ui/borrowck/issue-92015.stderr b/src/test/ui/borrowck/issue-92015.stderr
new file mode 100644
index 00000000000..32a65d3b5bb
--- /dev/null
+++ b/src/test/ui/borrowck/issue-92015.stderr
@@ -0,0 +1,11 @@
+error[E0594]: cannot assign to `*foo`, which is behind a `&` reference
+  --> $DIR/issue-92015.rs:6:5
+   |
+LL |     let foo = Some(&0).unwrap();
+   |         --- help: consider changing this to be a mutable reference: `&mut i32`
+LL |     *foo = 1;
+   |     ^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/c-variadic/variadic-unreachable-arg-error.rs b/src/test/ui/c-variadic/variadic-unreachable-arg-error.rs
new file mode 100644
index 00000000000..f60f6f3e808
--- /dev/null
+++ b/src/test/ui/c-variadic/variadic-unreachable-arg-error.rs
@@ -0,0 +1,14 @@
+// check-pass
+
+#![feature(c_variadic)]
+
+extern "C" {
+    fn foo(f: isize, x: u8, ...);
+}
+
+fn main() {
+    unsafe {
+        // FIXME: Ideally we could give an unreachable warning
+        foo(1, loop {}, 1usize);
+    }
+}