about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-03-22 19:06:04 +0000
committerbors <bors@rust-lang.org>2022-03-22 19:06:04 +0000
commit5f37001055c29982f4c27ee9edd90449c8e07774 (patch)
treed8897f02157dc621ff21fa007dbd082e6aed28f0
parent64137f0b15b752d0c734661dc713bcd140858320 (diff)
parent2aca599325021f352f9bff06fa42daeb3c4bd4f8 (diff)
downloadrust-5f37001055c29982f4c27ee9edd90449c8e07774.tar.gz
rust-5f37001055c29982f4c27ee9edd90449c8e07774.zip
Auto merge of #95215 - Dylan-DPC:rollup-l9f9t7l, r=Dylan-DPC
Rollup of 5 pull requests

Successful merges:

 - #95188 ([`macro-metavar-expr`] Fix generated tokens hygiene)
 - #95196 (rename LocalState::Uninitialized to Unallocated)
 - #95197 (Suggest constraining param for unary ops when missing trait impl)
 - #95200 (Cancel a not emitted error after parsing const generic args)
 - #95207 (update Termination trait docs)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs22
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs14
-rw-r--r--compiler/rustc_mir_transform/src/const_prop.rs8
-rw-r--r--compiler/rustc_parse/src/parser/path.rs12
-rw-r--r--compiler/rustc_typeck/src/check/op.rs21
-rw-r--r--library/std/src/process.rs5
-rw-r--r--src/test/ui/const-generics/ice-const-generic-function-return-ty.rs5
-rw-r--r--src/test/ui/const-generics/ice-const-generic-function-return-ty.stderr8
-rw-r--r--src/test/ui/type/type-check/missing_trait_impl.rs6
-rw-r--r--src/test/ui/type/type-check/missing_trait_impl.stderr32
10 files changed, 107 insertions, 26 deletions
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index a8a57e6990f..d78c7a9fad9 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -177,11 +177,10 @@ pub struct LocalState<'tcx, Tag: Provenance = AllocId> {
 pub enum LocalValue<Tag: Provenance = AllocId> {
     /// This local is not currently alive, and cannot be used at all.
     Dead,
-    /// This local is alive but not yet initialized. It can be written to
-    /// but not read from or its address taken. Locals get initialized on
-    /// first write because for unsized locals, we do not know their size
-    /// before that.
-    Uninitialized,
+    /// This local is alive but not yet allocated. It cannot be read from or have its address taken,
+    /// and will be allocated on the first write. This is to support unsized locals, where we cannot
+    /// know their size in advance.
+    Unallocated,
     /// A normal, live local.
     /// Mostly for convenience, we re-use the `Operand` type here.
     /// This is an optimization over just always having a pointer here;
@@ -198,7 +197,7 @@ impl<'tcx, Tag: Provenance + 'static> LocalState<'tcx, Tag> {
     pub fn access(&self) -> InterpResult<'tcx, Operand<Tag>> {
         match self.value {
             LocalValue::Dead => throw_ub!(DeadLocal),
-            LocalValue::Uninitialized => {
+            LocalValue::Unallocated => {
                 bug!("The type checker should prevent reading from a never-written local")
             }
             LocalValue::Live(val) => Ok(val),
@@ -216,8 +215,7 @@ impl<'tcx, Tag: Provenance + 'static> LocalState<'tcx, Tag> {
         match self.value {
             LocalValue::Dead => throw_ub!(DeadLocal),
             LocalValue::Live(Operand::Indirect(mplace)) => Ok(Err(mplace)),
-            ref mut
-            local @ (LocalValue::Live(Operand::Immediate(_)) | LocalValue::Uninitialized) => {
+            ref mut local @ (LocalValue::Live(Operand::Immediate(_)) | LocalValue::Unallocated) => {
                 Ok(Ok(local))
             }
         }
@@ -752,8 +750,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             })?;
         }
 
-        // Locals are initially uninitialized.
-        let dummy = LocalState { value: LocalValue::Uninitialized, layout: Cell::new(None) };
+        // Locals are initially unallocated.
+        let dummy = LocalState { value: LocalValue::Unallocated, layout: Cell::new(None) };
         let mut locals = IndexVec::from_elem(dummy, &body.local_decls);
 
         // Now mark those locals as dead that we do not want to initialize
@@ -921,7 +919,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         assert!(local != mir::RETURN_PLACE, "Cannot make return place live");
         trace!("{:?} is now live", local);
 
-        let local_val = LocalValue::Uninitialized;
+        let local_val = LocalValue::Unallocated;
         // StorageLive expects the local to be dead, and marks it live.
         let old = mem::replace(&mut self.frame_mut().locals[local].value, local_val);
         if !matches!(old, LocalValue::Dead) {
@@ -1025,7 +1023,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> std::fmt::Debug
 
                 match self.ecx.stack()[frame].locals[local].value {
                     LocalValue::Dead => write!(fmt, " is dead")?,
-                    LocalValue::Uninitialized => write!(fmt, " is uninitialized")?,
+                    LocalValue::Unallocated => write!(fmt, " is unallocated")?,
                     LocalValue::Live(Operand::Indirect(mplace)) => {
                         write!(
                             fmt,
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index 5ec63739cf5..e8a1e61376f 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -257,7 +257,7 @@ pub(super) fn transcribe<'a>(
 
             // Replace meta-variable expressions with the result of their expansion.
             mbe::TokenTree::MetaVarExpr(sp, expr) => {
-                transcribe_metavar_expr(cx, expr, interp, &repeats, &mut result, &sp)?;
+                transcribe_metavar_expr(cx, expr, interp, &mut marker, &repeats, &mut result, &sp)?;
             }
 
             // If we are entering a new delimiter, we push its contents to the `stack` to be
@@ -513,17 +513,23 @@ fn transcribe_metavar_expr<'a>(
     cx: &ExtCtxt<'a>,
     expr: MetaVarExpr,
     interp: &FxHashMap<MacroRulesNormalizedIdent, NamedMatch>,
+    marker: &mut Marker,
     repeats: &[(usize, usize)],
     result: &mut Vec<TreeAndSpacing>,
     sp: &DelimSpan,
 ) -> PResult<'a, ()> {
+    let mut visited_span = || {
+        let mut span = sp.entire();
+        marker.visit_span(&mut span);
+        span
+    };
     match expr {
         MetaVarExpr::Count(original_ident, depth_opt) => {
             let matched = matched_from_ident(cx, original_ident, interp)?;
             let count = count_repetitions(cx, depth_opt, matched, &repeats, sp)?;
             let tt = TokenTree::token(
                 TokenKind::lit(token::Integer, sym::integer(count), None),
-                sp.entire(),
+                visited_span(),
             );
             result.push(tt.into());
         }
@@ -536,7 +542,7 @@ fn transcribe_metavar_expr<'a>(
                 result.push(
                     TokenTree::token(
                         TokenKind::lit(token::Integer, sym::integer(*index), None),
-                        sp.entire(),
+                        visited_span(),
                     )
                     .into(),
                 );
@@ -548,7 +554,7 @@ fn transcribe_metavar_expr<'a>(
                 result.push(
                     TokenTree::token(
                         TokenKind::lit(token::Integer, sym::integer(*length), None),
-                        sp.entire(),
+                        visited_span(),
                     )
                     .into(),
                 );
diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs
index 5ed33ab9fec..c4d15d4d187 100644
--- a/compiler/rustc_mir_transform/src/const_prop.rs
+++ b/compiler/rustc_mir_transform/src/const_prop.rs
@@ -244,8 +244,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
     ) -> InterpResult<'tcx, InterpOperand<Self::PointerTag>> {
         let l = &frame.locals[local];
 
-        if l.value == LocalValue::Uninitialized {
-            throw_machine_stop_str!("tried to access an uninitialized local")
+        if l.value == LocalValue::Unallocated {
+            throw_machine_stop_str!("tried to access an unallocated local")
         }
 
         l.access()
@@ -442,7 +442,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
     /// but not reading from them anymore.
     fn remove_const(ecx: &mut InterpCx<'mir, 'tcx, ConstPropMachine<'mir, 'tcx>>, local: Local) {
         ecx.frame_mut().locals[local] =
-            LocalState { value: LocalValue::Uninitialized, layout: Cell::new(None) };
+            LocalState { value: LocalValue::Unallocated, layout: Cell::new(None) };
     }
 
     fn lint_root(&self, source_info: SourceInfo) -> Option<HirId> {
@@ -1147,7 +1147,7 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> {
                     let frame = self.ecx.frame_mut();
                     frame.locals[local].value =
                         if let StatementKind::StorageLive(_) = statement.kind {
-                            LocalValue::Uninitialized
+                            LocalValue::Unallocated
                         } else {
                             LocalValue::Dead
                         };
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 17c57867cf9..07ce879de8f 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -630,10 +630,14 @@ impl<'a> Parser<'a> {
                 Ok(ty) => GenericArg::Type(ty),
                 Err(err) => {
                     if is_const_fn {
-                        if let Ok(expr) = (*snapshot).parse_expr_res(Restrictions::CONST_EXPR, None)
-                        {
-                            self.restore_snapshot(snapshot);
-                            return Ok(Some(self.dummy_const_arg_needs_braces(err, expr.span)));
+                        match (*snapshot).parse_expr_res(Restrictions::CONST_EXPR, None) {
+                            Ok(expr) => {
+                                self.restore_snapshot(snapshot);
+                                return Ok(Some(self.dummy_const_arg_needs_braces(err, expr.span)));
+                            }
+                            Err(err) => {
+                                err.cancel();
+                            }
                         }
                     }
                     // Try to recover from possible `const` arg without braces.
diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs
index af154e62a1e..e0dbe027aef 100644
--- a/compiler/rustc_typeck/src/check/op.rs
+++ b/compiler/rustc_typeck/src/check/op.rs
@@ -672,6 +672,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         ex.span,
                         format!("cannot apply unary operator `{}`", op.as_str()),
                     );
+                    let missing_trait = match op {
+                        hir::UnOp::Deref => unreachable!("check unary op `-` or `!` only"),
+                        hir::UnOp::Not => "std::ops::Not",
+                        hir::UnOp::Neg => "std::ops::Neg",
+                    };
+                    let mut visitor = TypeParamVisitor(vec![]);
+                    visitor.visit_ty(operand_ty);
+                    if let [ty] = &visitor.0[..] {
+                        if let ty::Param(p) = *operand_ty.kind() {
+                            suggest_constraining_param(
+                                self.tcx,
+                                self.body_id,
+                                &mut err,
+                                *ty,
+                                operand_ty,
+                                missing_trait,
+                                p,
+                                true,
+                            );
+                        }
+                    }
 
                     let sp = self.tcx.sess.source_map().start_point(ex.span);
                     if let Some(sp) =
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index d88ab625371..9824cce6c72 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -2030,6 +2030,11 @@ pub fn id() -> u32 {
 ///
 /// The default implementations are returning `libc::EXIT_SUCCESS` to indicate
 /// a successful execution. In case of a failure, `libc::EXIT_FAILURE` is returned.
+///
+/// Because different runtimes have different specifications on the return value
+/// of the `main` function, this trait is likely to be available only on
+/// standard library's runtime for convenience. Other runtimes are not required
+/// to provide similar functionality.
 #[cfg_attr(not(test), lang = "termination")]
 #[unstable(feature = "termination_trait_lib", issue = "43301")]
 #[rustc_on_unimplemented(
diff --git a/src/test/ui/const-generics/ice-const-generic-function-return-ty.rs b/src/test/ui/const-generics/ice-const-generic-function-return-ty.rs
new file mode 100644
index 00000000000..2bf628af8a7
--- /dev/null
+++ b/src/test/ui/const-generics/ice-const-generic-function-return-ty.rs
@@ -0,0 +1,5 @@
+// #95163
+fn return_ty() -> impl Into<<() as Reexported;
+//~^ ERROR expected one of `(`, `::`, `<`, or `>`, found `;`
+
+fn main() {}
diff --git a/src/test/ui/const-generics/ice-const-generic-function-return-ty.stderr b/src/test/ui/const-generics/ice-const-generic-function-return-ty.stderr
new file mode 100644
index 00000000000..a72f5800a07
--- /dev/null
+++ b/src/test/ui/const-generics/ice-const-generic-function-return-ty.stderr
@@ -0,0 +1,8 @@
+error: expected one of `(`, `::`, `<`, or `>`, found `;`
+  --> $DIR/ice-const-generic-function-return-ty.rs:2:46
+   |
+LL | fn return_ty() -> impl Into<<() as Reexported;
+   |                                              ^ expected one of `(`, `::`, `<`, or `>`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type/type-check/missing_trait_impl.rs b/src/test/ui/type/type-check/missing_trait_impl.rs
index f61ada3f63f..0e3e703a2f5 100644
--- a/src/test/ui/type/type-check/missing_trait_impl.rs
+++ b/src/test/ui/type/type-check/missing_trait_impl.rs
@@ -8,3 +8,9 @@ fn foo<T>(x: T, y: T) {
 fn bar<T>(x: T) {
     x += x; //~ ERROR binary assignment operation `+=` cannot be applied to type `T`
 }
+
+fn baz<T>(x: T) {
+    let y = -x; //~ ERROR cannot apply unary operator `-` to type `T`
+    let y = !x; //~ ERROR cannot apply unary operator `!` to type `T`
+    let y = *x; //~ ERROR type `T` cannot be dereferenced
+}
diff --git a/src/test/ui/type/type-check/missing_trait_impl.stderr b/src/test/ui/type/type-check/missing_trait_impl.stderr
index 45f2e845735..59b8692dd4d 100644
--- a/src/test/ui/type/type-check/missing_trait_impl.stderr
+++ b/src/test/ui/type/type-check/missing_trait_impl.stderr
@@ -24,7 +24,35 @@ help: consider restricting type parameter `T`
 LL | fn bar<T: std::ops::AddAssign>(x: T) {
    |         +++++++++++++++++++++
 
-error: aborting due to 2 previous errors
+error[E0600]: cannot apply unary operator `-` to type `T`
+  --> $DIR/missing_trait_impl.rs:13:13
+   |
+LL |     let y = -x;
+   |             ^^ cannot apply unary operator `-`
+   |
+help: consider restricting type parameter `T`
+   |
+LL | fn baz<T: std::ops::Neg<Output = T>>(x: T) {
+   |         +++++++++++++++++++++++++++
+
+error[E0600]: cannot apply unary operator `!` to type `T`
+  --> $DIR/missing_trait_impl.rs:14:13
+   |
+LL |     let y = !x;
+   |             ^^ cannot apply unary operator `!`
+   |
+help: consider restricting type parameter `T`
+   |
+LL | fn baz<T: std::ops::Not<Output = T>>(x: T) {
+   |         +++++++++++++++++++++++++++
+
+error[E0614]: type `T` cannot be dereferenced
+  --> $DIR/missing_trait_impl.rs:15:13
+   |
+LL |     let y = *x;
+   |             ^^
+
+error: aborting due to 5 previous errors
 
-Some errors have detailed explanations: E0368, E0369.
+Some errors have detailed explanations: E0368, E0369, E0600, E0614.
 For more information about an error, try `rustc --explain E0368`.