From 74e7313e0e425260da26a61e8ee8bbf80a65f014 Mon Sep 17 00:00:00 2001 From: Caio Date: Mon, 21 Mar 2022 19:45:55 -0300 Subject: [PATCH 1/7] Fix generated tokens hygiene --- compiler/rustc_expand/src/mbe/transcribe.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) 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, + marker: &mut Marker, repeats: &[(usize, usize)], result: &mut Vec, 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(), ); From b92a60586a3f121592bded64a1556fae0f69c302 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 21 Mar 2022 22:33:23 -0400 Subject: [PATCH 2/7] rename LocalState::Uninitialized to Unallocated --- .../src/interpret/eval_context.rs | 22 +++++++++---------- .../rustc_mir_transform/src/const_prop.rs | 8 +++---- 2 files changed, 14 insertions(+), 16 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 { /// 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> { 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_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> { 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 { @@ -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 }; From f28d8b13dffc372b099aa9a0e906b21962569076 Mon Sep 17 00:00:00 2001 From: Frank King Date: Tue, 22 Mar 2022 12:17:30 +0800 Subject: [PATCH 3/7] suggest constraining param for unary ops when missing trait impl --- compiler/rustc_typeck/src/check/op.rs | 21 ++++++++++++ .../ui/type/type-check/missing_trait_impl.rs | 6 ++++ .../type/type-check/missing_trait_impl.stderr | 32 +++++++++++++++++-- 3 files changed, 57 insertions(+), 2 deletions(-) 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/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(x: T, y: T) { fn bar(x: T) { x += x; //~ ERROR binary assignment operation `+=` cannot be applied to type `T` } + +fn baz(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(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>(x: T) { + | +++++++++++++++++++++++++++ -Some errors have detailed explanations: E0368, E0369. +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>(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, E0600, E0614. For more information about an error, try `rustc --explain E0368`. From 62ded071d588b92b394c4561d19d517d87074728 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Tue, 22 Mar 2022 16:06:56 +0900 Subject: [PATCH 4/7] cancel a not emitted error after parsing const generic args --- compiler/rustc_parse/src/parser/path.rs | 12 ++++++++---- .../ice-const-generic-function-return-ty.rs | 5 +++++ .../ice-const-generic-function-return-ty.stderr | 8 ++++++++ 3 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/const-generics/ice-const-generic-function-return-ty.rs create mode 100644 src/test/ui/const-generics/ice-const-generic-function-return-ty.stderr 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/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 + From 6e971a8bc28705018f735bc075cb79ddd495601f Mon Sep 17 00:00:00 2001 From: ZHANGWENTAI <2092913428@qq.com> Date: Tue, 22 Mar 2022 22:37:17 +0800 Subject: [PATCH 5/7] update Termination trait docs --- library/std/src/process.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/std/src/process.rs b/library/std/src/process.rs index d88ab625371..498be0aa262 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -2030,6 +2030,10 @@ 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. +/// +/// For the reason that different runtimes have diffrent specificatons on the +/// return value of the `main` function, this trait is likely to be available +/// only on standard library's runtime for type convenience. #[cfg_attr(not(test), lang = "termination")] #[unstable(feature = "termination_trait_lib", issue = "43301")] #[rustc_on_unimplemented( From 161b01a9acdfb0ccc5ec59f28996944780a6bbd4 Mon Sep 17 00:00:00 2001 From: ZHANGWENTAI <2092913428@qq.com> Date: Tue, 22 Mar 2022 23:10:00 +0800 Subject: [PATCH 6/7] fix the lint problem Signed-off-by: ZHANGWENTAI <2092913428@qq.com> --- library/std/src/process.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 498be0aa262..9d2e844187e 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -2032,7 +2032,7 @@ pub fn id() -> u32 { /// a successful execution. In case of a failure, `libc::EXIT_FAILURE` is returned. /// /// For the reason that different runtimes have diffrent specificatons on the -/// return value of the `main` function, this trait is likely to be available +/// return value of the `main` function, this trait is likely to be available /// only on standard library's runtime for type convenience. #[cfg_attr(not(test), lang = "termination")] #[unstable(feature = "termination_trait_lib", issue = "43301")] From 71e34231e089b19c6066efba3744673208ab4ffd Mon Sep 17 00:00:00 2001 From: ZHANGWENTAI <2092913428@qq.com> Date: Tue, 22 Mar 2022 23:33:08 +0800 Subject: [PATCH 7/7] add some fix Signed-off-by: ZHANGWENTAI <2092913428@qq.com> --- library/std/src/process.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 9d2e844187e..9824cce6c72 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -2031,9 +2031,10 @@ 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. /// -/// For the reason that different runtimes have diffrent specificatons on the -/// return value of the `main` function, this trait is likely to be available -/// only on standard library's runtime for type convenience. +/// 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(