about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/doc/unstable-book/src/library-features/asm.md14
-rw-r--r--src/librustc_middle/mir/interpret/queries.rs23
-rw-r--r--src/librustc_mir/interpret/memory.rs20
-rw-r--r--src/librustc_mir/interpret/mod.rs2
-rw-r--r--src/librustc_typeck/check/place_op.rs37
-rw-r--r--src/test/ui/typeck/issue-74933.rs38
-rw-r--r--src/tools/tidy/src/style.rs2
7 files changed, 104 insertions, 32 deletions
diff --git a/src/doc/unstable-book/src/library-features/asm.md b/src/doc/unstable-book/src/library-features/asm.md
index c4c985dd134..28a5fe31fc4 100644
--- a/src/doc/unstable-book/src/library-features/asm.md
+++ b/src/doc/unstable-book/src/library-features/asm.md
@@ -18,7 +18,15 @@ It can be used to embed handwritten assembly in the assembly output generated by
 Generally this should not be necessary, but might be where the required performance or timing
 cannot be otherwise achieved. Accessing low level hardware primitives, e.g. in kernel code, may also demand this functionality.
 
-> **Note**: the examples here are given in x86/x86-64 assembly, but ARM, AArch64 and RISC-V are also supported.
+> **Note**: the examples here are given in x86/x86-64 assembly, but other architectures are also supported.
+
+Inline assembly is currently supported on the following architectures:
+- x86 and x86-64
+- ARM
+- AArch64
+- RISC-V
+- NVPTX
+- Hexagon
 
 ## Basic usage
 
@@ -606,6 +614,10 @@ Some registers cannot be used for input or output operands:
 | RISC-V | `gp`, `tp` | These registers are reserved and cannot be used as inputs or outputs. |
 | Hexagon | `lr` | This is the link register which cannot be used as an input or output. |
 
+In some cases LLVM will allocate a "reserved register" for `reg` operands even though this register cannot be explicitly specified. Assembly code making use of reserved registers should be careful since `reg` operands may alias with those registers. Reserved registers are:
+- The frame pointer on all architectures.
+- `r6` on ARM.
+
 ## Template modifiers
 
 The placeholders can be augmented by modifiers which are specified after the `:` in the curly braces. These modifiers do not affect register allocation, but change the way operands are formatted when inserted into the template string. Only one modifier is allowed per template placeholder.
diff --git a/src/librustc_middle/mir/interpret/queries.rs b/src/librustc_middle/mir/interpret/queries.rs
index 442e7f6b0f4..dcc1f8b1a4b 100644
--- a/src/librustc_middle/mir/interpret/queries.rs
+++ b/src/librustc_middle/mir/interpret/queries.rs
@@ -74,4 +74,27 @@ impl<'tcx> TyCtxt<'tcx> {
             self.const_eval_validated(inputs)
         }
     }
+
+    /// Evaluate a static's initializer, returning the allocation of the initializer's memory.
+    pub fn eval_static_initializer(
+        self,
+        def_id: DefId,
+    ) -> Result<&'tcx mir::Allocation, ErrorHandled> {
+        trace!("eval_static_initializer: Need to compute {:?}", def_id);
+        assert!(self.is_static(def_id));
+        let instance = ty::Instance::mono(self, def_id);
+        let gid = GlobalId { instance, promoted: None };
+        self.eval_to_allocation(gid, ty::ParamEnv::reveal_all())
+    }
+
+    /// Evaluate anything constant-like, returning the allocation of the final memory.
+    fn eval_to_allocation(
+        self,
+        gid: GlobalId<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> Result<&'tcx mir::Allocation, ErrorHandled> {
+        trace!("eval_to_allocation: Need to compute {:?}", gid);
+        let raw_const = self.const_eval_raw(param_env.and(gid))?;
+        Ok(self.global_alloc(raw_const.alloc_id).unwrap_memory())
+    }
 }
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index 705a547262f..49d97ff7cec 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -14,13 +14,12 @@ use std::ptr;
 
 use rustc_ast::ast::Mutability;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_hir::def_id::DefId;
-use rustc_middle::ty::{self, Instance, ParamEnv, TyCtxt};
+use rustc_middle::ty::{Instance, ParamEnv, TyCtxt};
 use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout};
 
 use super::{
-    AllocId, AllocMap, Allocation, AllocationExtra, CheckInAllocMsg, GlobalAlloc, GlobalId,
-    InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Scalar,
+    AllocId, AllocMap, Allocation, AllocationExtra, CheckInAllocMsg, GlobalAlloc, InterpResult,
+    Machine, MayLeak, Pointer, PointerArithmetic, Scalar,
 };
 use crate::util::pretty;
 
@@ -119,17 +118,6 @@ pub struct Memory<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
     pub tcx: TyCtxt<'tcx>,
 }
 
-/// Return the `tcx` allocation containing the initial value of the given static
-pub fn get_static(tcx: TyCtxt<'tcx>, def_id: DefId) -> InterpResult<'tcx, &'tcx Allocation> {
-    trace!("get_static: Need to compute {:?}", def_id);
-    let instance = Instance::mono(tcx, def_id);
-    let gid = GlobalId { instance, promoted: None };
-    // Use the raw query here to break validation cycles. Later uses of the static
-    // will call the full query anyway.
-    let raw_const = tcx.const_eval_raw(ty::ParamEnv::reveal_all().and(gid))?;
-    Ok(tcx.global_alloc(raw_const.alloc_id).unwrap_memory())
-}
-
 impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for Memory<'mir, 'tcx, M> {
     #[inline]
     fn data_layout(&self) -> &TargetDataLayout {
@@ -489,7 +477,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
                     throw_unsup!(ReadExternStatic(def_id));
                 }
 
-                (get_static(tcx, def_id)?, Some(def_id))
+                (tcx.eval_static_initializer(def_id)?, Some(def_id))
             }
         };
         M::before_access_global(memory_extra, id, alloc, def_id, is_write)?;
diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs
index 5218b03d65e..a931b0bbe97 100644
--- a/src/librustc_mir/interpret/mod.rs
+++ b/src/librustc_mir/interpret/mod.rs
@@ -21,7 +21,7 @@ pub use rustc_middle::mir::interpret::*; // have all the `interpret` symbols in
 pub use self::eval_context::{Frame, FrameInfo, InterpCx, LocalState, LocalValue, StackPopCleanup};
 pub use self::intern::{intern_const_alloc_recursive, InternKind};
 pub use self::machine::{compile_time_machine, AllocMap, Machine, MayLeak, StackPopJump};
-pub use self::memory::{get_static, AllocCheck, FnVal, Memory, MemoryKind};
+pub use self::memory::{AllocCheck, FnVal, Memory, MemoryKind};
 pub use self::operand::{ImmTy, Immediate, OpTy, Operand};
 pub use self::place::{MPlaceTy, MemPlace, MemPlaceMeta, Place, PlaceTy};
 pub use self::validity::RefTracking;
diff --git a/src/librustc_typeck/check/place_op.rs b/src/librustc_typeck/check/place_op.rs
index 84f34c0039a..4bef9aecd2e 100644
--- a/src/librustc_typeck/check/place_op.rs
+++ b/src/librustc_typeck/check/place_op.rs
@@ -9,6 +9,7 @@ use rustc_middle::ty::{self, Ty};
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::Span;
 use rustc_trait_selection::autoderef::Autoderef;
+use std::slice;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Type-check `*oprnd_expr` with `oprnd_expr` type-checked already.
@@ -243,19 +244,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
 
             match expr.kind {
-                hir::ExprKind::Index(ref base_expr, ref index_expr) => {
-                    // We need to get the final type in case dereferences were needed for the trait
-                    // to apply (#72002).
-                    let index_expr_ty = self.typeck_results.borrow().expr_ty_adjusted(index_expr);
-                    self.convert_place_op_to_mutable(
-                        PlaceOp::Index,
-                        expr,
-                        base_expr,
-                        &[index_expr_ty],
-                    );
+                hir::ExprKind::Index(ref base_expr, ..) => {
+                    self.convert_place_op_to_mutable(PlaceOp::Index, expr, base_expr);
                 }
                 hir::ExprKind::Unary(hir::UnOp::UnDeref, ref base_expr) => {
-                    self.convert_place_op_to_mutable(PlaceOp::Deref, expr, base_expr, &[]);
+                    self.convert_place_op_to_mutable(PlaceOp::Deref, expr, base_expr);
                 }
                 _ => {}
             }
@@ -267,9 +260,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         op: PlaceOp,
         expr: &hir::Expr<'_>,
         base_expr: &hir::Expr<'_>,
-        arg_tys: &[Ty<'tcx>],
     ) {
-        debug!("convert_place_op_to_mutable({:?}, {:?}, {:?}, {:?})", op, expr, base_expr, arg_tys);
+        debug!("convert_place_op_to_mutable({:?}, {:?}, {:?})", op, expr, base_expr);
         if !self.typeck_results.borrow().is_method_call(expr) {
             debug!("convert_place_op_to_mutable - builtin, nothing to do");
             return;
@@ -284,6 +276,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             .expect("place op takes something that is not a ref")
             .ty;
 
+        let arg_ty = match op {
+            PlaceOp::Deref => None,
+            PlaceOp::Index => {
+                // We would need to recover the `T` used when we resolve `<_ as Index<T>>::index`
+                // in try_index_step. This is the subst at index 1.
+                //
+                // Note: we should *not* use `expr_ty` of index_expr here because autoderef
+                // during coercions can cause type of index_expr to differ from `T` (#72002).
+                // We also could not use `expr_ty_adjusted` of index_expr because reborrowing
+                // during coercions can also cause type of index_expr to differ from `T`,
+                // which can potentially cause regionck failure (#74933).
+                Some(self.typeck_results.borrow().node_substs(expr.hir_id).type_at(1))
+            }
+        };
+        let arg_tys = match arg_ty {
+            None => &[],
+            Some(ref ty) => slice::from_ref(ty),
+        };
+
         let method = self.try_mutable_overloaded_place_op(expr.span, base_ty, arg_tys, op);
         let method = match method {
             Some(ok) => self.register_infer_ok_obligations(ok),
diff --git a/src/test/ui/typeck/issue-74933.rs b/src/test/ui/typeck/issue-74933.rs
new file mode 100644
index 00000000000..4b6c173b8ce
--- /dev/null
+++ b/src/test/ui/typeck/issue-74933.rs
@@ -0,0 +1,38 @@
+// check-pass
+//
+// rust-lang/rust#74933: Lifetime error when indexing with borrowed index
+
+use std::ops::{Index, IndexMut};
+
+struct S(V);
+struct K<'a>(&'a ());
+struct V;
+
+impl<'a> Index<&'a K<'a>> for S {
+    type Output = V;
+
+    fn index(&self, _: &'a K<'a>) -> &V {
+        &self.0
+    }
+}
+
+impl<'a> IndexMut<&'a K<'a>> for S {
+    fn index_mut(&mut self, _: &'a K<'a>) -> &mut V {
+        &mut self.0
+    }
+}
+
+impl V {
+    fn foo(&mut self) {}
+}
+
+fn test(s: &mut S, k: &K<'_>) {
+    s[k] = V;
+    s[k].foo();
+}
+
+fn main() {
+    let mut s = S(V);
+    let k = K(&());
+    test(&mut s, &k);
+}
diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs
index 9c27a8a6f88..bce3cf06b07 100644
--- a/src/tools/tidy/src/style.rs
+++ b/src/tools/tidy/src/style.rs
@@ -263,7 +263,7 @@ pub fn check(path: &Path, bad: &mut bool) {
                     suppressible_tidy_err!(err, skip_undocumented_unsafe, "undocumented unsafe");
                 }
             }
-            if line.contains("// SAFETY: ") || line.contains("// Safety: ") {
+            if line.contains("// SAFETY:") || line.contains("// Safety:") {
                 last_safety_comment = true;
             } else if line.trim().starts_with("//") || line.trim().is_empty() {
                 // keep previous value