From f77b602a78f7df7080801c25964cad3f2b07e3ab Mon Sep 17 00:00:00 2001 From: Andrew Xu Date: Sat, 20 Apr 2019 15:45:47 +0800 Subject: [PATCH 001/212] Fix broken link in rustc_plugin doc --- src/librustc_plugin/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustc_plugin/lib.rs b/src/librustc_plugin/lib.rs index 351ba7f04d3b1..74324312e8b4e 100644 --- a/src/librustc_plugin/lib.rs +++ b/src/librustc_plugin/lib.rs @@ -47,8 +47,9 @@ //! #![plugin(myplugin)] //! ``` //! -//! See the [`plugin` feature](../unstable-book/language-features/plugin.html) of -//! the Unstable Book for more examples. +//! See the [`plugin` +//! feature](https://doc.rust-lang.org/nightly/unstable-book/language-features/plugin.html) +//! of the Unstable Book for more examples. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] From d9ea132b7322cebd595598a0639cf6018816d454 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Mon, 22 Apr 2019 18:20:19 +0100 Subject: [PATCH 002/212] Explain error when yielding a reference to a local variable --- .../borrow_check/error_reporting.rs | 34 ++++++--- .../borrow_check/nll/explain_borrow/mod.rs | 4 ++ .../error_reporting/region_name.rs | 71 +++++++++++++++++-- src/librustc_mir/util/borrowck_errors.rs | 6 +- src/test/ui/nll/issue-55850.rs | 2 +- src/test/ui/nll/issue-55850.stderr | 16 ++--- 6 files changed, 107 insertions(+), 26 deletions(-) diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 3ab0996d3a17f..956e8c5627278 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -826,18 +826,21 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let borrow_span = borrow_spans.var_or_use(); if let BorrowExplanation::MustBeValidFor { - category: ConstraintCategory::Return, + category, span, ref opt_place_desc, from_closure: false, .. } = explanation { - return self.report_cannot_return_reference_to_local( + if let Some(diag) = self.try_report_cannot_return_reference_to_local( borrow, borrow_span, span, + category, opt_place_desc.as_ref(), - ); + ) { + return diag; + } } let mut err = self.infcx.tcx.path_does_not_live_long_enough( @@ -1015,17 +1018,20 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ); if let BorrowExplanation::MustBeValidFor { - category: ConstraintCategory::Return, + category, span, from_closure: false, .. } = explanation { - return self.report_cannot_return_reference_to_local( + if let Some(diag) = self.try_report_cannot_return_reference_to_local( borrow, proper_span, span, + category, None, - ); + ) { + return diag; + } } let tcx = self.infcx.tcx; @@ -1064,15 +1070,22 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { err } - fn report_cannot_return_reference_to_local( + fn try_report_cannot_return_reference_to_local( &self, borrow: &BorrowData<'tcx>, borrow_span: Span, return_span: Span, + category: ConstraintCategory, opt_place_desc: Option<&String>, - ) -> DiagnosticBuilder<'cx> { + ) -> Option> { let tcx = self.infcx.tcx; + let return_kind = match category { + ConstraintCategory::Return => "return", + ConstraintCategory::Yield => "yield", + _ => return None, + }; + // FIXME use a better heuristic than Spans let reference_desc = if return_span == self.mir.source_info(borrow.reserve_location).span { "reference to" @@ -1110,7 +1123,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let local = if let Place::Base(PlaceBase::Local(local)) = *root_place { local } else { - bug!("report_cannot_return_reference_to_local: not a local") + bug!("try_report_cannot_return_reference_to_local: not a local") }; match self.mir.local_kind(local) { LocalKind::ReturnPointer | LocalKind::Temp => { @@ -1131,6 +1144,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let mut err = tcx.cannot_return_reference_to_local( return_span, + return_kind, reference_desc, &place_desc, Origin::Mir, @@ -1140,7 +1154,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { err.span_label(borrow_span, note); } - err + Some(err) } fn report_escaping_closure_capture( diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index 5ad54080c5a61..5b1c64039bee3 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -313,9 +313,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { opt_place_desc, } } else { + debug!("explain_why_borrow_contains_point: \ + Could not generate a region name"); BorrowExplanation::Unexplained } } else { + debug!("explain_why_borrow_contains_point: \ + Could not generate an error region vid"); BorrowExplanation::Unexplained } } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs index 362214d325712..e72d4c9e3d570 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs @@ -32,6 +32,7 @@ crate enum RegionNameSource { MatchedAdtAndSegment(Span), AnonRegionFromUpvar(Span, String), AnonRegionFromOutput(Span, String, String), + AnonRegionFromYieldTy(Span, String), } impl RegionName { @@ -46,7 +47,8 @@ impl RegionName { RegionNameSource::MatchedHirTy(..) | RegionNameSource::MatchedAdtAndSegment(..) | RegionNameSource::AnonRegionFromUpvar(..) | - RegionNameSource::AnonRegionFromOutput(..) => false, + RegionNameSource::AnonRegionFromOutput(..) | + RegionNameSource::AnonRegionFromYieldTy(..) => false, } } @@ -103,6 +105,12 @@ impl RegionName { format!("return type{} is {}", mir_description, type_name), ); }, + RegionNameSource::AnonRegionFromYieldTy(span, type_name) => { + diag.span_label( + *span, + format!("yield type is {}", type_name), + ); + } RegionNameSource::Static => {}, } } @@ -167,6 +175,11 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.give_name_if_anonymous_region_appears_in_output( infcx, mir, mir_def_id, fr, counter, ) + }) + .or_else(|| { + self.give_name_if_anonymous_region_appears_in_yield_ty( + infcx, mir, mir_def_id, fr, counter, + ) }); debug!("give_region_a_name: gave name {:?}", value); @@ -673,10 +686,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { "give_name_if_anonymous_region_appears_in_output: return_ty = {:?}", return_ty ); - if !infcx - .tcx - .any_free_region_meets(&return_ty, |r| r.to_region_vid() == fr) - { + if !tcx.any_free_region_meets(&return_ty, |r| r.to_region_vid() == fr) { return None; } @@ -721,6 +731,57 @@ impl<'tcx> RegionInferenceContext<'tcx> { }) } + fn give_name_if_anonymous_region_appears_in_yield_ty( + &self, + infcx: &InferCtxt<'_, '_, 'tcx>, + mir: &Mir<'tcx>, + mir_def_id: DefId, + fr: RegionVid, + counter: &mut usize, + ) -> Option { + // Note: generators from `async fn` yield `()`, so we don't have to + // worry about them here. + let yield_ty = self.universal_regions.yield_ty?; + debug!( + "give_name_if_anonymous_region_appears_in_yield_ty: yield_ty = {:?}", + yield_ty, + ); + + let tcx = infcx.tcx; + + if !tcx.any_free_region_meets(&yield_ty, |r| r.to_region_vid() == fr) { + return None; + } + + let mut highlight = RegionHighlightMode::default(); + highlight.highlighting_region_vid(fr, *counter); + let type_name = infcx.extract_type_name(&yield_ty, Some(highlight)); + + let mir_node_id = tcx.hir().as_local_node_id(mir_def_id).expect("non-local mir"); + + let yield_span = match tcx.hir().get(mir_node_id) { + hir::Node::Expr(hir::Expr { + node: hir::ExprKind::Closure(_, _, _, span, _), + .. + }) => ( + tcx.sess.source_map().end_point(*span) + ), + _ => mir.span, + }; + + debug!( + "give_name_if_anonymous_region_appears_in_yield_ty: \ + type_name = {:?}, yield_span = {:?}", + yield_span, + type_name, + ); + + Some(RegionName { + name: self.synthesize_region_name(counter), + source: RegionNameSource::AnonRegionFromYieldTy(yield_span, type_name), + }) + } + /// Creates a synthetic region named `'1`, incrementing the /// counter. fn synthesize_region_name(&self, counter: &mut usize) -> InternedString { diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs index e334e27cc8556..0cbe39ab6d434 100644 --- a/src/librustc_mir/util/borrowck_errors.rs +++ b/src/librustc_mir/util/borrowck_errors.rs @@ -650,6 +650,7 @@ pub trait BorrowckErrors<'cx>: Sized + Copy { fn cannot_return_reference_to_local( self, span: Span, + return_kind: &str, reference_desc: &str, path_desc: &str, o: Origin, @@ -658,7 +659,8 @@ pub trait BorrowckErrors<'cx>: Sized + Copy { self, span, E0515, - "cannot return {REFERENCE} {LOCAL}{OGN}", + "cannot {RETURN} {REFERENCE} {LOCAL}{OGN}", + RETURN=return_kind, REFERENCE=reference_desc, LOCAL=path_desc, OGN = o @@ -666,7 +668,7 @@ pub trait BorrowckErrors<'cx>: Sized + Copy { err.span_label( span, - format!("returns a {} data owned by the current function", reference_desc), + format!("{}s a {} data owned by the current function", return_kind, reference_desc), ); self.cancel_if_wrong_origin(err, o) diff --git a/src/test/ui/nll/issue-55850.rs b/src/test/ui/nll/issue-55850.rs index 8a016bf87795b..a8f7299f89937 100644 --- a/src/test/ui/nll/issue-55850.rs +++ b/src/test/ui/nll/issue-55850.rs @@ -25,7 +25,7 @@ where fn bug<'a>() -> impl Iterator { GenIter(move || { let mut s = String::new(); - yield &s[..] //~ ERROR `s` does not live long enough [E0597] + yield &s[..] //~ ERROR cannot yield value referencing local variable `s` [E0515] //~| ERROR borrow may still be in use when generator yields }) } diff --git a/src/test/ui/nll/issue-55850.stderr b/src/test/ui/nll/issue-55850.stderr index 66c2995efc880..86a8cdc42ff9f 100644 --- a/src/test/ui/nll/issue-55850.stderr +++ b/src/test/ui/nll/issue-55850.stderr @@ -1,11 +1,11 @@ -error[E0597]: `s` does not live long enough - --> $DIR/issue-55850.rs:28:16 +error[E0515]: cannot yield value referencing local variable `s` + --> $DIR/issue-55850.rs:28:9 | LL | yield &s[..] - | ^ borrowed value does not live long enough -LL | -LL | }) - | - `s` dropped here while still borrowed + | ^^^^^^^-^^^^ + | | | + | | `s` is borrowed here + | yields a value referencing data owned by the current function error[E0626]: borrow may still be in use when generator yields --> $DIR/issue-55850.rs:28:16 @@ -15,5 +15,5 @@ LL | yield &s[..] error: aborting due to 2 previous errors -Some errors have detailed explanations: E0597, E0626. -For more information about an error, try `rustc --explain E0597`. +Some errors have detailed explanations: E0515, E0626. +For more information about an error, try `rustc --explain E0515`. From 4cb6d1c523ce375388622477e8020117a89d0c1d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 23 Apr 2019 17:51:10 +0200 Subject: [PATCH 003/212] deny -> warn --- src/libcore/tests/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 2e4a8a15d2088..f168458bff1d2 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -32,7 +32,7 @@ #![feature(slice_partition_dedup)] #![feature(copy_within)] #![feature(int_error_matching)] -#![deny(rust_2018_idioms)] +#![warn(rust_2018_idioms)] extern crate test; From 902904a79a5498438e93f41d728615b54c679f19 Mon Sep 17 00:00:00 2001 From: Daiki Mizukami Date: Wed, 24 Apr 2019 20:12:24 +0900 Subject: [PATCH 004/212] std: Derive `Default` for `io::Cursor` --- src/libstd/io/cursor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs index 247d45c3ec91f..abef36e7b2e2e 100644 --- a/src/libstd/io/cursor.rs +++ b/src/libstd/io/cursor.rs @@ -72,7 +72,7 @@ use core::convert::TryInto; /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Default)] pub struct Cursor { inner: T, pos: u64, From 885a001788d18dbbde14587e1dbccca0dad73776 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 24 Apr 2019 21:15:25 +0200 Subject: [PATCH 005/212] const-stabilize NonNull::dangling and NonNull::cast --- src/libcore/ptr.rs | 2 -- src/test/run-pass/consts/const-ptr-nonnull.rs | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index f05700a1db285..eee83ba5ebd3b 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -2959,7 +2959,6 @@ impl NonNull { /// some other means. #[stable(feature = "nonnull", since = "1.25.0")] #[inline] - #[rustc_const_unstable(feature = "const_ptr_nonnull")] pub const fn dangling() -> Self { unsafe { let ptr = mem::align_of::() as *mut T; @@ -3023,7 +3022,6 @@ impl NonNull { /// Cast to a pointer of another type #[stable(feature = "nonnull_cast", since = "1.27.0")] #[inline] - #[rustc_const_unstable(feature = "const_ptr_nonnull")] pub const fn cast(self) -> NonNull { unsafe { NonNull::new_unchecked(self.as_ptr() as *mut U) diff --git a/src/test/run-pass/consts/const-ptr-nonnull.rs b/src/test/run-pass/consts/const-ptr-nonnull.rs index 91624e92fbe75..c5b9d837b47a8 100644 --- a/src/test/run-pass/consts/const-ptr-nonnull.rs +++ b/src/test/run-pass/consts/const-ptr-nonnull.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(const_ptr_nonnull)] - use std::ptr::NonNull; const DANGLING: NonNull = NonNull::dangling(); From 24d89e5016d269637712e9b3806f07234d59a650 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Fri, 26 Apr 2019 12:45:26 -0700 Subject: [PATCH 006/212] impl From for TryFromSliceError --- src/libcore/array.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/libcore/array.rs b/src/libcore/array.rs index fb9c99f667df2..50b3ef477904a 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -11,7 +11,7 @@ use crate::borrow::{Borrow, BorrowMut}; use crate::cmp::Ordering; -use crate::convert::TryFrom; +use crate::convert::{Infallible, TryFrom}; use crate::fmt; use crate::hash::{Hash, self}; use crate::marker::Unsize; @@ -72,6 +72,13 @@ impl TryFromSliceError { } } +#[stable(feature = "try_from_slice_error", since = "1.36.0")] +impl From for TryFromSliceError { + fn from(x: Infallible) -> TryFromSliceError { + match x {} + } +} + macro_rules! __impl_slice_eq1 { ($Lhs: ty, $Rhs: ty) => { __impl_slice_eq1! { $Lhs, $Rhs, Sized } From f007e6f442adafae3e5f2f7f635dc12463bbe0bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 22 Apr 2019 19:37:23 -0700 Subject: [PATCH 007/212] Identify when a stmt could have been parsed as an expr There are some expressions that can be parsed as a statement without a trailing semicolon depending on the context, which can lead to confusing errors due to the same looking code being accepted in some places and not others. Identify these cases and suggest enclosing in parenthesis making the parse non-ambiguous without changing the accepted grammar. --- src/librustc_typeck/check/mod.rs | 28 ++++++- src/libsyntax/parse/lexer/mod.rs | 3 +- src/libsyntax/parse/mod.rs | 4 +- src/libsyntax/parse/parser.rs | 64 ++++++++++++++- src/libsyntax/util/parser.rs | 22 +++++ src/test/ui/parser/expr-as-stmt.fixed | 34 ++++++++ src/test/ui/parser/expr-as-stmt.rs | 34 ++++++++ src/test/ui/parser/expr-as-stmt.stderr | 80 +++++++++++++++++++ .../parser/match-arrows-block-then-binop.rs | 6 +- .../match-arrows-block-then-binop.stderr | 6 ++ 10 files changed, 270 insertions(+), 11 deletions(-) create mode 100644 src/test/ui/parser/expr-as-stmt.fixed create mode 100644 src/test/ui/parser/expr-as-stmt.rs create mode 100644 src/test/ui/parser/expr-as-stmt.stderr diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f11638478923f..61270716dfcbc 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4165,9 +4165,31 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { oprnd_t = self.make_overloaded_place_return_type(method).ty; self.write_method_call(expr.hir_id, method); } else { - type_error_struct!(tcx.sess, expr.span, oprnd_t, E0614, - "type `{}` cannot be dereferenced", - oprnd_t).emit(); + let mut err = type_error_struct!( + tcx.sess, + expr.span, + oprnd_t, + E0614, + "type `{}` cannot be dereferenced", + oprnd_t, + ); + let sp = tcx.sess.source_map().start_point(expr.span); + if let Some(sp) = tcx.sess.parse_sess.abiguous_block_expr_parse + .borrow().get(&sp) + { + if let Ok(snippet) = tcx.sess.source_map() + .span_to_snippet(*sp) + { + err.span_suggestion( + *sp, + "parenthesis are required to parse this \ + as an expression", + format!("({})", snippet), + Applicability::MachineApplicable, + ); + } + } + err.emit(); oprnd_t = tcx.types.err; } } diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index cf8f8abe2ab50..e7d79a647d360 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -1899,7 +1899,7 @@ mod tests { use std::io; use std::path::PathBuf; use syntax_pos::{BytePos, Span, NO_EXPANSION}; - use rustc_data_structures::fx::FxHashSet; + use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use rustc_data_structures::sync::Lock; fn mk_sess(sm: Lrc) -> ParseSess { @@ -1918,6 +1918,7 @@ mod tests { raw_identifier_spans: Lock::new(Vec::new()), registered_diagnostics: Lock::new(ErrorMap::new()), buffered_lints: Lock::new(vec![]), + abiguous_block_expr_parse: Lock::new(FxHashMap::default()), } } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 1abc7832ffa0f..94bbd5ba2f75b 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -16,7 +16,7 @@ use rustc_data_structures::sync::{Lrc, Lock}; use syntax_pos::{Span, SourceFile, FileName, MultiSpan}; use log::debug; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use std::borrow::Cow; use std::iter; use std::path::{Path, PathBuf}; @@ -47,6 +47,7 @@ pub struct ParseSess { included_mod_stack: Lock>, source_map: Lrc, pub buffered_lints: Lock>, + pub abiguous_block_expr_parse: Lock>, } impl ParseSess { @@ -70,6 +71,7 @@ impl ParseSess { included_mod_stack: Lock::new(vec![]), source_map, buffered_lints: Lock::new(vec![]), + abiguous_block_expr_parse: Lock::new(FxHashMap::default()), } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 8efe84cdf016f..3c7f477cc8f00 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -186,6 +186,7 @@ enum PrevTokenKind { Interpolated, Eof, Ident, + BitOr, Other, } @@ -1410,6 +1411,7 @@ impl<'a> Parser<'a> { token::DocComment(..) => PrevTokenKind::DocComment, token::Comma => PrevTokenKind::Comma, token::BinOp(token::Plus) => PrevTokenKind::Plus, + token::BinOp(token::Or) => PrevTokenKind::BitOr, token::Interpolated(..) => PrevTokenKind::Interpolated, token::Eof => PrevTokenKind::Eof, token::Ident(..) => PrevTokenKind::Ident, @@ -2925,6 +2927,19 @@ impl<'a> Parser<'a> { let msg = format!("expected expression, found {}", self.this_token_descr()); let mut err = self.fatal(&msg); + let sp = self.sess.source_map().start_point(self.span); + if let Some(sp) = self.sess.abiguous_block_expr_parse.borrow() + .get(&sp) + { + if let Ok(snippet) = self.sess.source_map().span_to_snippet(*sp) { + err.span_suggestion( + *sp, + "parenthesis are required to parse this as an expression", + format!("({})", snippet), + Applicability::MachineApplicable, + ); + } + } err.span_label(self.span, "expected expression"); return Err(err); } @@ -3616,9 +3631,41 @@ impl<'a> Parser<'a> { } }; - if self.expr_is_complete(&lhs) { - // Semi-statement forms are odd. See https://github.com/rust-lang/rust/issues/29071 - return Ok(lhs); + match (self.expr_is_complete(&lhs), AssocOp::from_token(&self.token)) { + (true, None) => { + // Semi-statement forms are odd. See https://github.com/rust-lang/rust/issues/29071 + return Ok(lhs); + } + (false, _) => {} // continue parsing the expression + (true, Some(AssocOp::Multiply)) | // `{ 42 } *foo = bar;` + (true, Some(AssocOp::Subtract)) | // `{ 42 } -5` + (true, Some(AssocOp::Add)) => { // `{ 42 } + 42 + // These cases are ambiguous and can't be identified in the parser alone + let sp = self.sess.source_map().start_point(self.span); + self.sess.abiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span); + return Ok(lhs); + } + (true, Some(ref op)) if !op.can_continue_expr_unambiguously() => { + return Ok(lhs); + } + (true, Some(_)) => { + // #54186, #54482, #59975 + // We've found an expression that would be parsed as a statement, but the next + // token implies this should be parsed as an expression. + let mut err = self.sess.span_diagnostic.struct_span_err( + self.span, + "ambiguous parse", + ); + let snippet = self.sess.source_map().span_to_snippet(lhs.span) + .unwrap_or_else(|_| pprust::expr_to_string(&lhs)); + err.span_suggestion( + lhs.span, + "parenthesis are required to parse this as an expression", + format!("({})", snippet), + Applicability::MachineApplicable, + ); + err.emit(); + } } self.expected_tokens.push(TokenType::Operator); while let Some(op) = AssocOp::from_token(&self.token) { @@ -4929,6 +4976,17 @@ impl<'a> Parser<'a> { ); let mut err = self.fatal(&msg); err.span_label(self.span, format!("expected {}", expected)); + let sp = self.sess.source_map().start_point(self.span); + if let Some(sp) = self.sess.abiguous_block_expr_parse.borrow().get(&sp) { + if let Ok(snippet) = self.sess.source_map().span_to_snippet(*sp) { + err.span_suggestion( + *sp, + "parenthesis are required to parse this as an expression", + format!("({})", snippet), + Applicability::MachineApplicable, + ); + } + } return Err(err); } } diff --git a/src/libsyntax/util/parser.rs b/src/libsyntax/util/parser.rs index 5f15ede7b0b6a..d76dede8155a0 100644 --- a/src/libsyntax/util/parser.rs +++ b/src/libsyntax/util/parser.rs @@ -207,6 +207,28 @@ impl AssocOp { ObsoleteInPlace | Assign | AssignOp(_) | As | DotDot | DotDotEq | Colon => None } } + + pub fn can_continue_expr_unambiguously(&self) -> bool { + use AssocOp::*; + match self { + BitXor | // `{ 42 } ^ 3` + Assign | // `{ 42 } = { 42 }` + Divide | // `{ 42 } / 42` + Modulus | // `{ 42 } % 2` + ShiftRight | // `{ 42 } >> 2` + LessEqual | // `{ 42 } <= 3` + Greater | // `{ 42 } > 3` + GreaterEqual | // `{ 42 } >= 3` + AssignOp(_) | // `{ 42 } +=` + LAnd | // `{ 42 } &&foo` + As | // `{ 42 } as usize` + // Equal | // `{ 42 } == { 42 }` Accepting these here would regress incorrect + // NotEqual | // `{ 42 } != { 42 } struct literals parser recovery. + Colon => true, // `{ 42 }: usize` + _ => false, + } + + } } pub const PREC_RESET: i8 = -100; diff --git a/src/test/ui/parser/expr-as-stmt.fixed b/src/test/ui/parser/expr-as-stmt.fixed new file mode 100644 index 0000000000000..a0abd00a15c2a --- /dev/null +++ b/src/test/ui/parser/expr-as-stmt.fixed @@ -0,0 +1,34 @@ +// run-rustfix +#![allow(unused_variables)] +#![allow(dead_code)] +#![allow(unused_must_use)] + +fn foo() -> i32 { + ({2}) + {2} //~ ERROR expected expression, found `+` + //~^ ERROR mismatched types +} + +fn bar() -> i32 { + ({2}) + 2 //~ ERROR expected expression, found `+` + //~^ ERROR mismatched types +} + +fn zul() -> u32 { + let foo = 3; + ({ 42 }) + foo; //~ ERROR expected expression, found `+` + //~^ ERROR mismatched types + 32 +} + +fn baz() -> i32 { + ({ 3 }) * 3 //~ ERROR type `{integer}` cannot be dereferenced + //~^ ERROR mismatched types +} + +fn qux(a: Option, b: Option) -> bool { + (if let Some(x) = a { true } else { false }) + && //~ ERROR ambiguous parse + if let Some(y) = a { true } else { false } +} + +fn main() {} diff --git a/src/test/ui/parser/expr-as-stmt.rs b/src/test/ui/parser/expr-as-stmt.rs new file mode 100644 index 0000000000000..cf2e7266a4aac --- /dev/null +++ b/src/test/ui/parser/expr-as-stmt.rs @@ -0,0 +1,34 @@ +// run-rustfix +#![allow(unused_variables)] +#![allow(dead_code)] +#![allow(unused_must_use)] + +fn foo() -> i32 { + {2} + {2} //~ ERROR expected expression, found `+` + //~^ ERROR mismatched types +} + +fn bar() -> i32 { + {2} + 2 //~ ERROR expected expression, found `+` + //~^ ERROR mismatched types +} + +fn zul() -> u32 { + let foo = 3; + { 42 } + foo; //~ ERROR expected expression, found `+` + //~^ ERROR mismatched types + 32 +} + +fn baz() -> i32 { + { 3 } * 3 //~ ERROR type `{integer}` cannot be dereferenced + //~^ ERROR mismatched types +} + +fn qux(a: Option, b: Option) -> bool { + if let Some(x) = a { true } else { false } + && //~ ERROR ambiguous parse + if let Some(y) = a { true } else { false } +} + +fn main() {} diff --git a/src/test/ui/parser/expr-as-stmt.stderr b/src/test/ui/parser/expr-as-stmt.stderr new file mode 100644 index 0000000000000..0311960543277 --- /dev/null +++ b/src/test/ui/parser/expr-as-stmt.stderr @@ -0,0 +1,80 @@ +error: expected expression, found `+` + --> $DIR/expr-as-stmt.rs:7:9 + | +LL | {2} + {2} + | --- ^ expected expression + | | + | help: parenthesis are required to parse this as an expression: `({2})` + +error: expected expression, found `+` + --> $DIR/expr-as-stmt.rs:12:9 + | +LL | {2} + 2 + | --- ^ expected expression + | | + | help: parenthesis are required to parse this as an expression: `({2})` + +error: expected expression, found `+` + --> $DIR/expr-as-stmt.rs:18:12 + | +LL | { 42 } + foo; + | ------ ^ expected expression + | | + | help: parenthesis are required to parse this as an expression: `({ 42 })` + +error: ambiguous parse + --> $DIR/expr-as-stmt.rs:30:5 + | +LL | if let Some(x) = a { true } else { false } + | ------------------------------------------ help: parenthesis are required to parse this as an expression: `(if let Some(x) = a { true } else { false })` +LL | && + | ^^ + +error[E0308]: mismatched types + --> $DIR/expr-as-stmt.rs:7:6 + | +LL | {2} + {2} + | ^ expected (), found integer + | + = note: expected type `()` + found type `{integer}` + +error[E0308]: mismatched types + --> $DIR/expr-as-stmt.rs:12:6 + | +LL | {2} + 2 + | ^ expected (), found integer + | + = note: expected type `()` + found type `{integer}` + +error[E0308]: mismatched types + --> $DIR/expr-as-stmt.rs:18:7 + | +LL | { 42 } + foo; + | ^^ expected (), found integer + | + = note: expected type `()` + found type `{integer}` + +error[E0308]: mismatched types + --> $DIR/expr-as-stmt.rs:24:7 + | +LL | { 3 } * 3 + | ^ expected (), found integer + | + = note: expected type `()` + found type `{integer}` + +error[E0614]: type `{integer}` cannot be dereferenced + --> $DIR/expr-as-stmt.rs:24:11 + | +LL | { 3 } * 3 + | ----- ^^^ + | | + | help: parenthesis are required to parse this as an expression: `({ 3 })` + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0308, E0614. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/match-arrows-block-then-binop.rs b/src/test/ui/parser/match-arrows-block-then-binop.rs index 1a40d67492990..56c917c7462f2 100644 --- a/src/test/ui/parser/match-arrows-block-then-binop.rs +++ b/src/test/ui/parser/match-arrows-block-then-binop.rs @@ -1,7 +1,7 @@ fn main() { - - match 0 { + let _ = match 0 { 0 => { + 0 } + 5 //~ ERROR expected pattern, found `+` - } + }; } diff --git a/src/test/ui/parser/match-arrows-block-then-binop.stderr b/src/test/ui/parser/match-arrows-block-then-binop.stderr index a844cac189aa1..0d7f81645b46a 100644 --- a/src/test/ui/parser/match-arrows-block-then-binop.stderr +++ b/src/test/ui/parser/match-arrows-block-then-binop.stderr @@ -3,6 +3,12 @@ error: expected pattern, found `+` | LL | } + 5 | ^ expected pattern +help: parenthesis are required to parse this as an expression + | +LL | 0 => ({ +LL | 0 +LL | }) + 5 + | error: aborting due to previous error From bff0be37845a96010fa2161bbf137fadfe763ae5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 29 Apr 2019 14:35:09 -0700 Subject: [PATCH 008/212] Add test case for #47287 --- src/test/ui/parser/expr-as-stmt.fixed | 6 ++++++ src/test/ui/parser/expr-as-stmt.rs | 6 ++++++ src/test/ui/parser/expr-as-stmt.stderr | 14 +++++++++++++- 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/test/ui/parser/expr-as-stmt.fixed b/src/test/ui/parser/expr-as-stmt.fixed index a0abd00a15c2a..123f06e7707e0 100644 --- a/src/test/ui/parser/expr-as-stmt.fixed +++ b/src/test/ui/parser/expr-as-stmt.fixed @@ -31,4 +31,10 @@ fn qux(a: Option, b: Option) -> bool { if let Some(y) = a { true } else { false } } +fn moo(x: u32) -> bool { + (match x { + _ => 1, + }) > 0 //~ ERROR ambiguous parse +} + fn main() {} diff --git a/src/test/ui/parser/expr-as-stmt.rs b/src/test/ui/parser/expr-as-stmt.rs index cf2e7266a4aac..6f713c0894001 100644 --- a/src/test/ui/parser/expr-as-stmt.rs +++ b/src/test/ui/parser/expr-as-stmt.rs @@ -31,4 +31,10 @@ fn qux(a: Option, b: Option) -> bool { if let Some(y) = a { true } else { false } } +fn moo(x: u32) -> bool { + match x { + _ => 1, + } > 0 //~ ERROR ambiguous parse +} + fn main() {} diff --git a/src/test/ui/parser/expr-as-stmt.stderr b/src/test/ui/parser/expr-as-stmt.stderr index 0311960543277..be577b8f36fe6 100644 --- a/src/test/ui/parser/expr-as-stmt.stderr +++ b/src/test/ui/parser/expr-as-stmt.stderr @@ -30,6 +30,18 @@ LL | if let Some(x) = a { true } else { false } LL | && | ^^ +error: ambiguous parse + --> $DIR/expr-as-stmt.rs:37:7 + | +LL | } > 0 + | ^ +help: parenthesis are required to parse this as an expression + | +LL | (match x { +LL | _ => 1, +LL | }) > 0 + | + error[E0308]: mismatched types --> $DIR/expr-as-stmt.rs:7:6 | @@ -74,7 +86,7 @@ LL | { 3 } * 3 | | | help: parenthesis are required to parse this as an expression: `({ 3 })` -error: aborting due to 9 previous errors +error: aborting due to 10 previous errors Some errors have detailed explanations: E0308, E0614. For more information about an error, try `rustc --explain E0308`. From 9b3583375dbd45b19b8ce8822b89ff79529354d6 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 29 Apr 2019 18:32:05 -0700 Subject: [PATCH 009/212] Document the order of {Vec,VecDeque,String}::retain It's natural for `retain` to work in order from beginning to end, but this wasn't actually documented to be the case. If we actually promise this, then the caller can do useful things like track the index of each element being tested, as [discussed in the forum][1]. This is now documented for `Vec`, `VecDeque`, and `String`. [1]: https://users.rust-lang.org/t/vec-retain-by-index/27697 `HashMap` and `HashSet` also have `retain`, and the `hashbrown` implementation does happen to use a plain `iter()` order too, but it's not certain that this should always be the case for these types. --- src/liballoc/collections/vec_deque.rs | 4 ++-- src/liballoc/string.rs | 4 ++-- src/liballoc/vec.rs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index d65c24f7350ae..82a60f924444a 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -1835,8 +1835,8 @@ impl VecDeque { /// Retains only the elements specified by the predicate. /// /// In other words, remove all elements `e` such that `f(&e)` returns false. - /// This method operates in place and preserves the order of the retained - /// elements. + /// This method operates in place, visiting each element exactly once in the + /// original order, and preserves the order of the retained elements. /// /// # Examples /// diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index a3e2098695f70..aaa3814269339 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -1200,8 +1200,8 @@ impl String { /// Retains only the characters specified by the predicate. /// /// In other words, remove all characters `c` such that `f(c)` returns `false`. - /// This method operates in place and preserves the order of the retained - /// characters. + /// This method operates in place, visiting each character exactly once in the + /// original order, and preserves the order of the retained characters. /// /// # Examples /// diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index cd62c3e05244c..a9bc835010ffb 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -937,8 +937,8 @@ impl Vec { /// Retains only the elements specified by the predicate. /// /// In other words, remove all elements `e` such that `f(&e)` returns `false`. - /// This method operates in place and preserves the order of the retained - /// elements. + /// This method operates in place, visiting each element exactly once in the + /// original order, and preserves the order of the retained elements. /// /// # Examples /// From 617ce2b7ee330bbcc7ce8eb87160c71ad995639b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 30 Apr 2019 20:37:42 -0700 Subject: [PATCH 010/212] Reword ambigous parse error to fit with the current error --- src/libsyntax/parse/parser.rs | 11 ++++++----- src/test/ui/parser/expr-as-stmt.fixed | 4 ++-- src/test/ui/parser/expr-as-stmt.rs | 4 ++-- src/test/ui/parser/expr-as-stmt.stderr | 8 ++++---- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 3c7f477cc8f00..fbd1203dec94a 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3649,13 +3649,14 @@ impl<'a> Parser<'a> { return Ok(lhs); } (true, Some(_)) => { - // #54186, #54482, #59975 // We've found an expression that would be parsed as a statement, but the next // token implies this should be parsed as an expression. - let mut err = self.sess.span_diagnostic.struct_span_err( - self.span, - "ambiguous parse", - ); + // For example: `if let Some(x) = x { x } else { 0 } / 2` + let mut err = self.sess.span_diagnostic.struct_span_err(self.span, &format!( + "expected expression, found `{}`", + pprust::token_to_string(&self.token), + )); + err.span_label(self.span, "expected expression"); let snippet = self.sess.source_map().span_to_snippet(lhs.span) .unwrap_or_else(|_| pprust::expr_to_string(&lhs)); err.span_suggestion( diff --git a/src/test/ui/parser/expr-as-stmt.fixed b/src/test/ui/parser/expr-as-stmt.fixed index 123f06e7707e0..1ce6f9c25034f 100644 --- a/src/test/ui/parser/expr-as-stmt.fixed +++ b/src/test/ui/parser/expr-as-stmt.fixed @@ -27,14 +27,14 @@ fn baz() -> i32 { fn qux(a: Option, b: Option) -> bool { (if let Some(x) = a { true } else { false }) - && //~ ERROR ambiguous parse + && //~ ERROR expected expression if let Some(y) = a { true } else { false } } fn moo(x: u32) -> bool { (match x { _ => 1, - }) > 0 //~ ERROR ambiguous parse + }) > 0 //~ ERROR expected expression } fn main() {} diff --git a/src/test/ui/parser/expr-as-stmt.rs b/src/test/ui/parser/expr-as-stmt.rs index 6f713c0894001..b526c17488eaf 100644 --- a/src/test/ui/parser/expr-as-stmt.rs +++ b/src/test/ui/parser/expr-as-stmt.rs @@ -27,14 +27,14 @@ fn baz() -> i32 { fn qux(a: Option, b: Option) -> bool { if let Some(x) = a { true } else { false } - && //~ ERROR ambiguous parse + && //~ ERROR expected expression if let Some(y) = a { true } else { false } } fn moo(x: u32) -> bool { match x { _ => 1, - } > 0 //~ ERROR ambiguous parse + } > 0 //~ ERROR expected expression } fn main() {} diff --git a/src/test/ui/parser/expr-as-stmt.stderr b/src/test/ui/parser/expr-as-stmt.stderr index be577b8f36fe6..1725ba944c50f 100644 --- a/src/test/ui/parser/expr-as-stmt.stderr +++ b/src/test/ui/parser/expr-as-stmt.stderr @@ -22,19 +22,19 @@ LL | { 42 } + foo; | | | help: parenthesis are required to parse this as an expression: `({ 42 })` -error: ambiguous parse +error: expected expression, found `&&` --> $DIR/expr-as-stmt.rs:30:5 | LL | if let Some(x) = a { true } else { false } | ------------------------------------------ help: parenthesis are required to parse this as an expression: `(if let Some(x) = a { true } else { false })` LL | && - | ^^ + | ^^ expected expression -error: ambiguous parse +error: expected expression, found `>` --> $DIR/expr-as-stmt.rs:37:7 | LL | } > 0 - | ^ + | ^ expected expression help: parenthesis are required to parse this as an expression | LL | (match x { From 3b24cf80b4597652212cd4946e9ea09c4291d6c5 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Wed, 1 May 2019 12:16:54 +0200 Subject: [PATCH 011/212] Update RLS --- src/tools/rls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rls b/src/tools/rls index 20e32686df573..5b8e99bb61958 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit 20e32686df573fc44ac1052bf3e6982b0da27cfc +Subproject commit 5b8e99bb61958ca8abcb7c5eda70521726be1065 From 145add7ccfa14e74ff770ee10e0cf2d6609c7e70 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 30 Mar 2019 17:18:54 +0000 Subject: [PATCH 012/212] Add test for slice drop shims --- src/test/mir-opt/slice-drop-shim.rs | 92 +++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 src/test/mir-opt/slice-drop-shim.rs diff --git a/src/test/mir-opt/slice-drop-shim.rs b/src/test/mir-opt/slice-drop-shim.rs new file mode 100644 index 0000000000000..f558ec18ba9f2 --- /dev/null +++ b/src/test/mir-opt/slice-drop-shim.rs @@ -0,0 +1,92 @@ +fn main() { + std::ptr::drop_in_place::<[String]> as unsafe fn(_); +} + +// END RUST SOURCE + +// START rustc.ptr-real_drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir +// let mut _2: usize; +// let mut _3: bool; +// let mut _4: usize; +// let mut _5: usize; +// let mut _6: &mut std::string::String; +// let mut _7: bool; +// let mut _8: &mut std::string::String; +// let mut _9: bool; +// let mut _10: *mut std::string::String; +// let mut _11: usize; +// let mut _12: *mut std::string::String; +// let mut _13: &mut std::string::String; +// let mut _14: bool; +// let mut _15: &mut std::string::String; +// let mut _16: bool; +// let mut _17: *mut [std::string::String]; +// bb0: { +// goto -> bb15; +// } +// bb1: { +// return; +// } +// bb2 (cleanup): { +// resume; +// } +// bb3 (cleanup): { +// _6 = &mut (*_1)[_4]; +// _4 = Add(_4, const 1usize); +// drop((*_6)) -> bb4; +// } +// bb4 (cleanup): { +// _7 = Eq(_4, _5); +// switchInt(move _7) -> [false: bb3, otherwise: bb2]; +// } +// bb5: { +// _8 = &mut (*_1)[_4]; +// _4 = Add(_4, const 1usize); +// drop((*_8)) -> [return: bb6, unwind: bb4]; +// } +// bb6: { +// _9 = Eq(_4, _5); +// switchInt(move _9) -> [false: bb5, otherwise: bb1]; +// } +// bb7: { +// _5 = Len((*_1)); +// _4 = const 0usize; +// goto -> bb6; +// } +// bb8: { +// goto -> bb7; +// } +// bb9 (cleanup): { +// _13 = &mut (*_10); +// _10 = Offset(_10, const 1usize); +// drop((*_13)) -> bb10; +// } +// bb10 (cleanup): { +// _14 = Eq(_10, _12); +// switchInt(move _14) -> [false: bb9, otherwise: bb2]; +// } +// bb11: { +// _15 = &mut (*_10); +// _10 = Offset(_10, const 1usize); +// drop((*_15)) -> [return: bb12, unwind: bb10]; +// } +// bb12: { +// _16 = Eq(_10, _12); +// switchInt(move _16) -> [false: bb11, otherwise: bb1]; +// } +// bb13: { +// _11 = Len((*_1)); +// _17 = &mut (*_1); +// _10 = move _17 as *mut std::string::String (Misc); +// _12 = Offset(_10, move _11); +// goto -> bb12; +// } +// bb14: { +// goto -> bb13; +// } +// bb15: { +// _2 = SizeOf(std::string::String); +// _3 = Eq(move _2, const 0usize); +// switchInt(move _3) -> [false: bb14, otherwise: bb8]; +// } +// END rustc.ptr-real_drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir From 6fff547828c13d311bc3e3034f190747b9367816 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Mon, 29 Apr 2019 20:38:08 +0100 Subject: [PATCH 013/212] Slightly simplify the MIR for slice drop shims --- src/librustc_mir/util/elaborate_drops.rs | 122 ++++++++++++----------- src/test/mir-opt/slice-drop-shim.rs | 72 +++++++------ 2 files changed, 99 insertions(+), 95 deletions(-) diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 856783bcbaa46..98ca7c32675c8 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -10,7 +10,7 @@ use rustc::ty::util::IntTypeExt; use rustc_data_structures::indexed_vec::Idx; use crate::util::patch::MirPatch; -use std::u32; +use std::convert::TryInto; #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum DropFlagState { @@ -545,10 +545,9 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> self.elaborator.patch().new_block(result) } - /// create a loop that drops an array: - /// - + /// Create a loop that drops an array: /// + /// ```text /// loop-block: /// can_go = cur == length_or_end /// if can_go then succ else drop-block @@ -561,15 +560,16 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> /// cur = cur + 1 /// } /// drop(ptr) - fn drop_loop(&mut self, - succ: BasicBlock, - cur: Local, - length_or_end: &Place<'tcx>, - ety: Ty<'tcx>, - unwind: Unwind, - ptr_based: bool) - -> BasicBlock - { + /// ``` + fn drop_loop( + &mut self, + succ: BasicBlock, + cur: Local, + length_or_end: &Place<'tcx>, + ety: Ty<'tcx>, + unwind: Unwind, + ptr_based: bool, + ) -> BasicBlock { let copy = |place: &Place<'tcx>| Operand::Copy(place.clone()); let move_ = |place: &Place<'tcx>| Operand::Move(place.clone()); let tcx = self.tcx(); @@ -591,13 +591,13 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> elem: ProjectionElem::Deref, })) ), - Rvalue::BinaryOp(BinOp::Offset, copy(&Place::Base(PlaceBase::Local(cur))), one)) + Rvalue::BinaryOp(BinOp::Offset, move_(&Place::Base(PlaceBase::Local(cur))), one)) } else { (Rvalue::Ref( tcx.lifetimes.re_erased, BorrowKind::Mut { allow_two_phase_borrow: false }, self.place.clone().index(cur)), - Rvalue::BinaryOp(BinOp::Add, copy(&Place::Base(PlaceBase::Local(cur))), one)) + Rvalue::BinaryOp(BinOp::Add, move_(&Place::Base(PlaceBase::Local(cur))), one)) }; let drop_block = BasicBlockData { @@ -647,9 +647,9 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> // } if let Some(size) = opt_size { - assert!(size <= (u32::MAX as u64), - "move out check doesn't implemented for array bigger then u32"); - let size = size as u32; + let size: u32 = size.try_into().unwrap_or_else(|_| { + bug!("move out check isn't implemented for array sizes bigger than u32::MAX"); + }); let fields: Vec<(Place<'tcx>, Option)> = (0..size).map(|i| { (self.place.clone().elem(ProjectionElem::ConstantIndex{ offset: i, @@ -667,33 +667,42 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> let move_ = |place: &Place<'tcx>| Operand::Move(place.clone()); let tcx = self.tcx(); - let size = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.usize))); - let size_is_zero = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.bool))); + let elem_size = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.usize))); + let len = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.usize))); + + static USIZE_SWITCH_ZERO: &[u128] = &[0]; + let base_block = BasicBlockData { statements: vec![ - self.assign(size, Rvalue::NullaryOp(NullOp::SizeOf, ety)), - self.assign(size_is_zero, Rvalue::BinaryOp(BinOp::Eq, - move_(size), - self.constant_usize(0))) + self.assign(elem_size, Rvalue::NullaryOp(NullOp::SizeOf, ety)), + self.assign(len, Rvalue::Len(self.place.clone())), ], is_cleanup: self.unwind.is_cleanup(), terminator: Some(Terminator { source_info: self.source_info, - kind: TerminatorKind::if_( - tcx, - move_(size_is_zero), - self.drop_loop_pair(ety, false), - self.drop_loop_pair(ety, true) - ) + kind: TerminatorKind::SwitchInt { + discr: move_(elem_size), + switch_ty: tcx.types.usize, + values: From::from(USIZE_SWITCH_ZERO), + targets: vec![ + self.drop_loop_pair(ety, false, len.clone()), + self.drop_loop_pair(ety, true, len.clone()), + ], + }, }) }; self.elaborator.patch().new_block(base_block) } - // create a pair of drop-loops of `place`, which drops its contents - // even in the case of 1 panic. If `ptr_based`, create a pointer loop, - // otherwise create an index loop. - fn drop_loop_pair(&mut self, ety: Ty<'tcx>, ptr_based: bool) -> BasicBlock { + /// Ceates a pair of drop-loops of `place`, which drops its contents, even + /// in the case of 1 panic. If `ptr_based`, creates a pointer loop, + /// otherwise create an index loop. + fn drop_loop_pair( + &mut self, + ety: Ty<'tcx>, + ptr_based: bool, + length: Place<'tcx>, + ) -> BasicBlock { debug!("drop_loop_pair({:?}, {:?})", ety, ptr_based); let tcx = self.tcx(); let iter_ty = if ptr_based { @@ -703,7 +712,6 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> }; let cur = self.new_temp(iter_ty); - let length = Place::Base(PlaceBase::Local(self.new_temp(tcx.types.usize))); let length_or_end = if ptr_based { // FIXME check if we want to make it return a `Place` directly // if all use sites want a `Place::Base` anyway. @@ -722,9 +730,8 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> ptr_based) }); - let succ = self.succ; // FIXME(#43234) let loop_block = self.drop_loop( - succ, + self.succ, cur, &length_or_end, ety, @@ -732,31 +739,32 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> ptr_based); let cur = Place::Base(PlaceBase::Local(cur)); - let zero = self.constant_usize(0); - let mut drop_block_stmts = vec![]; - drop_block_stmts.push(self.assign(&length, Rvalue::Len(self.place.clone()))); - if ptr_based { + let drop_block_stmts = if ptr_based { let tmp_ty = tcx.mk_mut_ptr(self.place_ty(self.place)); let tmp = Place::Base(PlaceBase::Local(self.new_temp(tmp_ty))); // tmp = &mut P; // cur = tmp as *mut T; // end = Offset(cur, len); - drop_block_stmts.push(self.assign(&tmp, Rvalue::Ref( - tcx.lifetimes.re_erased, - BorrowKind::Mut { allow_two_phase_borrow: false }, - self.place.clone() - ))); - drop_block_stmts.push(self.assign(&cur, Rvalue::Cast( - CastKind::Misc, Operand::Move(tmp), iter_ty - ))); - drop_block_stmts.push(self.assign(&length_or_end, - Rvalue::BinaryOp(BinOp::Offset, - Operand::Copy(cur), Operand::Move(length) - ))); + vec![ + self.assign(&tmp, Rvalue::Ref( + tcx.lifetimes.re_erased, + BorrowKind::Mut { allow_two_phase_borrow: false }, + self.place.clone() + )), + self.assign( + &cur, + Rvalue::Cast(CastKind::Misc, Operand::Move(tmp), iter_ty), + ), + self.assign( + &length_or_end, + Rvalue::BinaryOp(BinOp::Offset, Operand::Copy(cur), Operand::Move(length) + )), + ] } else { - // index = 0 (length already pushed) - drop_block_stmts.push(self.assign(&cur, Rvalue::Use(zero))); - } + // cur = 0 (length already pushed) + let zero = self.constant_usize(0); + vec![self.assign(&cur, Rvalue::Use(zero))] + }; let drop_block = self.elaborator.patch().new_block(BasicBlockData { statements: drop_block_stmts, is_cleanup: unwind.is_cleanup(), @@ -768,7 +776,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> // FIXME(#34708): handle partially-dropped array/slice elements. let reset_block = self.drop_flag_reset_block(DropFlagMode::Deep, drop_block, unwind); - self.drop_flag_test_block(reset_block, succ, unwind) + self.drop_flag_test_block(reset_block, self.succ, unwind) } /// The slow-path - create an "open", elaborated drop for a type diff --git a/src/test/mir-opt/slice-drop-shim.rs b/src/test/mir-opt/slice-drop-shim.rs index f558ec18ba9f2..754fad51b21e7 100644 --- a/src/test/mir-opt/slice-drop-shim.rs +++ b/src/test/mir-opt/slice-drop-shim.rs @@ -6,21 +6,19 @@ fn main() { // START rustc.ptr-real_drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir // let mut _2: usize; -// let mut _3: bool; +// let mut _3: usize; // let mut _4: usize; -// let mut _5: usize; -// let mut _6: &mut std::string::String; -// let mut _7: bool; -// let mut _8: &mut std::string::String; -// let mut _9: bool; +// let mut _5: &mut std::string::String; +// let mut _6: bool; +// let mut _7: &mut std::string::String; +// let mut _8: bool; +// let mut _9: *mut std::string::String; // let mut _10: *mut std::string::String; -// let mut _11: usize; -// let mut _12: *mut std::string::String; +// let mut _11: &mut std::string::String; +// let mut _12: bool; // let mut _13: &mut std::string::String; // let mut _14: bool; -// let mut _15: &mut std::string::String; -// let mut _16: bool; -// let mut _17: *mut [std::string::String]; +// let mut _15: *mut [std::string::String]; // bb0: { // goto -> bb15; // } @@ -31,25 +29,24 @@ fn main() { // resume; // } // bb3 (cleanup): { -// _6 = &mut (*_1)[_4]; -// _4 = Add(_4, const 1usize); -// drop((*_6)) -> bb4; +// _5 = &mut (*_1)[_4]; +// _4 = Add(move _4, const 1usize); +// drop((*_5)) -> bb4; // } // bb4 (cleanup): { -// _7 = Eq(_4, _5); -// switchInt(move _7) -> [false: bb3, otherwise: bb2]; +// _6 = Eq(_4, _3); +// switchInt(move _6) -> [false: bb3, otherwise: bb2]; // } // bb5: { -// _8 = &mut (*_1)[_4]; -// _4 = Add(_4, const 1usize); -// drop((*_8)) -> [return: bb6, unwind: bb4]; +// _7 = &mut (*_1)[_4]; +// _4 = Add(move _4, const 1usize); +// drop((*_7)) -> [return: bb6, unwind: bb4]; // } // bb6: { -// _9 = Eq(_4, _5); -// switchInt(move _9) -> [false: bb5, otherwise: bb1]; +// _8 = Eq(_4, _3); +// switchInt(move _8) -> [false: bb5, otherwise: bb1]; // } // bb7: { -// _5 = Len((*_1)); // _4 = const 0usize; // goto -> bb6; // } @@ -57,28 +54,27 @@ fn main() { // goto -> bb7; // } // bb9 (cleanup): { -// _13 = &mut (*_10); -// _10 = Offset(_10, const 1usize); -// drop((*_13)) -> bb10; +// _11 = &mut (*_9); +// _9 = Offset(move _9, const 1usize); +// drop((*_11)) -> bb10; // } // bb10 (cleanup): { -// _14 = Eq(_10, _12); -// switchInt(move _14) -> [false: bb9, otherwise: bb2]; +// _12 = Eq(_9, _10); +// switchInt(move _12) -> [false: bb9, otherwise: bb2]; // } // bb11: { -// _15 = &mut (*_10); -// _10 = Offset(_10, const 1usize); -// drop((*_15)) -> [return: bb12, unwind: bb10]; +// _13 = &mut (*_9); +// _9 = Offset(move _9, const 1usize); +// drop((*_13)) -> [return: bb12, unwind: bb10]; // } // bb12: { -// _16 = Eq(_10, _12); -// switchInt(move _16) -> [false: bb11, otherwise: bb1]; +// _14 = Eq(_9, _10); +// switchInt(move _14) -> [false: bb11, otherwise: bb1]; // } // bb13: { -// _11 = Len((*_1)); -// _17 = &mut (*_1); -// _10 = move _17 as *mut std::string::String (Misc); -// _12 = Offset(_10, move _11); +// _15 = &mut (*_1); +// _9 = move _15 as *mut std::string::String (Misc); +// _10 = Offset(_9, move _3); // goto -> bb12; // } // bb14: { @@ -86,7 +82,7 @@ fn main() { // } // bb15: { // _2 = SizeOf(std::string::String); -// _3 = Eq(move _2, const 0usize); -// switchInt(move _3) -> [false: bb14, otherwise: bb8]; +// _3 = Len((*_1)); +// switchInt(move _2) -> [0usize: bb8, otherwise: bb14]; // } // END rustc.ptr-real_drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir From adbaf7a9cdc3f67116e2034d0e5e235779dae286 Mon Sep 17 00:00:00 2001 From: Alexey Shmalko Date: Wed, 1 May 2019 23:26:06 +0300 Subject: [PATCH 014/212] BinaryHeap: add min-heap example --- src/liballoc/collections/binary_heap.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/liballoc/collections/binary_heap.rs b/src/liballoc/collections/binary_heap.rs index 8c142a3d317c6..c355361b53c46 100644 --- a/src/liballoc/collections/binary_heap.rs +++ b/src/liballoc/collections/binary_heap.rs @@ -207,6 +207,30 @@ use super::SpecExtend; /// // The heap should now be empty. /// assert!(heap.is_empty()) /// ``` +/// +/// ## Min-heap +/// +/// Either `std::cmp::Reverse` or a custom `Ord` implementation can be used to +/// make `BinaryHeap` a min-heap. This makes `heap.pop()` return the smallest +/// value instead of the greatest one. +/// +/// ``` +/// use std::collections::BinaryHeap; +/// use std::cmp::Reverse; +/// +/// let mut heap = BinaryHeap::new(); +/// +/// // Wrap values in `Reverse` +/// heap.push(Reverse(1)); +/// heap.push(Reverse(5)); +/// heap.push(Reverse(2)); +/// +/// // If we pop these scores now, they should come back in the reverse order. +/// assert_eq!(heap.pop(), Some(Reverse(1))); +/// assert_eq!(heap.pop(), Some(Reverse(2))); +/// assert_eq!(heap.pop(), Some(Reverse(5))); +/// assert_eq!(heap.pop(), None); +/// ``` #[stable(feature = "rust1", since = "1.0.0")] pub struct BinaryHeap { data: Vec, From 31407e8d41e8a87bbd530e32e811453669dee078 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Thu, 2 May 2019 11:51:23 +0200 Subject: [PATCH 015/212] Update Cargo Align with the version bump in https://github.com/rust-lang/rls/pull/1448 --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 6be12653dcefb..beb8fcb5248dc 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 6be12653dcefb46ee7b605f063ee75b5e6cba513 +Subproject commit beb8fcb5248dc2e6aa488af9613216d5ccb31c6a From bfa5f278472d0bad4e7db4a4259b2f1fa97ca0ab Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 25 Apr 2019 11:48:25 +0300 Subject: [PATCH 016/212] introduce unescape module Currently, we deal with escape sequences twice: once when we lex a string, and a second time when we unescape literals. This PR aims to remove this duplication, by introducing a new `unescape` mode as a single source of truth for character escaping rules --- src/librustc_errors/diagnostic_builder.rs | 2 +- src/libsyntax/parse/lexer/mod.rs | 585 +++++------------- src/libsyntax/parse/mod.rs | 262 ++------ src/libsyntax/parse/unescape.rs | 515 +++++++++++++++ .../parse/unescape_error_reporting.rs | 200 ++++++ src/test/ui/fmt/format-string-error-2.rs | 3 +- src/test/ui/fmt/format-string-error-2.stderr | 52 +- .../parser/ascii-only-character-escape.stderr | 12 +- src/test/ui/parser/byte-literals.stderr | 6 +- .../ui/parser/byte-string-literals.stderr | 4 +- .../ui/parser/issue-23620-invalid-escapes.rs | 7 +- .../parser/issue-23620-invalid-escapes.stderr | 60 +- .../ui/parser/lex-bad-char-literals-1.stderr | 8 +- .../ui/parser/lex-bad-char-literals-2.stderr | 4 + src/test/ui/parser/lex-bad-char-literals-4.rs | 2 +- .../ui/parser/lex-bad-char-literals-4.stderr | 4 +- .../ui/parser/lex-bad-char-literals-6.stderr | 12 + src/test/ui/parser/lex-bad-char-literals-7.rs | 14 + .../ui/parser/lex-bad-char-literals-7.stderr | 20 + ...literals-are-validated-before-expansion.rs | 10 + ...rals-are-validated-before-expansion.stderr | 18 + .../ui/parser/new-unicode-escapes-1.stderr | 4 +- .../ui/parser/new-unicode-escapes-2.stderr | 4 +- .../ui/parser/new-unicode-escapes-3.stderr | 8 +- 24 files changed, 1047 insertions(+), 769 deletions(-) create mode 100644 src/libsyntax/parse/unescape.rs create mode 100644 src/libsyntax/parse/unescape_error_reporting.rs create mode 100644 src/test/ui/parser/lex-bad-char-literals-7.rs create mode 100644 src/test/ui/parser/lex-bad-char-literals-7.stderr create mode 100644 src/test/ui/parser/macro/literals-are-validated-before-expansion.rs create mode 100644 src/test/ui/parser/macro/literals-are-validated-before-expansion.stderr diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index c8d47339fb365..f74dcd6070c70 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -184,7 +184,7 @@ impl<'a> DiagnosticBuilder<'a> { ) -> &mut Self); forward!(pub fn warn(&mut self, msg: &str) -> &mut Self); forward!(pub fn span_warn>(&mut self, sp: S, msg: &str) -> &mut Self); - forward!(pub fn help(&mut self , msg: &str) -> &mut Self); + forward!(pub fn help(&mut self, msg: &str) -> &mut Self); forward!(pub fn span_help>(&mut self, sp: S, msg: &str, diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index cf8f8abe2ab50..3c342c2ff26a9 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -1,8 +1,10 @@ use crate::ast::{self, Ident}; use crate::parse::{token, ParseSess}; use crate::symbol::Symbol; +use crate::parse::unescape; +use crate::parse::unescape_error_reporting::{emit_unescape_error, push_escaped_char}; -use errors::{Applicability, FatalError, Diagnostic, DiagnosticBuilder}; +use errors::{FatalError, Diagnostic, DiagnosticBuilder}; use syntax_pos::{BytePos, Pos, Span, NO_EXPANSION}; use core::unicode::property::Pattern_White_Space; @@ -334,25 +336,12 @@ impl<'a> StringReader<'a> { self.err_span(self.mk_sp(from_pos, to_pos), m) } - /// Pushes a character to a message string for error reporting - fn push_escaped_char_for_msg(m: &mut String, c: char) { - match c { - '\u{20}'..='\u{7e}' => { - // Don't escape \, ' or " for user-facing messages - m.push(c); - } - _ => { - m.extend(c.escape_default()); - } - } - } - /// Report a lexical error spanning [`from_pos`, `to_pos`), appending an /// escaped character to the error message fn fatal_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) -> FatalError { let mut m = m.to_string(); m.push_str(": "); - Self::push_escaped_char_for_msg(&mut m, c); + push_escaped_char(&mut m, c); self.fatal_span_(from_pos, to_pos, &m[..]) } @@ -368,7 +357,7 @@ impl<'a> StringReader<'a> { { let mut m = m.to_string(); m.push_str(": "); - Self::push_escaped_char_for_msg(&mut m, c); + push_escaped_char(&mut m, c); self.sess.span_diagnostic.struct_span_fatal(self.mk_sp(from_pos, to_pos), &m[..]) } @@ -378,29 +367,10 @@ impl<'a> StringReader<'a> { fn err_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) { let mut m = m.to_string(); m.push_str(": "); - Self::push_escaped_char_for_msg(&mut m, c); + push_escaped_char(&mut m, c); self.err_span_(from_pos, to_pos, &m[..]); } - fn struct_err_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) - -> DiagnosticBuilder<'a> - { - let mut m = m.to_string(); - m.push_str(": "); - Self::push_escaped_char_for_msg(&mut m, c); - - self.sess.span_diagnostic.struct_span_err(self.mk_sp(from_pos, to_pos), &m[..]) - } - - /// Report a lexical error spanning [`from_pos`, `to_pos`), appending the - /// offending string to the error message - fn fatal_span_verbose(&self, from_pos: BytePos, to_pos: BytePos, mut m: String) -> FatalError { - m.push_str(": "); - m.push_str(&self.src[self.src_index(from_pos)..self.src_index(to_pos)]); - - self.fatal_span_(from_pos, to_pos, &m[..]) - } - /// Advance peek_tok and peek_span to refer to the next token, and /// possibly update the interner. fn advance_token(&mut self) -> Result<(), ()> { @@ -863,271 +833,6 @@ impl<'a> StringReader<'a> { } } - /// Scan over `n_digits` hex digits, stopping at `delim`, reporting an - /// error if too many or too few digits are encountered. - fn scan_hex_digits(&mut self, n_digits: usize, delim: char, below_0x7f_only: bool) -> bool { - debug!("scanning {} digits until {:?}", n_digits, delim); - let start_bpos = self.pos; - let mut accum_int = 0; - - let mut valid = true; - for _ in 0..n_digits { - if self.is_eof() { - let last_bpos = self.pos; - self.fatal_span_(start_bpos, - last_bpos, - "unterminated numeric character escape").raise(); - } - if self.ch_is(delim) { - let last_bpos = self.pos; - self.err_span_(start_bpos, - last_bpos, - "numeric character escape is too short"); - valid = false; - break; - } - let c = self.ch.unwrap_or('\x00'); - accum_int *= 16; - accum_int += c.to_digit(16).unwrap_or_else(|| { - self.err_span_char(self.pos, - self.next_pos, - "invalid character in numeric character escape", - c); - - valid = false; - 0 - }); - self.bump(); - } - - if below_0x7f_only && accum_int >= 0x80 { - self.err_span_(start_bpos, - self.pos, - "this form of character escape may only be used with characters in \ - the range [\\x00-\\x7f]"); - valid = false; - } - - match char::from_u32(accum_int) { - Some(_) => valid, - None => { - let last_bpos = self.pos; - self.err_span_(start_bpos, last_bpos, "invalid numeric character escape"); - false - } - } - } - - /// Scan for a single (possibly escaped) byte or char - /// in a byte, (non-raw) byte string, char, or (non-raw) string literal. - /// `start` is the position of `first_source_char`, which is already consumed. - /// - /// Returns `true` if there was a valid char/byte. - fn scan_char_or_byte(&mut self, - start: BytePos, - first_source_char: char, - ascii_only: bool, - delim: char) - -> bool - { - match first_source_char { - '\\' => { - // '\X' for some X must be a character constant: - let escaped = self.ch; - let escaped_pos = self.pos; - self.bump(); - match escaped { - None => {} // EOF here is an error that will be checked later. - Some(e) => { - return match e { - 'n' | 'r' | 't' | '\\' | '\'' | '"' | '0' => true, - 'x' => self.scan_byte_escape(delim, !ascii_only), - 'u' => { - let valid = if self.ch_is('{') { - self.scan_unicode_escape(delim) && !ascii_only - } else { - let span = self.mk_sp(start, self.pos); - let mut suggestion = "\\u{".to_owned(); - let msg = "incorrect unicode escape sequence"; - let mut err = self.sess.span_diagnostic.struct_span_err( - span, - msg, - ); - let mut i = 0; - while let (Some(ch), true) = (self.ch, i < 6) { - if ch.is_digit(16) { - suggestion.push(ch); - self.bump(); - i += 1; - } else { - break; - } - } - if i != 0 { - suggestion.push('}'); - err.span_suggestion( - self.mk_sp(start, self.pos), - "format of unicode escape sequences uses braces", - suggestion, - Applicability::MaybeIncorrect, - ); - } else { - err.span_label(span, msg); - err.help( - "format of unicode escape sequences is `\\u{...}`", - ); - } - err.emit(); - false - }; - if ascii_only { - self.err_span_(start, - self.pos, - "unicode escape sequences cannot be used as a \ - byte or in a byte string"); - } - valid - - } - '\n' if delim == '"' => { - self.consume_whitespace(); - true - } - '\r' if delim == '"' && self.ch_is('\n') => { - self.consume_whitespace(); - true - } - c => { - let pos = self.pos; - let msg = if ascii_only { - "unknown byte escape" - } else { - "unknown character escape" - }; - let mut err = self.struct_err_span_char(escaped_pos, pos, msg, c); - err.span_label(self.mk_sp(escaped_pos, pos), msg); - if e == '\r' { - err.help( - "this is an isolated carriage return; consider checking \ - your editor and version control settings", - ); - } - if (e == '{' || e == '}') && !ascii_only { - err.help( - "if used in a formatting string, curly braces are escaped \ - with `{{` and `}}`", - ); - } - err.emit(); - false - } - } - } - } - } - '\t' | '\n' | '\r' | '\'' if delim == '\'' => { - let pos = self.pos; - self.err_span_char(start, - pos, - if ascii_only { - "byte constant must be escaped" - } else { - "character constant must be escaped" - }, - first_source_char); - return false; - } - '\r' => { - if self.ch_is('\n') { - self.bump(); - return true; - } else { - self.err_span_(start, - self.pos, - "bare CR not allowed in string, use \\r instead"); - return false; - } - } - _ => { - if ascii_only && first_source_char > '\x7F' { - let pos = self.pos; - self.err_span_(start, - pos, - "byte constant must be ASCII. Use a \\xHH escape for a \ - non-ASCII byte"); - return false; - } - } - } - true - } - - /// Scan over a `\u{...}` escape - /// - /// At this point, we have already seen the `\` and the `u`, the `{` is the current character. - /// We will read a hex number (with `_` separators), with 1 to 6 actual digits, - /// and pass over the `}`. - fn scan_unicode_escape(&mut self, delim: char) -> bool { - self.bump(); // past the { - let start_bpos = self.pos; - let mut valid = true; - - if let Some('_') = self.ch { - // disallow leading `_` - self.err_span_(self.pos, - self.next_pos, - "invalid start of unicode escape"); - valid = false; - } - - let count = self.scan_digits(16, 16); - - if count > 6 { - self.err_span_(start_bpos, - self.pos, - "overlong unicode escape (must have at most 6 hex digits)"); - valid = false; - } - - loop { - match self.ch { - Some('}') => { - if valid && count == 0 { - self.err_span_(start_bpos, - self.pos, - "empty unicode escape (must have at least 1 hex digit)"); - valid = false; - } - self.bump(); // past the ending `}` - break; - }, - Some(c) => { - if c == delim { - self.err_span_(self.pos, - self.pos, - "unterminated unicode escape (needed a `}`)"); - valid = false; - break; - } else if valid { - self.err_span_char(start_bpos, - self.pos, - "invalid character in unicode escape", - c); - valid = false; - } - }, - None => { - self.fatal_span_(start_bpos, - self.pos, - "unterminated unicode escape (found EOF)").raise(); - } - } - self.bump(); - } - - valid - } - /// Scan over a float exponent. fn scan_float_exponent(&mut self) { if self.ch_is('e') || self.ch_is('E') { @@ -1393,26 +1098,21 @@ impl<'a> StringReader<'a> { self.bump(); let start = self.pos; - // the eof will be picked up by the final `'` check below - let c2 = self.ch.unwrap_or('\x00'); - self.bump(); - // If the character is an ident start not followed by another single // quote, then this is a lifetime name: - if (ident_start(Some(c2)) || c2.is_numeric()) && !self.ch_is('\'') { + let starts_with_number = self.ch.unwrap_or('\x00').is_numeric(); + if (ident_start(self.ch) || starts_with_number) && !self.nextch_is('\'') { + self.bump(); while ident_continue(self.ch) { self.bump(); } // lifetimes shouldn't end with a single quote // if we find one, then this is an invalid character literal if self.ch_is('\'') { - self.err_span_( - start_with_quote, - self.next_pos, - "character literal may only contain one codepoint"); + let id = self.name_from(start); self.bump(); - return Ok(token::Literal(token::Err(Symbol::intern("??")), None)) - + self.validate_char_escape(start_with_quote); + return Ok(token::Literal(token::Char(id), None)) } // Include the leading `'` in the real identifier, for macro @@ -1422,7 +1122,7 @@ impl<'a> StringReader<'a> { self.mk_ident(lifetime_name) }); - if c2.is_numeric() { + if starts_with_number { // this is a recovered lifetime written `'1`, error but accept it self.err_span_( start_with_quote, @@ -1433,58 +1133,30 @@ impl<'a> StringReader<'a> { return Ok(token::Lifetime(ident)); } - - let valid = self.scan_char_or_byte(start, c2, /* ascii_only */ false, '\''); - - if !self.ch_is('\'') { - let pos = self.pos; - - loop { - self.bump(); - if self.ch_is('\'') { - let start = self.src_index(start); - let end = self.src_index(self.pos); - self.bump(); - let span = self.mk_sp(start_with_quote, self.pos); - self.sess.span_diagnostic - .struct_span_err(span, - "character literal may only contain one codepoint") - .span_suggestion( - span, - "if you meant to write a `str` literal, use double quotes", - format!("\"{}\"", &self.src[start..end]), - Applicability::MachineApplicable - ).emit(); - return Ok(token::Literal(token::Err(Symbol::intern("??")), None)) - } - if self.ch_is('\n') || self.is_eof() || self.ch_is('/') { - // Only attempt to infer single line string literals. If we encounter - // a slash, bail out in order to avoid nonsensical suggestion when - // involving comments. - break; - } - } - - self.fatal_span_verbose(start_with_quote, pos, - String::from("character literal may only contain one codepoint")).raise(); - } - - let id = if valid { - self.name_from(start) - } else { - Symbol::intern("0") - }; - - self.bump(); // advance ch past token + let msg = "unterminated character literal"; + let id = self.scan_single_quoted_string(start_with_quote, msg); + self.validate_char_escape(start_with_quote); let suffix = self.scan_optional_raw_name(); - Ok(token::Literal(token::Char(id), suffix)) } 'b' => { self.bump(); let lit = match self.ch { - Some('\'') => self.scan_byte(), - Some('"') => self.scan_byte_string(), + Some('\'') => { + let start_with_quote = self.pos; + self.bump(); + let msg = "unterminated byte constant"; + let id = self.scan_single_quoted_string(start_with_quote, msg); + self.validate_byte_escape(start_with_quote); + token::Byte(id) + }, + Some('"') => { + let start_with_quote = self.pos; + let msg = "unterminated double quote byte string"; + let id = self.scan_double_quoted_string(msg); + self.validate_byte_str_escape(start_with_quote); + token::ByteStr(id) + }, Some('r') => self.scan_raw_byte_string(), _ => unreachable!(), // Should have been a token::Ident above. }; @@ -1493,32 +1165,11 @@ impl<'a> StringReader<'a> { Ok(token::Literal(lit, suffix)) } '"' => { - let start_bpos = self.pos; - let mut valid = true; - self.bump(); - - while !self.ch_is('"') { - if self.is_eof() { - let last_bpos = self.pos; - self.fatal_span_(start_bpos, - last_bpos, - "unterminated double quote string").raise(); - } - - let ch_start = self.pos; - let ch = self.ch.unwrap(); - self.bump(); - valid &= self.scan_char_or_byte(ch_start, ch, /* ascii_only */ false, '"'); - } - // adjust for the ASCII " at the start of the literal - let id = if valid { - self.name_from(start_bpos + BytePos(1)) - } else { - Symbol::intern("??") - }; - self.bump(); + let start_with_quote = self.pos; + let msg = "unterminated double quote string"; + let id = self.scan_double_quoted_string(msg); + self.validate_str_escape(start_with_quote); let suffix = self.scan_optional_raw_name(); - Ok(token::Literal(token::Str_(id), suffix)) } 'r' => { @@ -1659,12 +1310,6 @@ impl<'a> StringReader<'a> { } } - fn consume_whitespace(&mut self) { - while is_pattern_whitespace(self.ch) && !self.is_eof() { - self.bump(); - } - } - fn read_to_eol(&mut self) -> String { let mut val = String::new(); while !self.ch_is('\n') && !self.is_eof() { @@ -1698,73 +1343,63 @@ impl<'a> StringReader<'a> { (self.ch_is('#') && self.nextch_is('!') && !self.nextnextch_is('[')) } - fn scan_byte(&mut self) -> token::Lit { - self.bump(); + fn scan_single_quoted_string(&mut self, + start_with_quote: BytePos, + unterminated_msg: &str) -> ast::Name { + // assumes that first `'` is consumed let start = self.pos; - - // the eof will be picked up by the final `'` check below - let c2 = self.ch.unwrap_or('\x00'); - self.bump(); - - let valid = self.scan_char_or_byte(start, - c2, - // ascii_only = - true, - '\''); - if !self.ch_is('\'') { - // Byte offsetting here is okay because the - // character before position `start` are an - // ascii single quote and ascii 'b'. - let pos = self.pos; - self.fatal_span_verbose(start - BytePos(2), - pos, - "unterminated byte constant".to_string()).raise(); - } - - let id = if valid { - self.name_from(start) + // lex `'''` as a single char, for recovery + if self.ch_is('\'') && self.nextch_is('\'') { + self.bump(); } else { - Symbol::intern("?") - }; - self.bump(); // advance ch past token - - token::Byte(id) - } + let mut first = true; + loop { + if self.ch_is('\'') { + break; + } + if self.ch_is('\\') && (self.nextch_is('\'') || self.nextch_is('\\')) { + self.bump(); + self.bump(); + } else { + // Only attempt to infer single line string literals. If we encounter + // a slash, bail out in order to avoid nonsensical suggestion when + // involving comments. + if self.is_eof() + || (self.ch_is('/') && !first) + || (self.ch_is('\n') && !self.nextch_is('\'')) { + + self.fatal_span_(start_with_quote, self.pos, unterminated_msg.into()) + .raise() + } + self.bump(); + } + first = false; + } + } - #[inline] - fn scan_byte_escape(&mut self, delim: char, below_0x7f_only: bool) -> bool { - self.scan_hex_digits(2, delim, below_0x7f_only) + let id = self.name_from(start); + self.bump(); + id } - fn scan_byte_string(&mut self) -> token::Lit { + fn scan_double_quoted_string(&mut self, unterminated_msg: &str) -> ast::Name { + debug_assert!(self.ch_is('\"')); + let start_with_quote = self.pos; self.bump(); let start = self.pos; - let mut valid = true; - while !self.ch_is('"') { if self.is_eof() { let pos = self.pos; - self.fatal_span_(start, pos, "unterminated double quote byte string").raise(); + self.fatal_span_(start_with_quote, pos, unterminated_msg).raise(); + } + if self.ch_is('\\') && (self.nextch_is('\\') || self.nextch_is('"')) { + self.bump(); } - - let ch_start = self.pos; - let ch = self.ch.unwrap(); self.bump(); - valid &= self.scan_char_or_byte(ch_start, - ch, - // ascii_only = - true, - '"'); } - - let id = if valid { - self.name_from(start) - } else { - Symbol::intern("??") - }; + let id = self.name_from(start); self.bump(); - - token::ByteStr(id) + id } fn scan_raw_byte_string(&mut self) -> token::Lit { @@ -1826,6 +1461,70 @@ impl<'a> StringReader<'a> { token::ByteStrRaw(self.name_from_to(content_start_bpos, content_end_bpos), hash_count) } + + fn validate_char_escape(&self, start_with_quote: BytePos) { + self.with_str_from_to(start_with_quote + BytePos(1), self.pos - BytePos(1), |lit| { + if let Err((off, err)) = unescape::unescape_char(lit) { + emit_unescape_error( + &self.sess.span_diagnostic, + lit, + self.mk_sp(start_with_quote, self.pos), + unescape::Mode::Char, + 0..off, + err, + ) + } + }); + } + + fn validate_byte_escape(&self, start_with_quote: BytePos) { + self.with_str_from_to(start_with_quote + BytePos(1), self.pos - BytePos(1), |lit| { + if let Err((off, err)) = unescape::unescape_byte(lit) { + emit_unescape_error( + &self.sess.span_diagnostic, + lit, + self.mk_sp(start_with_quote, self.pos), + unescape::Mode::Byte, + 0..off, + err, + ) + } + }); + } + + fn validate_str_escape(&self, start_with_quote: BytePos) { + self.with_str_from_to(start_with_quote + BytePos(1), self.pos - BytePos(1), |lit| { + unescape::unescape_str(lit, &mut |range, c| { + if let Err(err) = c { + emit_unescape_error( + &self.sess.span_diagnostic, + lit, + self.mk_sp(start_with_quote, self.pos), + unescape::Mode::Str, + range, + err, + ) + } + }) + }); + } + + fn validate_byte_str_escape(&self, start_with_quote: BytePos) { + self.with_str_from_to(start_with_quote + BytePos(1), self.pos - BytePos(1), |lit| { + unescape::unescape_byte_str(lit, &mut |range, c| { + if let Err(err) = c { + emit_unescape_error( + &self.sess.span_diagnostic, + lit, + self.mk_sp(start_with_quote, self.pos), + unescape::Mode::ByteStr, + range, + err, + ) + } + }) + }); + } } // This tests the character for the unicode property 'PATTERN_WHITE_SPACE' which diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 1abc7832ffa0f..d6d4f8e8f0429 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -18,7 +18,6 @@ use log::debug; use rustc_data_structures::fx::FxHashSet; use std::borrow::Cow; -use std::iter; use std::path::{Path, PathBuf}; use std::str; @@ -33,6 +32,11 @@ pub mod attr; pub mod classify; +pub(crate) mod unescape; +use unescape::{unescape_str, unescape_char, unescape_byte_str, unescape_byte, EscapeError}; + +pub(crate) mod unescape_error_reporting; + /// Info about a parsing session. pub struct ParseSess { pub span_diagnostic: Handler, @@ -306,133 +310,6 @@ pub fn stream_to_parser(sess: &ParseSess, stream: TokenStream) -> Parser<'_> { Parser::new(sess, stream, None, true, false) } -/// Parses a string representing a character literal into its final form. -/// Rather than just accepting/rejecting a given literal, unescapes it as -/// well. Can take any slice prefixed by a character escape. Returns the -/// character and the number of characters consumed. -fn char_lit(lit: &str, diag: Option<(Span, &Handler)>) -> (char, isize) { - use std::char; - - // Handle non-escaped chars first. - if lit.as_bytes()[0] != b'\\' { - // If the first byte isn't '\\' it might part of a multi-byte char, so - // get the char with chars(). - let c = lit.chars().next().unwrap(); - return (c, 1); - } - - // Handle escaped chars. - match lit.as_bytes()[1] as char { - '"' => ('"', 2), - 'n' => ('\n', 2), - 'r' => ('\r', 2), - 't' => ('\t', 2), - '\\' => ('\\', 2), - '\'' => ('\'', 2), - '0' => ('\0', 2), - 'x' => { - let v = u32::from_str_radix(&lit[2..4], 16).unwrap(); - let c = char::from_u32(v).unwrap(); - (c, 4) - } - 'u' => { - assert_eq!(lit.as_bytes()[2], b'{'); - let idx = lit.find('}').unwrap(); - - // All digits and '_' are ascii, so treat each byte as a char. - let mut v: u32 = 0; - for c in lit[3..idx].bytes() { - let c = char::from(c); - if c != '_' { - let x = c.to_digit(16).unwrap(); - v = v.checked_mul(16).unwrap().checked_add(x).unwrap(); - } - } - let c = char::from_u32(v).unwrap_or_else(|| { - if let Some((span, diag)) = diag { - let mut diag = diag.struct_span_err(span, "invalid unicode character escape"); - if v > 0x10FFFF { - diag.help("unicode escape must be at most 10FFFF").emit(); - } else { - diag.help("unicode escape must not be a surrogate").emit(); - } - } - '\u{FFFD}' - }); - (c, (idx + 1) as isize) - } - _ => panic!("lexer should have rejected a bad character escape {}", lit) - } -} - -/// Parses a string representing a string literal into its final form. Does unescaping. -fn str_lit(lit: &str, diag: Option<(Span, &Handler)>) -> String { - debug!("str_lit: given {}", lit.escape_default()); - let mut res = String::with_capacity(lit.len()); - - let error = |i| format!("lexer should have rejected {} at {}", lit, i); - - /// Eat everything up to a non-whitespace. - fn eat<'a>(it: &mut iter::Peekable>) { - loop { - match it.peek().map(|x| x.1) { - Some(' ') | Some('\n') | Some('\r') | Some('\t') => { - it.next(); - }, - _ => { break; } - } - } - } - - let mut chars = lit.char_indices().peekable(); - while let Some((i, c)) = chars.next() { - match c { - '\\' => { - let ch = chars.peek().unwrap_or_else(|| { - panic!("{}", error(i)) - }).1; - - if ch == '\n' { - eat(&mut chars); - } else if ch == '\r' { - chars.next(); - let ch = chars.peek().unwrap_or_else(|| { - panic!("{}", error(i)) - }).1; - - if ch != '\n' { - panic!("lexer accepted bare CR"); - } - eat(&mut chars); - } else { - // otherwise, a normal escape - let (c, n) = char_lit(&lit[i..], diag); - for _ in 0..n - 1 { // we don't need to move past the first \ - chars.next(); - } - res.push(c); - } - }, - '\r' => { - let ch = chars.peek().unwrap_or_else(|| { - panic!("{}", error(i)) - }).1; - - if ch != '\n' { - panic!("lexer accepted bare CR"); - } - chars.next(); - res.push('\n'); - } - c => res.push(c), - } - } - - res.shrink_to_fit(); // probably not going to do anything, unless there was an escape. - debug!("parse_str_lit: returning {}", res); - res -} - /// Parses a string representing a raw string literal into its final form. The /// only operation this does is convert embedded CRLF into a single LF. fn raw_str_lit(lit: &str) -> String { @@ -475,9 +352,23 @@ crate fn lit_token(lit: token::Lit, suf: Option, diag: Option<(Span, &Ha use ast::LitKind; match lit { - token::Byte(i) => (true, Some(LitKind::Byte(byte_lit(&i.as_str()).0))), - token::Char(i) => (true, Some(LitKind::Char(char_lit(&i.as_str(), diag).0))), - token::Err(i) => (true, Some(LitKind::Err(i))), + token::Byte(i) => { + let lit_kind = match unescape_byte(&i.as_str()) { + Ok(c) => LitKind::Byte(c), + Err((_, EscapeError::MoreThanOneChar)) => LitKind::Err(i), + Err(_) => LitKind::Byte(0), + }; + (true, Some(lit_kind)) + }, + token::Char(i) => { + let lit_kind = match unescape_char(&i.as_str()) { + Ok(c) => LitKind::Char(c), + Err((_, EscapeError::MoreThanOneChar)) => LitKind::Err(i), + Err(_) => LitKind::Char('\u{FFFD}'), + }; + (true, Some(lit_kind)) + }, + token::Err(i) => (true, Some(LitKind::Err(i))), // There are some valid suffixes for integer and float literals, // so all the handling is done internally. @@ -491,7 +382,14 @@ crate fn lit_token(lit: token::Lit, suf: Option, diag: Option<(Span, &Ha // string in the Token. let s = &sym.as_str(); if s.as_bytes().iter().any(|&c| c == b'\\' || c == b'\r') { - sym = Symbol::intern(&str_lit(s, diag)); + let mut buf = String::with_capacity(s.len()); + unescape_str(s, &mut |_, unescaped_char| { + match unescaped_char { + Ok(c) => buf.push(c), + Err(_) => buf.push('\u{FFFD}'), + } + }); + sym = Symbol::intern(&buf) } (true, Some(LitKind::Str(sym, ast::StrStyle::Cooked))) } @@ -504,7 +402,16 @@ crate fn lit_token(lit: token::Lit, suf: Option, diag: Option<(Span, &Ha (true, Some(LitKind::Str(sym, ast::StrStyle::Raw(n)))) } token::ByteStr(i) => { - (true, Some(LitKind::ByteStr(byte_str_lit(&i.as_str())))) + let s = &i.as_str(); + let mut buf = Vec::with_capacity(s.len()); + unescape_byte_str(s, &mut |_, unescaped_byte| { + match unescaped_byte { + Ok(c) => buf.push(c), + Err(_) => buf.push(0), + } + }); + buf.shrink_to_fit(); + (true, Some(LitKind::ByteStr(Lrc::new(buf)))) } token::ByteStrRaw(i, _) => { (true, Some(LitKind::ByteStr(Lrc::new(i.to_string().into_bytes())))) @@ -559,95 +466,6 @@ fn float_lit(s: &str, suffix: Option, diag: Option<(Span, &Handler)>) filtered_float_lit(Symbol::intern(s), suffix, diag) } -/// Parses a string representing a byte literal into its final form. Similar to `char_lit`. -fn byte_lit(lit: &str) -> (u8, usize) { - let err = |i| format!("lexer accepted invalid byte literal {} step {}", lit, i); - - if lit.len() == 1 { - (lit.as_bytes()[0], 1) - } else { - assert_eq!(lit.as_bytes()[0], b'\\', "{}", err(0)); - let b = match lit.as_bytes()[1] { - b'"' => b'"', - b'n' => b'\n', - b'r' => b'\r', - b't' => b'\t', - b'\\' => b'\\', - b'\'' => b'\'', - b'0' => b'\0', - _ => { - match u64::from_str_radix(&lit[2..4], 16).ok() { - Some(c) => - if c > 0xFF { - panic!(err(2)) - } else { - return (c as u8, 4) - }, - None => panic!(err(3)) - } - } - }; - (b, 2) - } -} - -fn byte_str_lit(lit: &str) -> Lrc> { - let mut res = Vec::with_capacity(lit.len()); - - let error = |i| panic!("lexer should have rejected {} at {}", lit, i); - - /// Eat everything up to a non-whitespace. - fn eat>(it: &mut iter::Peekable) { - loop { - match it.peek().map(|x| x.1) { - Some(b' ') | Some(b'\n') | Some(b'\r') | Some(b'\t') => { - it.next(); - }, - _ => { break; } - } - } - } - - // byte string literals *must* be ASCII, but the escapes don't have to be - let mut chars = lit.bytes().enumerate().peekable(); - loop { - match chars.next() { - Some((i, b'\\')) => { - match chars.peek().unwrap_or_else(|| error(i)).1 { - b'\n' => eat(&mut chars), - b'\r' => { - chars.next(); - if chars.peek().unwrap_or_else(|| error(i)).1 != b'\n' { - panic!("lexer accepted bare CR"); - } - eat(&mut chars); - } - _ => { - // otherwise, a normal escape - let (c, n) = byte_lit(&lit[i..]); - // we don't need to move past the first \ - for _ in 0..n - 1 { - chars.next(); - } - res.push(c); - } - } - }, - Some((i, b'\r')) => { - if chars.peek().unwrap_or_else(|| error(i)).1 != b'\n' { - panic!("lexer accepted bare CR"); - } - chars.next(); - res.push(b'\n'); - } - Some((_, c)) => res.push(c), - None => break, - } - } - - Lrc::new(res) -} - fn integer_lit(s: &str, suffix: Option, diag: Option<(Span, &Handler)>) -> Option { // s can only be ascii, byte indexing is fine diff --git a/src/libsyntax/parse/unescape.rs b/src/libsyntax/parse/unescape.rs new file mode 100644 index 0000000000000..90ee549db017b --- /dev/null +++ b/src/libsyntax/parse/unescape.rs @@ -0,0 +1,515 @@ +//! Utilities for validating string and char literals and turning them into +//! values they represent. + +use std::str::Chars; +use std::ops::Range; + +#[derive(Debug, PartialEq, Eq)] +pub(crate) enum EscapeError { + ZeroChars, + MoreThanOneChar, + + LoneSlash, + InvalidEscape, + BareCarriageReturn, + EscapeOnlyChar, + + TooShortHexEscape, + InvalidCharInHexEscape, + OutOfRangeHexEscape, + + NoBraceInUnicodeEscape, + InvalidCharInUnicodeEscape, + EmptyUnicodeEscape, + UnclosedUnicodeEscape, + LeadingUnderscoreUnicodeEscape, + OverlongUnicodeEscape, + LoneSurrogateUnicodeEscape, + OutOfRangeUnicodeEscape, + + UnicodeEscapeInByte, + NonAsciiCharInByte, +} + +/// Takes a contents of a char literal (without quotes), and returns an +/// unescaped char or an error +pub(crate) fn unescape_char(literal_text: &str) -> Result { + let mut chars = literal_text.chars(); + unescape_char_or_byte(&mut chars, Mode::Char) + .map_err(|err| (literal_text.len() - chars.as_str().len(), err)) +} + +/// Takes a contents of a string literal (without quotes) and produces a +/// sequence of escaped characters or errors. +pub(crate) fn unescape_str(literal_text: &str, callback: &mut F) +where + F: FnMut(Range, Result), +{ + unescape_str_or_byte_str(literal_text, Mode::Str, callback) +} + +pub(crate) fn unescape_byte(literal_text: &str) -> Result { + let mut chars = literal_text.chars(); + unescape_char_or_byte(&mut chars, Mode::Byte) + .map(byte_from_char) + .map_err(|err| (literal_text.len() - chars.as_str().len(), err)) +} + +/// Takes a contents of a string literal (without quotes) and produces a +/// sequence of escaped characters or errors. +pub(crate) fn unescape_byte_str(literal_text: &str, callback: &mut F) +where + F: FnMut(Range, Result), +{ + unescape_str_or_byte_str(literal_text, Mode::ByteStr, &mut |range, char| { + callback(range, char.map(byte_from_char)) + }) +} + +#[derive(Debug, Clone, Copy)] +pub(crate) enum Mode { + Char, + Str, + Byte, + ByteStr, +} + +impl Mode { + fn in_single_quotes(self) -> bool { + match self { + Mode::Char | Mode::Byte => true, + Mode::Str | Mode::ByteStr => false, + } + } + + pub(crate) fn in_double_quotes(self) -> bool { + !self.in_single_quotes() + } + + pub(crate) fn is_bytes(self) -> bool { + match self { + Mode::Byte | Mode::ByteStr => true, + Mode::Char | Mode::Str => false, + } + } +} + + +fn scan_escape(first_char: char, chars: &mut Chars<'_>, mode: Mode) -> Result { + if first_char != '\\' { + return match first_char { + '\t' | '\n' => Err(EscapeError::EscapeOnlyChar), + '\r' => Err(if chars.clone().next() == Some('\n') { + EscapeError::EscapeOnlyChar + } else { + EscapeError::BareCarriageReturn + }), + '\'' if mode.in_single_quotes() => Err(EscapeError::EscapeOnlyChar), + '"' if mode.in_double_quotes() => Err(EscapeError::EscapeOnlyChar), + _ => { + if mode.is_bytes() && !first_char.is_ascii() { + return Err(EscapeError::NonAsciiCharInByte); + } + Ok(first_char) + } + }; + } + + let second_char = chars.next().ok_or(EscapeError::LoneSlash)?; + + let res = match second_char { + '"' => '"', + 'n' => '\n', + 'r' => '\r', + 't' => '\t', + '\\' => '\\', + '\'' => '\'', + '0' => '\0', + + 'x' => { + let hi = chars.next().ok_or(EscapeError::TooShortHexEscape)?; + let hi = hi.to_digit(16).ok_or(EscapeError::InvalidCharInHexEscape)?; + + let lo = chars.next().ok_or(EscapeError::TooShortHexEscape)?; + let lo = lo.to_digit(16).ok_or(EscapeError::InvalidCharInHexEscape)?; + + let value = hi * 16 + lo; + + if !mode.is_bytes() && !is_ascii(value) { + return Err(EscapeError::OutOfRangeHexEscape); + } + let value = value as u8; + + value as char + } + + 'u' => { + if chars.next() != Some('{') { + return Err(EscapeError::NoBraceInUnicodeEscape); + } + + let mut n_digits = 1; + let mut value: u32 = match chars.next().ok_or(EscapeError::UnclosedUnicodeEscape)? { + '_' => return Err(EscapeError::LeadingUnderscoreUnicodeEscape), + '}' => return Err(EscapeError::EmptyUnicodeEscape), + c => c.to_digit(16).ok_or(EscapeError::InvalidCharInUnicodeEscape)?, + }; + + loop { + match chars.next() { + None => return Err(EscapeError::UnclosedUnicodeEscape), + Some('_') => continue, + Some('}') => { + if n_digits > 6 { + return Err(EscapeError::OverlongUnicodeEscape); + } + if mode.is_bytes() { + return Err(EscapeError::UnicodeEscapeInByte); + } + + break std::char::from_u32(value).ok_or_else(|| { + if value > 0x10FFFF { + EscapeError::OutOfRangeUnicodeEscape + } else { + EscapeError::LoneSurrogateUnicodeEscape + } + })?; + } + Some(c) => { + let digit = c.to_digit(16).ok_or(EscapeError::InvalidCharInUnicodeEscape)?; + n_digits += 1; + if n_digits > 6 { + continue; + } + let digit = digit as u32; + value = value * 16 + digit; + } + }; + } + } + _ => return Err(EscapeError::InvalidEscape), + }; + Ok(res) +} + +fn unescape_char_or_byte(chars: &mut Chars<'_>, mode: Mode) -> Result { + let first_char = chars.next().ok_or(EscapeError::ZeroChars)?; + let res = scan_escape(first_char, chars, mode)?; + if chars.next().is_some() { + return Err(EscapeError::MoreThanOneChar); + } + Ok(res) +} + +/// Takes a contents of a string literal (without quotes) and produces a +/// sequence of escaped characters or errors. +fn unescape_str_or_byte_str(src: &str, mode: Mode, callback: &mut F) +where + F: FnMut(Range, Result), +{ + assert!(mode.in_double_quotes()); + let initial_len = src.len(); + let mut chars = src.chars(); + while let Some(first_char) = chars.next() { + let start = initial_len - chars.as_str().len() - first_char.len_utf8(); + + let unescaped_char = match first_char { + '\\' => { + let (second_char, third_char) = { + let mut chars = chars.clone(); + (chars.next(), chars.next()) + }; + match (second_char, third_char) { + (Some('\n'), _) | (Some('\r'), Some('\n')) => { + skip_ascii_whitespace(&mut chars); + continue; + } + _ => scan_escape(first_char, &mut chars, mode), + } + } + '\r' => { + let second_char = chars.clone().next(); + if second_char == Some('\n') { + chars.next(); + Ok('\n') + } else { + scan_escape(first_char, &mut chars, mode) + } + } + '\n' => Ok('\n'), + '\t' => Ok('\t'), + _ => scan_escape(first_char, &mut chars, mode), + }; + let end = initial_len - chars.as_str().len(); + callback(start..end, unescaped_char); + } + + fn skip_ascii_whitespace(chars: &mut Chars<'_>) { + let str = chars.as_str(); + let first_non_space = str + .bytes() + .position(|b| b != b' ' && b != b'\t' && b != b'\n' && b != b'\r') + .unwrap_or(str.len()); + *chars = str[first_non_space..].chars() + } +} + +fn byte_from_char(c: char) -> u8 { + let res = c as u32; + assert!(res <= u8::max_value() as u32, "guaranteed because of Mode::Byte"); + res as u8 +} + +fn is_ascii(x: u32) -> bool { + x <= 0x7F +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_unescape_char_bad() { + fn check(literal_text: &str, expected_error: EscapeError) { + let actual_result = unescape_char(literal_text).map_err(|(_offset, err)| err); + assert_eq!(actual_result, Err(expected_error)); + } + + check("", EscapeError::ZeroChars); + check(r"\", EscapeError::LoneSlash); + + check("\n", EscapeError::EscapeOnlyChar); + check("\r\n", EscapeError::EscapeOnlyChar); + check("\t", EscapeError::EscapeOnlyChar); + check("'", EscapeError::EscapeOnlyChar); + check("\r", EscapeError::BareCarriageReturn); + + check("spam", EscapeError::MoreThanOneChar); + check(r"\x0ff", EscapeError::MoreThanOneChar); + check(r#"\"a"#, EscapeError::MoreThanOneChar); + check(r"\na", EscapeError::MoreThanOneChar); + check(r"\ra", EscapeError::MoreThanOneChar); + check(r"\ta", EscapeError::MoreThanOneChar); + check(r"\\a", EscapeError::MoreThanOneChar); + check(r"\'a", EscapeError::MoreThanOneChar); + check(r"\0a", EscapeError::MoreThanOneChar); + check(r"\u{0}x", EscapeError::MoreThanOneChar); + check(r"\u{1F63b}}", EscapeError::MoreThanOneChar); + + check(r"\v", EscapeError::InvalidEscape); + check(r"\💩", EscapeError::InvalidEscape); + check(r"\●", EscapeError::InvalidEscape); + + check(r"\x", EscapeError::TooShortHexEscape); + check(r"\x0", EscapeError::TooShortHexEscape); + check(r"\xf", EscapeError::TooShortHexEscape); + check(r"\xa", EscapeError::TooShortHexEscape); + check(r"\xx", EscapeError::InvalidCharInHexEscape); + check(r"\xы", EscapeError::InvalidCharInHexEscape); + check(r"\x🦀", EscapeError::InvalidCharInHexEscape); + check(r"\xtt", EscapeError::InvalidCharInHexEscape); + check(r"\xff", EscapeError::OutOfRangeHexEscape); + check(r"\xFF", EscapeError::OutOfRangeHexEscape); + check(r"\x80", EscapeError::OutOfRangeHexEscape); + + check(r"\u", EscapeError::NoBraceInUnicodeEscape); + check(r"\u[0123]", EscapeError::NoBraceInUnicodeEscape); + check(r"\u{0x}", EscapeError::InvalidCharInUnicodeEscape); + check(r"\u{", EscapeError::UnclosedUnicodeEscape); + check(r"\u{0000", EscapeError::UnclosedUnicodeEscape); + check(r"\u{}", EscapeError::EmptyUnicodeEscape); + check(r"\u{_0000}", EscapeError::LeadingUnderscoreUnicodeEscape); + check(r"\u{0000000}", EscapeError::OverlongUnicodeEscape); + check(r"\u{FFFFFF}", EscapeError::OutOfRangeUnicodeEscape); + check(r"\u{ffffff}", EscapeError::OutOfRangeUnicodeEscape); + check(r"\u{ffffff}", EscapeError::OutOfRangeUnicodeEscape); + + check(r"\u{DC00}", EscapeError::LoneSurrogateUnicodeEscape); + check(r"\u{DDDD}", EscapeError::LoneSurrogateUnicodeEscape); + check(r"\u{DFFF}", EscapeError::LoneSurrogateUnicodeEscape); + + check(r"\u{D800}", EscapeError::LoneSurrogateUnicodeEscape); + check(r"\u{DAAA}", EscapeError::LoneSurrogateUnicodeEscape); + check(r"\u{DBFF}", EscapeError::LoneSurrogateUnicodeEscape); + } + + #[test] + fn test_unescape_char_good() { + fn check(literal_text: &str, expected_char: char) { + let actual_result = unescape_char(literal_text); + assert_eq!(actual_result, Ok(expected_char)); + } + + check("a", 'a'); + check("ы", 'ы'); + check("🦀", '🦀'); + + check(r#"\""#, '"'); + check(r"\n", '\n'); + check(r"\r", '\r'); + check(r"\t", '\t'); + check(r"\\", '\\'); + check(r"\'", '\''); + check(r"\0", '\0'); + + check(r"\x00", '\0'); + check(r"\x5a", 'Z'); + check(r"\x5A", 'Z'); + check(r"\x7f", 127 as char); + + check(r"\u{0}", '\0'); + check(r"\u{000000}", '\0'); + check(r"\u{41}", 'A'); + check(r"\u{0041}", 'A'); + check(r"\u{00_41}", 'A'); + check(r"\u{4__1__}", 'A'); + check(r"\u{1F63b}", '😻'); + } + + #[test] + fn test_unescape_str_good() { + fn check(literal_text: &str, expected: &str) { + let mut buf = Ok(String::with_capacity(literal_text.len())); + unescape_str(literal_text, &mut |range, c| { + if let Ok(b) = &mut buf { + match c { + Ok(c) => b.push(c), + Err(e) => buf = Err((range, e)), + } + } + }); + let buf = buf.as_ref().map(|it| it.as_ref()); + assert_eq!(buf, Ok(expected)) + } + + check("foo", "foo"); + check("", ""); + check(" \t\n\r\n", " \t\n\n"); + + check("hello \\\n world", "hello world"); + check("hello \\\r\n world", "hello world"); + check("thread's", "thread's") + } + + #[test] + fn test_unescape_byte_bad() { + fn check(literal_text: &str, expected_error: EscapeError) { + let actual_result = unescape_byte(literal_text).map_err(|(_offset, err)| err); + assert_eq!(actual_result, Err(expected_error)); + } + + check("", EscapeError::ZeroChars); + check(r"\", EscapeError::LoneSlash); + + check("\n", EscapeError::EscapeOnlyChar); + check("\r\n", EscapeError::EscapeOnlyChar); + check("\t", EscapeError::EscapeOnlyChar); + check("'", EscapeError::EscapeOnlyChar); + check("\r", EscapeError::BareCarriageReturn); + + check("spam", EscapeError::MoreThanOneChar); + check(r"\x0ff", EscapeError::MoreThanOneChar); + check(r#"\"a"#, EscapeError::MoreThanOneChar); + check(r"\na", EscapeError::MoreThanOneChar); + check(r"\ra", EscapeError::MoreThanOneChar); + check(r"\ta", EscapeError::MoreThanOneChar); + check(r"\\a", EscapeError::MoreThanOneChar); + check(r"\'a", EscapeError::MoreThanOneChar); + check(r"\0a", EscapeError::MoreThanOneChar); + + check(r"\v", EscapeError::InvalidEscape); + check(r"\💩", EscapeError::InvalidEscape); + check(r"\●", EscapeError::InvalidEscape); + + check(r"\x", EscapeError::TooShortHexEscape); + check(r"\x0", EscapeError::TooShortHexEscape); + check(r"\xa", EscapeError::TooShortHexEscape); + check(r"\xf", EscapeError::TooShortHexEscape); + check(r"\xx", EscapeError::InvalidCharInHexEscape); + check(r"\xы", EscapeError::InvalidCharInHexEscape); + check(r"\x🦀", EscapeError::InvalidCharInHexEscape); + check(r"\xtt", EscapeError::InvalidCharInHexEscape); + + check(r"\u", EscapeError::NoBraceInUnicodeEscape); + check(r"\u[0123]", EscapeError::NoBraceInUnicodeEscape); + check(r"\u{0x}", EscapeError::InvalidCharInUnicodeEscape); + check(r"\u{", EscapeError::UnclosedUnicodeEscape); + check(r"\u{0000", EscapeError::UnclosedUnicodeEscape); + check(r"\u{}", EscapeError::EmptyUnicodeEscape); + check(r"\u{_0000}", EscapeError::LeadingUnderscoreUnicodeEscape); + check(r"\u{0000000}", EscapeError::OverlongUnicodeEscape); + + check("ы", EscapeError::NonAsciiCharInByte); + check("🦀", EscapeError::NonAsciiCharInByte); + + check(r"\u{0}", EscapeError::UnicodeEscapeInByte); + check(r"\u{000000}", EscapeError::UnicodeEscapeInByte); + check(r"\u{41}", EscapeError::UnicodeEscapeInByte); + check(r"\u{0041}", EscapeError::UnicodeEscapeInByte); + check(r"\u{00_41}", EscapeError::UnicodeEscapeInByte); + check(r"\u{4__1__}", EscapeError::UnicodeEscapeInByte); + check(r"\u{1F63b}", EscapeError::UnicodeEscapeInByte); + check(r"\u{0}x", EscapeError::UnicodeEscapeInByte); + check(r"\u{1F63b}}", EscapeError::UnicodeEscapeInByte); + check(r"\u{FFFFFF}", EscapeError::UnicodeEscapeInByte); + check(r"\u{ffffff}", EscapeError::UnicodeEscapeInByte); + check(r"\u{ffffff}", EscapeError::UnicodeEscapeInByte); + check(r"\u{DC00}", EscapeError::UnicodeEscapeInByte); + check(r"\u{DDDD}", EscapeError::UnicodeEscapeInByte); + check(r"\u{DFFF}", EscapeError::UnicodeEscapeInByte); + check(r"\u{D800}", EscapeError::UnicodeEscapeInByte); + check(r"\u{DAAA}", EscapeError::UnicodeEscapeInByte); + check(r"\u{DBFF}", EscapeError::UnicodeEscapeInByte); + } + + #[test] + fn test_unescape_byte_good() { + fn check(literal_text: &str, expected_byte: u8) { + let actual_result = unescape_byte(literal_text); + assert_eq!(actual_result, Ok(expected_byte)); + } + + check("a", b'a'); + + check(r#"\""#, b'"'); + check(r"\n", b'\n'); + check(r"\r", b'\r'); + check(r"\t", b'\t'); + check(r"\\", b'\\'); + check(r"\'", b'\''); + check(r"\0", b'\0'); + + check(r"\x00", b'\0'); + check(r"\x5a", b'Z'); + check(r"\x5A", b'Z'); + check(r"\x7f", 127); + check(r"\x80", 128); + check(r"\xff", 255); + check(r"\xFF", 255); + } + + #[test] + fn test_unescape_byte_str_good() { + fn check(literal_text: &str, expected: &[u8]) { + let mut buf = Ok(Vec::with_capacity(literal_text.len())); + unescape_byte_str(literal_text, &mut |range, c| { + if let Ok(b) = &mut buf { + match c { + Ok(c) => b.push(c), + Err(e) => buf = Err((range, e)), + } + } + }); + let buf = buf.as_ref().map(|it| it.as_ref()); + assert_eq!(buf, Ok(expected)) + } + + check("foo", b"foo"); + check("", b""); + check(" \t\n\r\n", b" \t\n\n"); + + check("hello \\\n world", b"hello world"); + check("hello \\\r\n world", b"hello world"); + check("thread's", b"thread's") + } +} diff --git a/src/libsyntax/parse/unescape_error_reporting.rs b/src/libsyntax/parse/unescape_error_reporting.rs new file mode 100644 index 0000000000000..22777c0884f47 --- /dev/null +++ b/src/libsyntax/parse/unescape_error_reporting.rs @@ -0,0 +1,200 @@ +//! Utilities for rendering escape sequence errors as diagnostics. + +use std::ops::Range; +use std::iter::once; + +use syntax_pos::{Span, BytePos}; + +use crate::errors::{Handler, Applicability}; + +use super::unescape::{EscapeError, Mode}; + +pub(crate) fn emit_unescape_error( + handler: &Handler, + // interior part of the literal, without quotes + lit: &str, + // full span of the literal, including quotes + span_with_quotes: Span, + mode: Mode, + // range of the error inside `lit` + range: Range, + error: EscapeError, +) { + log::debug!("emit_unescape_error: {:?}, {:?}, {:?}, {:?}, {:?}", + lit, span_with_quotes, mode, range, error); + let span = { + let Range { start, end } = range; + let (start, end) = (start as u32, end as u32); + let lo = span_with_quotes.lo() + BytePos(start + 1); + let hi = lo + BytePos(end - start); + span_with_quotes + .with_lo(lo) + .with_hi(hi) + }; + let last_char = || { + let c = lit[range.clone()].chars().rev().next().unwrap(); + let span = span.with_lo(span.hi() - BytePos(c.len_utf8() as u32)); + (c, span) + }; + match error { + EscapeError::LoneSurrogateUnicodeEscape => { + handler.struct_span_err(span, "invalid unicode character escape") + .help("unicode escape must not be a surrogate") + .emit(); + } + EscapeError::OutOfRangeUnicodeEscape => { + handler.struct_span_err(span, "invalid unicode character escape") + .help("unicode escape must be at most 10FFFF") + .emit(); + } + EscapeError::MoreThanOneChar => { + handler + .struct_span_err( + span_with_quotes, + "character literal may only contain one codepoint", + ) + .span_suggestion( + span_with_quotes, + "if you meant to write a `str` literal, use double quotes", + format!("\"{}\"", lit), + Applicability::MachineApplicable, + ).emit() + } + EscapeError::EscapeOnlyChar => { + let (c, _span) = last_char(); + + let mut msg = if mode.is_bytes() { + "byte constant must be escaped: " + } else { + "character constant must be escaped: " + }.to_string(); + push_escaped_char(&mut msg, c); + + handler.span_err(span, msg.as_str()) + } + EscapeError::BareCarriageReturn => { + let msg = if mode.in_double_quotes() { + "bare CR not allowed in string, use \\r instead" + } else { + "character constant must be escaped: \\r" + }; + handler.span_err(span, msg); + } + EscapeError::InvalidEscape => { + let (c, span) = last_char(); + + let label = if mode.is_bytes() { + "unknown byte escape" + } else { + "unknown character escape" + }; + let mut msg = label.to_string(); + msg.push_str(": "); + push_escaped_char(&mut msg, c); + + let mut diag = handler.struct_span_err(span, msg.as_str()); + diag.span_label(span, label); + if c == '{' || c == '}' && !mode.is_bytes() { + diag.help("if used in a formatting string, \ + curly braces are escaped with `{{` and `}}`"); + } else if c == '\r' { + diag.help("this is an isolated carriage return; \ + consider checking your editor and version control settings"); + } + diag.emit(); + } + EscapeError::TooShortHexEscape => { + handler.span_err(span, "numeric character escape is too short") + } + EscapeError::InvalidCharInHexEscape | EscapeError::InvalidCharInUnicodeEscape => { + let (c, span) = last_char(); + + let mut msg = if error == EscapeError::InvalidCharInHexEscape { + "invalid character in numeric character escape: " + } else { + "invalid character in unicode escape: " + }.to_string(); + push_escaped_char(&mut msg, c); + + handler.span_err(span, msg.as_str()) + } + EscapeError::NonAsciiCharInByte => { + assert!(mode.is_bytes()); + let (_c, span) = last_char(); + handler.span_err(span, "byte constant must be ASCII. \ + Use a \\xHH escape for a non-ASCII byte") + } + EscapeError::OutOfRangeHexEscape => { + handler.span_err(span, "this form of character escape may only be used \ + with characters in the range [\\x00-\\x7f]") + } + EscapeError::LeadingUnderscoreUnicodeEscape => { + let (_c, span) = last_char(); + handler.span_err(span, "invalid start of unicode escape") + } + EscapeError::OverlongUnicodeEscape => { + handler.span_err(span, "overlong unicode escape (must have at most 6 hex digits)") + } + EscapeError::UnclosedUnicodeEscape => { + handler.span_err(span, "unterminated unicode escape (needed a `}`)") + } + EscapeError::NoBraceInUnicodeEscape => { + let msg = "incorrect unicode escape sequence"; + let mut diag = handler.struct_span_err(span, msg); + + let mut suggestion = "\\u{".to_owned(); + let mut suggestion_len = 0; + let (c, char_span) = last_char(); + let chars = once(c).chain(lit[range.end..].chars()); + for c in chars.take(6).take_while(|c| c.is_digit(16)) { + suggestion.push(c); + suggestion_len += c.len_utf8(); + } + + if suggestion_len > 0 { + suggestion.push('}'); + let lo = char_span.lo(); + let hi = lo + BytePos(suggestion_len as u32); + diag.span_suggestion( + span.with_lo(lo).with_hi(hi), + "format of unicode escape sequences uses braces", + suggestion, + Applicability::MaybeIncorrect, + ); + } else { + diag.span_label(span, msg); + diag.help( + "format of unicode escape sequences is `\\u{...}`", + ); + } + + diag.emit(); + } + EscapeError::UnicodeEscapeInByte => { + handler.span_err(span, "unicode escape sequences cannot be used \ + as a byte or in a byte string") + } + EscapeError::EmptyUnicodeEscape => { + handler.span_err(span, "empty unicode escape (must have at least 1 hex digit)") + } + EscapeError::ZeroChars => { + handler.span_err(span, "empty character literal") + } + EscapeError::LoneSlash => { + panic!("lexer accepted unterminated literal with trailing slash") + } + } +} + +/// Pushes a character to a message string for error reporting +pub(crate) fn push_escaped_char(msg: &mut String, c: char) { + match c { + '\u{20}'..='\u{7e}' => { + // Don't escape \, ' or " for user-facing messages + msg.push(c); + } + _ => { + msg.extend(c.escape_default()); + } + } +} diff --git a/src/test/ui/fmt/format-string-error-2.rs b/src/test/ui/fmt/format-string-error-2.rs index 5c25ae502ff6d..e9169d338f7ec 100644 --- a/src/test/ui/fmt/format-string-error-2.rs +++ b/src/test/ui/fmt/format-string-error-2.rs @@ -1,3 +1,4 @@ +// compile-flags: -Z continue-parse-after-error // ignore-tidy-tab fn main() { @@ -76,7 +77,7 @@ raw { \n println!("\x7B}\u8 {", 1); //~^ ERROR incorrect unicode escape sequence - //~| ERROR argument never used + //~| ERROR invalid format string: expected `'}'` but string was terminated // note: raw strings don't escape `\xFF` and `\u{FF}` sequences println!(r#"\x7B}\u{8} {"#, 1); diff --git a/src/test/ui/fmt/format-string-error-2.stderr b/src/test/ui/fmt/format-string-error-2.stderr index 66d35a1b854d3..6656cc8236973 100644 --- a/src/test/ui/fmt/format-string-error-2.stderr +++ b/src/test/ui/fmt/format-string-error-2.stderr @@ -1,13 +1,13 @@ error: incorrect unicode escape sequence - --> $DIR/format-string-error-2.rs:77:20 + --> $DIR/format-string-error-2.rs:78:20 | LL | println!("\x7B}\u8 {", 1); | ^^- - | | - | help: format of unicode escape sequences uses braces: `\u{8}` + | | + | help: format of unicode escape sequences uses braces: `\u{8}` error: invalid format string: expected `'}'`, found `'a'` - --> $DIR/format-string-error-2.rs:5:5 + --> $DIR/format-string-error-2.rs:6:5 | LL | format!("{ | - because of this opening brace @@ -17,7 +17,7 @@ LL | a"); = note: if you intended to print `{`, you can escape it using `{{` error: invalid format string: expected `'}'`, found `'b'` - --> $DIR/format-string-error-2.rs:9:5 + --> $DIR/format-string-error-2.rs:10:5 | LL | format!("{ \ | - because of this opening brace @@ -28,7 +28,7 @@ LL | b"); = note: if you intended to print `{`, you can escape it using `{{` error: invalid format string: expected `'}'`, found `'\'` - --> $DIR/format-string-error-2.rs:11:18 + --> $DIR/format-string-error-2.rs:12:18 | LL | format!(r#"{ \ | - ^ expected `}` in format string @@ -38,7 +38,7 @@ LL | format!(r#"{ \ = note: if you intended to print `{`, you can escape it using `{{` error: invalid format string: expected `'}'`, found `'\'` - --> $DIR/format-string-error-2.rs:15:18 + --> $DIR/format-string-error-2.rs:16:18 | LL | format!(r#"{ \n | - ^ expected `}` in format string @@ -48,7 +48,7 @@ LL | format!(r#"{ \n = note: if you intended to print `{`, you can escape it using `{{` error: invalid format string: expected `'}'`, found `'e'` - --> $DIR/format-string-error-2.rs:21:5 + --> $DIR/format-string-error-2.rs:22:5 | LL | format!("{ \n | - because of this opening brace @@ -59,7 +59,7 @@ LL | e"); = note: if you intended to print `{`, you can escape it using `{{` error: invalid format string: expected `'}'`, found `'a'` - --> $DIR/format-string-error-2.rs:25:5 + --> $DIR/format-string-error-2.rs:26:5 | LL | { | - because of this opening brace @@ -69,7 +69,7 @@ LL | a"); = note: if you intended to print `{`, you can escape it using `{{` error: invalid format string: expected `'}'`, found `'a'` - --> $DIR/format-string-error-2.rs:29:5 + --> $DIR/format-string-error-2.rs:30:5 | LL | { | - because of this opening brace @@ -79,7 +79,7 @@ LL | a = note: if you intended to print `{`, you can escape it using `{{` error: invalid format string: expected `'}'`, found `'b'` - --> $DIR/format-string-error-2.rs:35:5 + --> $DIR/format-string-error-2.rs:36:5 | LL | { \ | - because of this opening brace @@ -90,7 +90,7 @@ LL | b"); = note: if you intended to print `{`, you can escape it using `{{` error: invalid format string: expected `'}'`, found `'b'` - --> $DIR/format-string-error-2.rs:40:5 + --> $DIR/format-string-error-2.rs:41:5 | LL | { \ | - because of this opening brace @@ -101,7 +101,7 @@ LL | b \ = note: if you intended to print `{`, you can escape it using `{{` error: invalid format string: expected `'}'`, found `'\'` - --> $DIR/format-string-error-2.rs:45:8 + --> $DIR/format-string-error-2.rs:46:8 | LL | raw { \ | - ^ expected `}` in format string @@ -111,7 +111,7 @@ LL | raw { \ = note: if you intended to print `{`, you can escape it using `{{` error: invalid format string: expected `'}'`, found `'\'` - --> $DIR/format-string-error-2.rs:50:8 + --> $DIR/format-string-error-2.rs:51:8 | LL | raw { \n | - ^ expected `}` in format string @@ -121,7 +121,7 @@ LL | raw { \n = note: if you intended to print `{`, you can escape it using `{{` error: invalid format string: expected `'}'`, found `'e'` - --> $DIR/format-string-error-2.rs:57:5 + --> $DIR/format-string-error-2.rs:58:5 | LL | { \n | - because of this opening brace @@ -132,7 +132,7 @@ LL | e"); = note: if you intended to print `{`, you can escape it using `{{` error: invalid format string: expected `'}'`, found `'a'` - --> $DIR/format-string-error-2.rs:67:5 + --> $DIR/format-string-error-2.rs:68:5 | LL | { | - because of this opening brace @@ -142,13 +142,13 @@ LL | asdf} = note: if you intended to print `{`, you can escape it using `{{` error: 1 positional argument in format string, but no arguments were given - --> $DIR/format-string-error-2.rs:70:17 + --> $DIR/format-string-error-2.rs:71:17 | LL | println!("\t{}"); | ^^ error: invalid format string: expected `'}'` but string was terminated - --> $DIR/format-string-error-2.rs:74:27 + --> $DIR/format-string-error-2.rs:75:27 | LL | println!("\x7B}\u{8} {", 1); | -^ expected `'}'` in format string @@ -157,16 +157,18 @@ LL | println!("\x7B}\u{8} {", 1); | = note: if you intended to print `{`, you can escape it using `{{` -error: argument never used - --> $DIR/format-string-error-2.rs:77:28 +error: invalid format string: expected `'}'` but string was terminated + --> $DIR/format-string-error-2.rs:78:27 | LL | println!("\x7B}\u8 {", 1); - | ------------ ^ argument never used - | | - | formatting specifier missing + | -^ expected `'}'` in format string + | | + | because of this opening brace + | + = note: if you intended to print `{`, you can escape it using `{{` error: invalid format string: unmatched `}` found - --> $DIR/format-string-error-2.rs:82:21 + --> $DIR/format-string-error-2.rs:83:21 | LL | println!(r#"\x7B}\u{8} {"#, 1); | ^ unmatched `}` in format string @@ -174,7 +176,7 @@ LL | println!(r#"\x7B}\u{8} {"#, 1); = note: if you intended to print `}`, you can escape it using `}}` error: invalid format string: unmatched `}` found - --> $DIR/format-string-error-2.rs:85:21 + --> $DIR/format-string-error-2.rs:86:21 | LL | println!(r#"\x7B}\u8 {"#, 1); | ^ unmatched `}` in format string diff --git a/src/test/ui/parser/ascii-only-character-escape.stderr b/src/test/ui/parser/ascii-only-character-escape.stderr index 8a981e8d62e2b..391677917580b 100644 --- a/src/test/ui/parser/ascii-only-character-escape.stderr +++ b/src/test/ui/parser/ascii-only-character-escape.stderr @@ -1,20 +1,20 @@ error: this form of character escape may only be used with characters in the range [\x00-\x7f] - --> $DIR/ascii-only-character-escape.rs:4:16 + --> $DIR/ascii-only-character-escape.rs:4:14 | LL | let x = "\x80"; - | ^^ + | ^^^^ error: this form of character escape may only be used with characters in the range [\x00-\x7f] - --> $DIR/ascii-only-character-escape.rs:5:16 + --> $DIR/ascii-only-character-escape.rs:5:14 | LL | let y = "\xff"; - | ^^ + | ^^^^ error: this form of character escape may only be used with characters in the range [\x00-\x7f] - --> $DIR/ascii-only-character-escape.rs:6:16 + --> $DIR/ascii-only-character-escape.rs:6:14 | LL | let z = "\xe2"; - | ^^ + | ^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/parser/byte-literals.stderr b/src/test/ui/parser/byte-literals.stderr index 28385f34f2ab2..58a5797b90776 100644 --- a/src/test/ui/parser/byte-literals.stderr +++ b/src/test/ui/parser/byte-literals.stderr @@ -34,11 +34,11 @@ error: byte constant must be ASCII. Use a \xHH escape for a non-ASCII byte LL | b'é'; | ^ -error: unterminated byte constant: b'a - --> $DIR/byte-literals.rs:14:5 +error: unterminated byte constant + --> $DIR/byte-literals.rs:14:6 | LL | b'a - | ^^^ + | ^^^^ error: aborting due to 7 previous errors diff --git a/src/test/ui/parser/byte-string-literals.stderr b/src/test/ui/parser/byte-string-literals.stderr index b855484444010..eeb2fcd12320b 100644 --- a/src/test/ui/parser/byte-string-literals.stderr +++ b/src/test/ui/parser/byte-string-literals.stderr @@ -23,10 +23,10 @@ LL | b"é"; | ^ error: unterminated double quote byte string - --> $DIR/byte-string-literals.rs:9:7 + --> $DIR/byte-string-literals.rs:9:6 | LL | b"a - | _______^ + | ______^ LL | | } | |__^ diff --git a/src/test/ui/parser/issue-23620-invalid-escapes.rs b/src/test/ui/parser/issue-23620-invalid-escapes.rs index b4b8f1fc0b0ab..53629973a1b5f 100644 --- a/src/test/ui/parser/issue-23620-invalid-escapes.rs +++ b/src/test/ui/parser/issue-23620-invalid-escapes.rs @@ -9,32 +9,27 @@ fn main() { let _ = b'\u'; //~^ ERROR incorrect unicode escape sequence - //~^^ ERROR unicode escape sequences cannot be used as a byte or in a byte string let _ = b'\x5'; //~^ ERROR numeric character escape is too short let _ = b'\xxy'; //~^ ERROR invalid character in numeric character escape: x - //~^^ ERROR invalid character in numeric character escape: y let _ = '\x5'; //~^ ERROR numeric character escape is too short let _ = '\xxy'; //~^ ERROR invalid character in numeric character escape: x - //~^^ ERROR invalid character in numeric character escape: y let _ = b"\u{a4a4} \xf \u"; //~^ ERROR unicode escape sequences cannot be used as a byte or in a byte string //~^^ ERROR invalid character in numeric character escape: //~^^^ ERROR incorrect unicode escape sequence - //~^^^^ ERROR unicode escape sequences cannot be used as a byte or in a byte string let _ = "\xf \u"; //~^ ERROR invalid character in numeric character escape: - //~^^ ERROR form of character escape may only be used with characters in the range [\x00-\x7f] - //~^^^ ERROR incorrect unicode escape sequence + //~^^ ERROR incorrect unicode escape sequence let _ = "\u8f"; //~^ ERROR incorrect unicode escape sequence diff --git a/src/test/ui/parser/issue-23620-invalid-escapes.stderr b/src/test/ui/parser/issue-23620-invalid-escapes.stderr index 295ba3b73e861..5fabc1d7e4326 100644 --- a/src/test/ui/parser/issue-23620-invalid-escapes.stderr +++ b/src/test/ui/parser/issue-23620-invalid-escapes.stderr @@ -18,88 +18,58 @@ LL | let _ = b'\u'; | = help: format of unicode escape sequences is `\u{...}` -error: unicode escape sequences cannot be used as a byte or in a byte string - --> $DIR/issue-23620-invalid-escapes.rs:10:15 - | -LL | let _ = b'\u'; - | ^^ - error: numeric character escape is too short - --> $DIR/issue-23620-invalid-escapes.rs:14:17 + --> $DIR/issue-23620-invalid-escapes.rs:13:15 | LL | let _ = b'\x5'; - | ^ + | ^^^ error: invalid character in numeric character escape: x - --> $DIR/issue-23620-invalid-escapes.rs:17:17 + --> $DIR/issue-23620-invalid-escapes.rs:16:17 | LL | let _ = b'\xxy'; | ^ -error: invalid character in numeric character escape: y - --> $DIR/issue-23620-invalid-escapes.rs:17:18 - | -LL | let _ = b'\xxy'; - | ^ - error: numeric character escape is too short - --> $DIR/issue-23620-invalid-escapes.rs:21:16 + --> $DIR/issue-23620-invalid-escapes.rs:19:14 | LL | let _ = '\x5'; - | ^ + | ^^^ error: invalid character in numeric character escape: x - --> $DIR/issue-23620-invalid-escapes.rs:24:16 + --> $DIR/issue-23620-invalid-escapes.rs:22:16 | LL | let _ = '\xxy'; | ^ -error: invalid character in numeric character escape: y - --> $DIR/issue-23620-invalid-escapes.rs:24:17 - | -LL | let _ = '\xxy'; - | ^ - error: unicode escape sequences cannot be used as a byte or in a byte string - --> $DIR/issue-23620-invalid-escapes.rs:28:15 + --> $DIR/issue-23620-invalid-escapes.rs:25:15 | LL | let _ = b"\u{a4a4} \xf \u"; | ^^^^^^^^ error: invalid character in numeric character escape: - --> $DIR/issue-23620-invalid-escapes.rs:28:27 + --> $DIR/issue-23620-invalid-escapes.rs:25:27 | LL | let _ = b"\u{a4a4} \xf \u"; | ^ error: incorrect unicode escape sequence - --> $DIR/issue-23620-invalid-escapes.rs:28:28 + --> $DIR/issue-23620-invalid-escapes.rs:25:28 | LL | let _ = b"\u{a4a4} \xf \u"; | ^^ incorrect unicode escape sequence | = help: format of unicode escape sequences is `\u{...}` -error: unicode escape sequences cannot be used as a byte or in a byte string - --> $DIR/issue-23620-invalid-escapes.rs:28:28 - | -LL | let _ = b"\u{a4a4} \xf \u"; - | ^^ - error: invalid character in numeric character escape: - --> $DIR/issue-23620-invalid-escapes.rs:34:17 + --> $DIR/issue-23620-invalid-escapes.rs:30:17 | LL | let _ = "\xf \u"; | ^ -error: this form of character escape may only be used with characters in the range [\x00-\x7f] - --> $DIR/issue-23620-invalid-escapes.rs:34:16 - | -LL | let _ = "\xf \u"; - | ^^ - error: incorrect unicode escape sequence - --> $DIR/issue-23620-invalid-escapes.rs:34:18 + --> $DIR/issue-23620-invalid-escapes.rs:30:18 | LL | let _ = "\xf \u"; | ^^ incorrect unicode escape sequence @@ -107,12 +77,12 @@ LL | let _ = "\xf \u"; = help: format of unicode escape sequences is `\u{...}` error: incorrect unicode escape sequence - --> $DIR/issue-23620-invalid-escapes.rs:39:14 + --> $DIR/issue-23620-invalid-escapes.rs:34:14 | LL | let _ = "\u8f"; | ^^-- - | | - | help: format of unicode escape sequences uses braces: `\u{8f}` + | | + | help: format of unicode escape sequences uses braces: `\u{8f}` -error: aborting due to 18 previous errors +error: aborting due to 13 previous errors diff --git a/src/test/ui/parser/lex-bad-char-literals-1.stderr b/src/test/ui/parser/lex-bad-char-literals-1.stderr index 414ad81512ae5..000d155c26833 100644 --- a/src/test/ui/parser/lex-bad-char-literals-1.stderr +++ b/src/test/ui/parser/lex-bad-char-literals-1.stderr @@ -1,14 +1,14 @@ error: numeric character escape is too short - --> $DIR/lex-bad-char-literals-1.rs:3:8 + --> $DIR/lex-bad-char-literals-1.rs:3:6 | LL | '\x1' - | ^ + | ^^^ error: numeric character escape is too short - --> $DIR/lex-bad-char-literals-1.rs:7:8 + --> $DIR/lex-bad-char-literals-1.rs:7:6 | LL | "\x1" - | ^ + | ^^^ error: unknown character escape: \u{25cf} --> $DIR/lex-bad-char-literals-1.rs:11:7 diff --git a/src/test/ui/parser/lex-bad-char-literals-2.stderr b/src/test/ui/parser/lex-bad-char-literals-2.stderr index 4c1c5c29f472e..b0a4ed02434b4 100644 --- a/src/test/ui/parser/lex-bad-char-literals-2.stderr +++ b/src/test/ui/parser/lex-bad-char-literals-2.stderr @@ -3,6 +3,10 @@ error: character literal may only contain one codepoint | LL | 'nope' | ^^^^^^ +help: if you meant to write a `str` literal, use double quotes + | +LL | "nope" + | ^^^^^^ error[E0601]: `main` function not found in crate `lex_bad_char_literals_2` | diff --git a/src/test/ui/parser/lex-bad-char-literals-4.rs b/src/test/ui/parser/lex-bad-char-literals-4.rs index e13f11f36df48..de0a19df99360 100644 --- a/src/test/ui/parser/lex-bad-char-literals-4.rs +++ b/src/test/ui/parser/lex-bad-char-literals-4.rs @@ -1,5 +1,5 @@ // // This test needs to the last one appearing in this file as it kills the parser static c: char = - '● //~ ERROR: character literal may only contain one codepoint + '● //~ ERROR: unterminated character literal ; diff --git a/src/test/ui/parser/lex-bad-char-literals-4.stderr b/src/test/ui/parser/lex-bad-char-literals-4.stderr index 7bcca3761fc60..8f8f806f6cf61 100644 --- a/src/test/ui/parser/lex-bad-char-literals-4.stderr +++ b/src/test/ui/parser/lex-bad-char-literals-4.stderr @@ -1,8 +1,8 @@ -error: character literal may only contain one codepoint: '● +error: unterminated character literal --> $DIR/lex-bad-char-literals-4.rs:4:5 | LL | '● - | ^^ + | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/lex-bad-char-literals-6.stderr b/src/test/ui/parser/lex-bad-char-literals-6.stderr index 74959c9a4ed4a..a7bbe05e94b7b 100644 --- a/src/test/ui/parser/lex-bad-char-literals-6.stderr +++ b/src/test/ui/parser/lex-bad-char-literals-6.stderr @@ -3,18 +3,30 @@ error: character literal may only contain one codepoint | LL | let x: &str = 'ab'; | ^^^^ +help: if you meant to write a `str` literal, use double quotes + | +LL | let x: &str = "ab"; + | ^^^^ error: character literal may only contain one codepoint --> $DIR/lex-bad-char-literals-6.rs:4:19 | LL | let y: char = 'cd'; | ^^^^ +help: if you meant to write a `str` literal, use double quotes + | +LL | let y: char = "cd"; + | ^^^^ error: character literal may only contain one codepoint --> $DIR/lex-bad-char-literals-6.rs:6:13 | LL | let z = 'ef'; | ^^^^ +help: if you meant to write a `str` literal, use double quotes + | +LL | let z = "ef"; + | ^^^^ error[E0277]: can't compare `&str` with `char` --> $DIR/lex-bad-char-literals-6.rs:9:10 diff --git a/src/test/ui/parser/lex-bad-char-literals-7.rs b/src/test/ui/parser/lex-bad-char-literals-7.rs new file mode 100644 index 0000000000000..70eafcb91dacb --- /dev/null +++ b/src/test/ui/parser/lex-bad-char-literals-7.rs @@ -0,0 +1,14 @@ +// compile-flags: -Z continue-parse-after-error +fn main() { + let _: char = ''; + //~^ ERROR: empty character literal + let _: char = '\u{}'; + //~^ ERROR: empty unicode escape (must have at least 1 hex digit) + + // Next two are OK, but may befool error recovery + let _ = '/'; + let _ = b'/'; + + let _ = ' hello // here's a comment + //~^ ERROR: unterminated character literal +} diff --git a/src/test/ui/parser/lex-bad-char-literals-7.stderr b/src/test/ui/parser/lex-bad-char-literals-7.stderr new file mode 100644 index 0000000000000..e1ba3c3ee0f17 --- /dev/null +++ b/src/test/ui/parser/lex-bad-char-literals-7.stderr @@ -0,0 +1,20 @@ +error: empty character literal + --> $DIR/lex-bad-char-literals-7.rs:3:20 + | +LL | let _: char = ''; + | ^ + +error: empty unicode escape (must have at least 1 hex digit) + --> $DIR/lex-bad-char-literals-7.rs:5:20 + | +LL | let _: char = '\u{}'; + | ^^^^ + +error: unterminated character literal + --> $DIR/lex-bad-char-literals-7.rs:12:13 + | +LL | let _ = ' hello // here's a comment + | ^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/parser/macro/literals-are-validated-before-expansion.rs b/src/test/ui/parser/macro/literals-are-validated-before-expansion.rs new file mode 100644 index 0000000000000..c3fc754b5567f --- /dev/null +++ b/src/test/ui/parser/macro/literals-are-validated-before-expansion.rs @@ -0,0 +1,10 @@ +macro_rules! black_hole { + ($($tt:tt)*) => {} +} + +fn main() { + black_hole! { '\u{FFFFFF}' } + //~^ ERROR: invalid unicode character escape + black_hole! { "this is surrogate: \u{DAAA}" } + //~^ ERROR: invalid unicode character escape +} diff --git a/src/test/ui/parser/macro/literals-are-validated-before-expansion.stderr b/src/test/ui/parser/macro/literals-are-validated-before-expansion.stderr new file mode 100644 index 0000000000000..d20eb0fb30a49 --- /dev/null +++ b/src/test/ui/parser/macro/literals-are-validated-before-expansion.stderr @@ -0,0 +1,18 @@ +error: invalid unicode character escape + --> $DIR/literals-are-validated-before-expansion.rs:6:20 + | +LL | black_hole! { '\u{FFFFFF}' } + | ^^^^^^^^^^ + | + = help: unicode escape must be at most 10FFFF + +error: invalid unicode character escape + --> $DIR/literals-are-validated-before-expansion.rs:8:39 + | +LL | black_hole! { "this is surrogate: \u{DAAA}" } + | ^^^^^^^^ + | + = help: unicode escape must not be a surrogate + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/parser/new-unicode-escapes-1.stderr b/src/test/ui/parser/new-unicode-escapes-1.stderr index a8da50951ddf3..22d6a0981ffd6 100644 --- a/src/test/ui/parser/new-unicode-escapes-1.stderr +++ b/src/test/ui/parser/new-unicode-escapes-1.stderr @@ -1,8 +1,8 @@ error: unterminated unicode escape (needed a `}`) - --> $DIR/new-unicode-escapes-1.rs:2:21 + --> $DIR/new-unicode-escapes-1.rs:2:14 | LL | let s = "\u{2603"; - | ^ + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/new-unicode-escapes-2.stderr b/src/test/ui/parser/new-unicode-escapes-2.stderr index ede49cdf7e1d1..b5148279c7450 100644 --- a/src/test/ui/parser/new-unicode-escapes-2.stderr +++ b/src/test/ui/parser/new-unicode-escapes-2.stderr @@ -1,8 +1,8 @@ error: overlong unicode escape (must have at most 6 hex digits) - --> $DIR/new-unicode-escapes-2.rs:2:17 + --> $DIR/new-unicode-escapes-2.rs:2:14 | LL | let s = "\u{260311111111}"; - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/new-unicode-escapes-3.stderr b/src/test/ui/parser/new-unicode-escapes-3.stderr index 59cfb988f2897..361698467f97d 100644 --- a/src/test/ui/parser/new-unicode-escapes-3.stderr +++ b/src/test/ui/parser/new-unicode-escapes-3.stderr @@ -1,16 +1,16 @@ error: invalid unicode character escape - --> $DIR/new-unicode-escapes-3.rs:2:14 + --> $DIR/new-unicode-escapes-3.rs:2:15 | LL | let s1 = "\u{d805}"; - | ^^^^^^^^^^ + | ^^^^^^^^ | = help: unicode escape must not be a surrogate error: invalid unicode character escape - --> $DIR/new-unicode-escapes-3.rs:3:14 + --> $DIR/new-unicode-escapes-3.rs:3:15 | LL | let s2 = "\u{ffffff}"; - | ^^^^^^^^^^^^ + | ^^^^^^^^^^ | = help: unicode escape must be at most 10FFFF From 2c371b21e4b912c11cbc39fdc26dd87987fe43ee Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Thu, 2 May 2019 12:09:46 -0400 Subject: [PATCH 017/212] build dist-aarch64-linux with --enable-profiler This change should enable PGO to be used for aarch64-linux. Fixes #57257. --- src/ci/docker/dist-aarch64-linux/Dockerfile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ci/docker/dist-aarch64-linux/Dockerfile b/src/ci/docker/dist-aarch64-linux/Dockerfile index cddfa557f6aed..f5eb66ed7142f 100644 --- a/src/ci/docker/dist-aarch64-linux/Dockerfile +++ b/src/ci/docker/dist-aarch64-linux/Dockerfile @@ -32,5 +32,8 @@ ENV CC_aarch64_unknown_linux_gnu=aarch64-unknown-linux-gnueabi-gcc \ ENV HOSTS=aarch64-unknown-linux-gnu -ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs +ENV RUST_CONFIGURE_ARGS \ + --enable-extended \ + --enable-profiler \ + --disable-docs ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS From 1835cbeb6574997ec5188cb22b9538c61976d2b4 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 2 May 2019 20:56:07 +0300 Subject: [PATCH 018/212] don't amplify errors in format! with bad literals --- src/libsyntax/ext/base.rs | 1 + src/libsyntax/parse/mod.rs | 21 +++++++++++++------- src/test/ui/fmt/format-string-error-2.rs | 1 - src/test/ui/fmt/format-string-error-2.stderr | 16 +++------------ src/test/ui/str/str-as-char.fixed | 3 +-- src/test/ui/str/str-as-char.rs | 1 - src/test/ui/str/str-as-char.stderr | 12 +---------- 7 files changed, 20 insertions(+), 35 deletions(-) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 452cc2f2c65cc..cc19acb61adc2 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -998,6 +998,7 @@ pub fn expr_to_spanned_string<'a>( Err(match expr.node { ast::ExprKind::Lit(ref l) => match l.node { ast::LitKind::Str(s, style) => return Ok(respan(expr.span, (s, style))), + ast::LitKind::Err(_) => None, _ => Some(cx.struct_span_err(l.span, err_msg)) }, ast::ExprKind::Err => None, diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index d6d4f8e8f0429..34a86bab2294f 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -33,7 +33,7 @@ pub mod attr; pub mod classify; pub(crate) mod unescape; -use unescape::{unescape_str, unescape_char, unescape_byte_str, unescape_byte, EscapeError}; +use unescape::{unescape_str, unescape_char, unescape_byte_str, unescape_byte}; pub(crate) mod unescape_error_reporting; @@ -355,16 +355,14 @@ crate fn lit_token(lit: token::Lit, suf: Option, diag: Option<(Span, &Ha token::Byte(i) => { let lit_kind = match unescape_byte(&i.as_str()) { Ok(c) => LitKind::Byte(c), - Err((_, EscapeError::MoreThanOneChar)) => LitKind::Err(i), - Err(_) => LitKind::Byte(0), + Err(_) => LitKind::Err(i), }; (true, Some(lit_kind)) }, token::Char(i) => { let lit_kind = match unescape_char(&i.as_str()) { Ok(c) => LitKind::Char(c), - Err((_, EscapeError::MoreThanOneChar)) => LitKind::Err(i), - Err(_) => LitKind::Char('\u{FFFD}'), + Err(_) => LitKind::Err(i), }; (true, Some(lit_kind)) }, @@ -380,17 +378,22 @@ crate fn lit_token(lit: token::Lit, suf: Option, diag: Option<(Span, &Ha // reuse the symbol from the Token. Otherwise, we must generate a // new symbol because the string in the LitKind is different to the // string in the Token. + let mut has_error = false; let s = &sym.as_str(); if s.as_bytes().iter().any(|&c| c == b'\\' || c == b'\r') { let mut buf = String::with_capacity(s.len()); unescape_str(s, &mut |_, unescaped_char| { match unescaped_char { Ok(c) => buf.push(c), - Err(_) => buf.push('\u{FFFD}'), + Err(_) => has_error = true, } }); + if has_error { + return (true, Some(LitKind::Err(sym))); + } sym = Symbol::intern(&buf) } + (true, Some(LitKind::Str(sym, ast::StrStyle::Cooked))) } token::StrRaw(mut sym, n) => { @@ -404,12 +407,16 @@ crate fn lit_token(lit: token::Lit, suf: Option, diag: Option<(Span, &Ha token::ByteStr(i) => { let s = &i.as_str(); let mut buf = Vec::with_capacity(s.len()); + let mut has_error = false; unescape_byte_str(s, &mut |_, unescaped_byte| { match unescaped_byte { Ok(c) => buf.push(c), - Err(_) => buf.push(0), + Err(_) => has_error = true, } }); + if has_error { + return (true, Some(LitKind::Err(i))); + } buf.shrink_to_fit(); (true, Some(LitKind::ByteStr(Lrc::new(buf)))) } diff --git a/src/test/ui/fmt/format-string-error-2.rs b/src/test/ui/fmt/format-string-error-2.rs index e9169d338f7ec..8ca98fc266a01 100644 --- a/src/test/ui/fmt/format-string-error-2.rs +++ b/src/test/ui/fmt/format-string-error-2.rs @@ -77,7 +77,6 @@ raw { \n println!("\x7B}\u8 {", 1); //~^ ERROR incorrect unicode escape sequence - //~| ERROR invalid format string: expected `'}'` but string was terminated // note: raw strings don't escape `\xFF` and `\u{FF}` sequences println!(r#"\x7B}\u{8} {"#, 1); diff --git a/src/test/ui/fmt/format-string-error-2.stderr b/src/test/ui/fmt/format-string-error-2.stderr index 6656cc8236973..227ec27efc87f 100644 --- a/src/test/ui/fmt/format-string-error-2.stderr +++ b/src/test/ui/fmt/format-string-error-2.stderr @@ -157,18 +157,8 @@ LL | println!("\x7B}\u{8} {", 1); | = note: if you intended to print `{`, you can escape it using `{{` -error: invalid format string: expected `'}'` but string was terminated - --> $DIR/format-string-error-2.rs:78:27 - | -LL | println!("\x7B}\u8 {", 1); - | -^ expected `'}'` in format string - | | - | because of this opening brace - | - = note: if you intended to print `{`, you can escape it using `{{` - error: invalid format string: unmatched `}` found - --> $DIR/format-string-error-2.rs:83:21 + --> $DIR/format-string-error-2.rs:82:21 | LL | println!(r#"\x7B}\u{8} {"#, 1); | ^ unmatched `}` in format string @@ -176,12 +166,12 @@ LL | println!(r#"\x7B}\u{8} {"#, 1); = note: if you intended to print `}`, you can escape it using `}}` error: invalid format string: unmatched `}` found - --> $DIR/format-string-error-2.rs:86:21 + --> $DIR/format-string-error-2.rs:85:21 | LL | println!(r#"\x7B}\u8 {"#, 1); | ^ unmatched `}` in format string | = note: if you intended to print `}`, you can escape it using `}}` -error: aborting due to 19 previous errors +error: aborting due to 18 previous errors diff --git a/src/test/ui/str/str-as-char.fixed b/src/test/ui/str/str-as-char.fixed index accead5c850cc..42bbef8391785 100644 --- a/src/test/ui/str/str-as-char.fixed +++ b/src/test/ui/str/str-as-char.fixed @@ -1,6 +1,5 @@ // run-rustfix fn main() { - println!("{}", "●●"); //~ ERROR character literal may only contain one codepoint - //~^ ERROR format argument must be a string literal + println!("●●"); //~ ERROR character literal may only contain one codepoint } diff --git a/src/test/ui/str/str-as-char.rs b/src/test/ui/str/str-as-char.rs index fb179ec7245d2..09b9dfc590db3 100644 --- a/src/test/ui/str/str-as-char.rs +++ b/src/test/ui/str/str-as-char.rs @@ -2,5 +2,4 @@ fn main() { println!('●●'); //~ ERROR character literal may only contain one codepoint - //~^ ERROR format argument must be a string literal } diff --git a/src/test/ui/str/str-as-char.stderr b/src/test/ui/str/str-as-char.stderr index 162f0888a2947..540a1b55376ff 100644 --- a/src/test/ui/str/str-as-char.stderr +++ b/src/test/ui/str/str-as-char.stderr @@ -8,15 +8,5 @@ help: if you meant to write a `str` literal, use double quotes LL | println!("●●"); | ^^^^ -error: format argument must be a string literal - --> $DIR/str-as-char.rs:4:14 - | -LL | println!('●●'); - | ^^^^ -help: you might be missing a string literal to format with - | -LL | println!("{}", '●●'); - | ^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error From 2e20da5c2c5a09f3f9e2421b08ccdd8a054cdb91 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 3 May 2019 00:13:39 +0200 Subject: [PATCH 019/212] Remove hamburger button from source code page --- src/librustdoc/html/static/rustdoc.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 53b08cf569783..959c862743c35 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -1052,6 +1052,10 @@ span.since { height: 45px; } + .rustdoc.source > .sidebar > .sidebar-menu { + display: none; + } + .sidebar-elems { position: fixed; z-index: 1; From e0cef5cf406016d5c1685a164a27571d182fa873 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 2 May 2019 15:53:09 -0700 Subject: [PATCH 020/212] fix typo --- src/librustc_typeck/check/mod.rs | 2 +- src/libsyntax/parse/parser.rs | 8 ++++---- src/test/ui/error-codes/E0423.stderr | 4 ++-- src/test/ui/parser/expr-as-stmt.stderr | 12 ++++++------ .../ui/parser/match-arrows-block-then-binop.stderr | 2 +- src/test/ui/parser/struct-literal-in-for.stderr | 2 +- src/test/ui/parser/struct-literal-in-if.stderr | 2 +- .../struct-literal-in-match-discriminant.stderr | 2 +- src/test/ui/parser/struct-literal-in-while.stderr | 2 +- .../struct-literal-restrictions-in-lamda.stderr | 2 +- src/test/ui/struct-literal-variant-in-if.stderr | 8 ++++---- 11 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 61270716dfcbc..a0050b1359679 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4182,7 +4182,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { { err.span_suggestion( *sp, - "parenthesis are required to parse this \ + "parentheses are required to parse this \ as an expression", format!("({})", snippet), Applicability::MachineApplicable, diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index fbd1203dec94a..02e6c5e1c8dbf 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2934,7 +2934,7 @@ impl<'a> Parser<'a> { if let Ok(snippet) = self.sess.source_map().span_to_snippet(*sp) { err.span_suggestion( *sp, - "parenthesis are required to parse this as an expression", + "parentheses are required to parse this as an expression", format!("({})", snippet), Applicability::MachineApplicable, ); @@ -2979,7 +2979,7 @@ impl<'a> Parser<'a> { "struct literals are not allowed here", ); err.multipart_suggestion( - "surround the struct literal with parenthesis", + "surround the struct literal with parentheses", vec![ (lo.shrink_to_lo(), "(".to_string()), (expr.span.shrink_to_hi(), ")".to_string()), @@ -3661,7 +3661,7 @@ impl<'a> Parser<'a> { .unwrap_or_else(|_| pprust::expr_to_string(&lhs)); err.span_suggestion( lhs.span, - "parenthesis are required to parse this as an expression", + "parentheses are required to parse this as an expression", format!("({})", snippet), Applicability::MachineApplicable, ); @@ -4982,7 +4982,7 @@ impl<'a> Parser<'a> { if let Ok(snippet) = self.sess.source_map().span_to_snippet(*sp) { err.span_suggestion( *sp, - "parenthesis are required to parse this as an expression", + "parentheses are required to parse this as an expression", format!("({})", snippet), Applicability::MachineApplicable, ); diff --git a/src/test/ui/error-codes/E0423.stderr b/src/test/ui/error-codes/E0423.stderr index 5cb7121a0d1c3..ec240003f9182 100644 --- a/src/test/ui/error-codes/E0423.stderr +++ b/src/test/ui/error-codes/E0423.stderr @@ -3,7 +3,7 @@ error: struct literals are not allowed here | LL | if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); } | ^^^^^^^^^^^^^^^^ -help: surround the struct literal with parenthesis +help: surround the struct literal with parentheses | LL | if let S { x: _x, y: 2 } = (S { x: 1, y: 2 }) { println!("Ok"); } | ^ ^ @@ -19,7 +19,7 @@ error: struct literals are not allowed here | LL | for _ in std::ops::Range { start: 0, end: 10 } {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: surround the struct literal with parenthesis +help: surround the struct literal with parentheses | LL | for _ in (std::ops::Range { start: 0, end: 10 }) {} | ^ ^ diff --git a/src/test/ui/parser/expr-as-stmt.stderr b/src/test/ui/parser/expr-as-stmt.stderr index 1725ba944c50f..a11209998a7d5 100644 --- a/src/test/ui/parser/expr-as-stmt.stderr +++ b/src/test/ui/parser/expr-as-stmt.stderr @@ -4,7 +4,7 @@ error: expected expression, found `+` LL | {2} + {2} | --- ^ expected expression | | - | help: parenthesis are required to parse this as an expression: `({2})` + | help: parentheses are required to parse this as an expression: `({2})` error: expected expression, found `+` --> $DIR/expr-as-stmt.rs:12:9 @@ -12,7 +12,7 @@ error: expected expression, found `+` LL | {2} + 2 | --- ^ expected expression | | - | help: parenthesis are required to parse this as an expression: `({2})` + | help: parentheses are required to parse this as an expression: `({2})` error: expected expression, found `+` --> $DIR/expr-as-stmt.rs:18:12 @@ -20,13 +20,13 @@ error: expected expression, found `+` LL | { 42 } + foo; | ------ ^ expected expression | | - | help: parenthesis are required to parse this as an expression: `({ 42 })` + | help: parentheses are required to parse this as an expression: `({ 42 })` error: expected expression, found `&&` --> $DIR/expr-as-stmt.rs:30:5 | LL | if let Some(x) = a { true } else { false } - | ------------------------------------------ help: parenthesis are required to parse this as an expression: `(if let Some(x) = a { true } else { false })` + | ------------------------------------------ help: parentheses are required to parse this as an expression: `(if let Some(x) = a { true } else { false })` LL | && | ^^ expected expression @@ -35,7 +35,7 @@ error: expected expression, found `>` | LL | } > 0 | ^ expected expression -help: parenthesis are required to parse this as an expression +help: parentheses are required to parse this as an expression | LL | (match x { LL | _ => 1, @@ -84,7 +84,7 @@ error[E0614]: type `{integer}` cannot be dereferenced LL | { 3 } * 3 | ----- ^^^ | | - | help: parenthesis are required to parse this as an expression: `({ 3 })` + | help: parentheses are required to parse this as an expression: `({ 3 })` error: aborting due to 10 previous errors diff --git a/src/test/ui/parser/match-arrows-block-then-binop.stderr b/src/test/ui/parser/match-arrows-block-then-binop.stderr index 0d7f81645b46a..bb7df30783acd 100644 --- a/src/test/ui/parser/match-arrows-block-then-binop.stderr +++ b/src/test/ui/parser/match-arrows-block-then-binop.stderr @@ -3,7 +3,7 @@ error: expected pattern, found `+` | LL | } + 5 | ^ expected pattern -help: parenthesis are required to parse this as an expression +help: parentheses are required to parse this as an expression | LL | 0 => ({ LL | 0 diff --git a/src/test/ui/parser/struct-literal-in-for.stderr b/src/test/ui/parser/struct-literal-in-for.stderr index 3c3f6e7f032f6..29af72a5d23d0 100644 --- a/src/test/ui/parser/struct-literal-in-for.stderr +++ b/src/test/ui/parser/struct-literal-in-for.stderr @@ -6,7 +6,7 @@ LL | for x in Foo { LL | | x: 3 LL | | }.hi() { | |_____^ -help: surround the struct literal with parenthesis +help: surround the struct literal with parentheses | LL | for x in (Foo { LL | x: 3 diff --git a/src/test/ui/parser/struct-literal-in-if.stderr b/src/test/ui/parser/struct-literal-in-if.stderr index 851c495abb4b0..e76c1cb45dd4e 100644 --- a/src/test/ui/parser/struct-literal-in-if.stderr +++ b/src/test/ui/parser/struct-literal-in-if.stderr @@ -6,7 +6,7 @@ LL | if Foo { LL | | x: 3 LL | | }.hi() { | |_____^ -help: surround the struct literal with parenthesis +help: surround the struct literal with parentheses | LL | if (Foo { LL | x: 3 diff --git a/src/test/ui/parser/struct-literal-in-match-discriminant.stderr b/src/test/ui/parser/struct-literal-in-match-discriminant.stderr index 0058e8981cd25..95b0882b7aeb5 100644 --- a/src/test/ui/parser/struct-literal-in-match-discriminant.stderr +++ b/src/test/ui/parser/struct-literal-in-match-discriminant.stderr @@ -6,7 +6,7 @@ LL | match Foo { LL | | x: 3 LL | | } { | |_____^ -help: surround the struct literal with parenthesis +help: surround the struct literal with parentheses | LL | match (Foo { LL | x: 3 diff --git a/src/test/ui/parser/struct-literal-in-while.stderr b/src/test/ui/parser/struct-literal-in-while.stderr index 9959a57be8596..acd31b477dc27 100644 --- a/src/test/ui/parser/struct-literal-in-while.stderr +++ b/src/test/ui/parser/struct-literal-in-while.stderr @@ -6,7 +6,7 @@ LL | while Foo { LL | | x: 3 LL | | }.hi() { | |_____^ -help: surround the struct literal with parenthesis +help: surround the struct literal with parentheses | LL | while (Foo { LL | x: 3 diff --git a/src/test/ui/parser/struct-literal-restrictions-in-lamda.stderr b/src/test/ui/parser/struct-literal-restrictions-in-lamda.stderr index 81f7a91ddb38a..24078074161e6 100644 --- a/src/test/ui/parser/struct-literal-restrictions-in-lamda.stderr +++ b/src/test/ui/parser/struct-literal-restrictions-in-lamda.stderr @@ -6,7 +6,7 @@ LL | while || Foo { LL | | x: 3 LL | | }.hi() { | |_____^ -help: surround the struct literal with parenthesis +help: surround the struct literal with parentheses | LL | while || (Foo { LL | x: 3 diff --git a/src/test/ui/struct-literal-variant-in-if.stderr b/src/test/ui/struct-literal-variant-in-if.stderr index 55f23baea7aa8..f91b9d7dce60f 100644 --- a/src/test/ui/struct-literal-variant-in-if.stderr +++ b/src/test/ui/struct-literal-variant-in-if.stderr @@ -3,7 +3,7 @@ error: struct literals are not allowed here | LL | if x == E::I { field1: true, field2: 42 } {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: surround the struct literal with parenthesis +help: surround the struct literal with parentheses | LL | if x == (E::I { field1: true, field2: 42 }) {} | ^ ^ @@ -13,7 +13,7 @@ error: struct literals are not allowed here | LL | if x == E::V { field: false } {} | ^^^^^^^^^^^^^^^^^^^^^ -help: surround the struct literal with parenthesis +help: surround the struct literal with parentheses | LL | if x == (E::V { field: false }) {} | ^ ^ @@ -23,7 +23,7 @@ error: struct literals are not allowed here | LL | if x == E::J { field: -42 } {} | ^^^^^^^^^^^^^^^^^^^ -help: surround the struct literal with parenthesis +help: surround the struct literal with parentheses | LL | if x == (E::J { field: -42 }) {} | ^ ^ @@ -33,7 +33,7 @@ error: struct literals are not allowed here | LL | if x == E::K { field: "" } {} | ^^^^^^^^^^^^^^^^^^ -help: surround the struct literal with parenthesis +help: surround the struct literal with parentheses | LL | if x == (E::K { field: "" }) {} | ^ ^ From f6a4b5270a0007e950546828a7f6fc7c54354b96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 2 May 2019 16:13:28 -0700 Subject: [PATCH 021/212] Deduplicate needed parentheses suggestion code --- src/librustc_typeck/check/mod.rs | 16 +++++----------- src/libsyntax/parse/mod.rs | 23 ++++++++++++++++++++++- src/libsyntax/parse/parser.rs | 29 ++++++----------------------- 3 files changed, 33 insertions(+), 35 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a0050b1359679..763d6b898a484 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4177,17 +4177,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(sp) = tcx.sess.parse_sess.abiguous_block_expr_parse .borrow().get(&sp) { - if let Ok(snippet) = tcx.sess.source_map() - .span_to_snippet(*sp) - { - err.span_suggestion( - *sp, - "parentheses are required to parse this \ - as an expression", - format!("({})", snippet), - Applicability::MachineApplicable, - ); - } + tcx.sess.parse_sess.expr_parentheses_needed( + &mut err, + *sp, + None, + ); } err.emit(); oprnd_t = tcx.types.err; diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 94bbd5ba2f75b..0d41a1ff84904 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -11,7 +11,7 @@ use crate::tokenstream::{TokenStream, TokenTree}; use crate::diagnostics::plugin::ErrorMap; use crate::print::pprust::token_to_string; -use errors::{FatalError, Level, Handler, ColorConfig, Diagnostic, DiagnosticBuilder}; +use errors::{Applicability, FatalError, Level, Handler, ColorConfig, Diagnostic, DiagnosticBuilder}; use rustc_data_structures::sync::{Lrc, Lock}; use syntax_pos::{Span, SourceFile, FileName, MultiSpan}; use log::debug; @@ -47,6 +47,9 @@ pub struct ParseSess { included_mod_stack: Lock>, source_map: Lrc, pub buffered_lints: Lock>, + /// Contains the spans of block expressions that could have been incomplete based on the + /// operation token that followed it, but that the parser cannot identify without further + /// analysis. pub abiguous_block_expr_parse: Lock>, } @@ -95,6 +98,24 @@ impl ParseSess { }); }); } + + /// Extend an error with a suggestion to wrap an expression with parentheses to allow the + /// parser to continue parsing the following operation as part of the same expression. + pub fn expr_parentheses_needed( + &self, + err: &mut DiagnosticBuilder<'_>, + span: Span, + alt_snippet: Option, + ) { + if let Some(snippet) = self.source_map().span_to_snippet(span).ok().or(alt_snippet) { + err.span_suggestion( + span, + "parentheses are required to parse this as an expression", + format!("({})", snippet), + Applicability::MachineApplicable, + ); + } + } } #[derive(Clone)] diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 02e6c5e1c8dbf..66d45f799d97d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2931,14 +2931,7 @@ impl<'a> Parser<'a> { if let Some(sp) = self.sess.abiguous_block_expr_parse.borrow() .get(&sp) { - if let Ok(snippet) = self.sess.source_map().span_to_snippet(*sp) { - err.span_suggestion( - *sp, - "parentheses are required to parse this as an expression", - format!("({})", snippet), - Applicability::MachineApplicable, - ); - } + self.sess.expr_parentheses_needed(&mut err, *sp, None); } err.span_label(self.span, "expected expression"); return Err(err); @@ -3657,14 +3650,11 @@ impl<'a> Parser<'a> { pprust::token_to_string(&self.token), )); err.span_label(self.span, "expected expression"); - let snippet = self.sess.source_map().span_to_snippet(lhs.span) - .unwrap_or_else(|_| pprust::expr_to_string(&lhs)); - err.span_suggestion( + self.sess.expr_parentheses_needed( + &mut err, lhs.span, - "parentheses are required to parse this as an expression", - format!("({})", snippet), - Applicability::MachineApplicable, - ); + Some(pprust::expr_to_string(&lhs), + )); err.emit(); } } @@ -4979,14 +4969,7 @@ impl<'a> Parser<'a> { err.span_label(self.span, format!("expected {}", expected)); let sp = self.sess.source_map().start_point(self.span); if let Some(sp) = self.sess.abiguous_block_expr_parse.borrow().get(&sp) { - if let Ok(snippet) = self.sess.source_map().span_to_snippet(*sp) { - err.span_suggestion( - *sp, - "parentheses are required to parse this as an expression", - format!("({})", snippet), - Applicability::MachineApplicable, - ); - } + self.sess.expr_parentheses_needed(&mut err, *sp, None); } return Err(err); } From 750808680add716394e94b4abb2a711b01400fb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 25 Apr 2019 11:36:16 -0700 Subject: [PATCH 022/212] Don't ICE when relating const type args --- src/test/ui/const-generics/issue-60263.rs | 9 +++++++++ src/test/ui/const-generics/issue-60263.stderr | 12 ++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 src/test/ui/const-generics/issue-60263.rs create mode 100644 src/test/ui/const-generics/issue-60263.stderr diff --git a/src/test/ui/const-generics/issue-60263.rs b/src/test/ui/const-generics/issue-60263.rs new file mode 100644 index 0000000000000..70cbc242c41a5 --- /dev/null +++ b/src/test/ui/const-generics/issue-60263.rs @@ -0,0 +1,9 @@ +struct B; //~ ERROR const generics are unstable + +impl B<0> { + fn bug() -> Self { + panic!() + } +} + +fn main() {} diff --git a/src/test/ui/const-generics/issue-60263.stderr b/src/test/ui/const-generics/issue-60263.stderr new file mode 100644 index 0000000000000..ab1b9e4a7cd86 --- /dev/null +++ b/src/test/ui/const-generics/issue-60263.stderr @@ -0,0 +1,12 @@ +error[E0658]: const generics are unstable + --> $DIR/issue-60263.rs:1:16 + | +LL | struct B; + | ^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/44580 + = help: add #![feature(const_generics)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. From 8fc6e420d16dc882f2047e6ec1b981cac5ef0d14 Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Fri, 3 May 2019 12:55:31 -0400 Subject: [PATCH 023/212] use span instead of div for since version --- src/librustdoc/html/render.rs | 2 +- src/librustdoc/html/static/rustdoc.css | 2 +- src/test/rustdoc/assoc-consts-version.rs | 5 ++--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index f4af362a55702..472192a646492 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -3410,7 +3410,7 @@ fn render_stability_since_raw<'a, T: fmt::Write>( ) -> fmt::Result { if let Some(v) = ver { if containing_ver != ver && v.len() > 0 { - write!(w, "
{0}
", v)? + write!(w, "{0}", v)? } } Ok(()) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 358549117a307..4204d20498d70 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -914,7 +914,7 @@ h3 > .collapse-toggle, h4 > .collapse-toggle { height: 12px; } -span.since { +.out-of-band > span.since { position: initial; font-size: 20px; margin-right: 5px; diff --git a/src/test/rustdoc/assoc-consts-version.rs b/src/test/rustdoc/assoc-consts-version.rs index c561269cf9a85..6060bc0a6fd5c 100644 --- a/src/test/rustdoc/assoc-consts-version.rs +++ b/src/test/rustdoc/assoc-consts-version.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - #![crate_name = "foo"] #![feature(staged_api)] @@ -10,7 +8,8 @@ pub struct SomeStruct; impl SomeStruct { - // @has 'foo/struct.SomeStruct.html' '//*[@id="associatedconstant.SOME_CONST"]//div[@class="since"]' '1.1.2' + // @has 'foo/struct.SomeStruct.html' \ + // '//*[@id="associatedconstant.SOME_CONST"]//span[@class="since"]' '1.1.2' #[stable(since="1.1.2", feature="rust2")] pub const SOME_CONST: usize = 0; } From 884632cc796816fd9d3c8de60f2245c216f9a25a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 3 May 2019 13:59:50 -0700 Subject: [PATCH 024/212] rustc: Always handle exported symbols on the wasm target Currently when linking an artifact rustc will only conditionally call the `Linker::export_symbols` function, but this causes issues on some targets, like WebAssembly, where it means that executable outputs will not have the same symbols exported that cdylib outputs have. This commit sinks the conditional call to `export_symbols` inside the various implementations of the function that still need it, and otherwise the wasm linker is configured to always pass through symbol visibility lists. --- src/librustc_codegen_ssa/back/link.rs | 10 ++++------ src/librustc_codegen_ssa/back/linker.rs | 10 ++++++++++ src/test/run-make/wasm-export-all-symbols/Makefile | 6 ++++++ src/test/run-make/wasm-export-all-symbols/main.rs | 3 +++ src/test/run-make/wasm-export-all-symbols/verify.js | 10 ++++++++-- 5 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 src/test/run-make/wasm-export-all-symbols/main.rs diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index f25891d77ce53..d530af559af13 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -1017,12 +1017,10 @@ fn link_args<'a, B: ArchiveBuilder<'a>>(cmd: &mut dyn Linker, } } - // If we're building a dynamic library then some platforms need to make sure - // that all symbols are exported correctly from the dynamic library. - if crate_type != config::CrateType::Executable || - sess.target.target.options.is_like_emscripten { - cmd.export_symbols(tmpdir, crate_type); - } + // If we're building something like a dynamic library then some platforms + // need to make sure that all symbols are exported correctly from the + // dynamic library. + cmd.export_symbols(tmpdir, crate_type); // When linking a dynamic library, we put the metadata into a section of the // executable. This metadata is in a separate object file from the main diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs index c99fc17dd89a1..926f4febe7bae 100644 --- a/src/librustc_codegen_ssa/back/linker.rs +++ b/src/librustc_codegen_ssa/back/linker.rs @@ -372,6 +372,11 @@ impl<'a> Linker for GccLinker<'a> { } fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) { + // Symbol visibility in object files typically takes care of this. + if crate_type == CrateType::Executable { + return; + } + // If we're compiling a dylib, then we let symbol visibility in object // files to take care of whether they're exported or not. // @@ -645,6 +650,11 @@ impl<'a> Linker for MsvcLinker<'a> { fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) { + // Symbol visibility takes care of this typically + if crate_type == CrateType::Executable { + return; + } + let path = tmpdir.join("lib.def"); let res: io::Result<()> = try { let mut f = BufWriter::new(File::create(&path)?); diff --git a/src/test/run-make/wasm-export-all-symbols/Makefile b/src/test/run-make/wasm-export-all-symbols/Makefile index 039481215f0a6..15403d8d4109d 100644 --- a/src/test/run-make/wasm-export-all-symbols/Makefile +++ b/src/test/run-make/wasm-export-all-symbols/Makefile @@ -6,8 +6,14 @@ all: $(RUSTC) bar.rs --target wasm32-unknown-unknown $(RUSTC) foo.rs --target wasm32-unknown-unknown $(NODE) verify.js $(TMPDIR)/foo.wasm + $(RUSTC) main.rs --target wasm32-unknown-unknown + $(NODE) verify.js $(TMPDIR)/main.wasm $(RUSTC) bar.rs --target wasm32-unknown-unknown -O $(RUSTC) foo.rs --target wasm32-unknown-unknown -O $(NODE) verify.js $(TMPDIR)/foo.wasm + $(RUSTC) main.rs --target wasm32-unknown-unknown -O + $(NODE) verify.js $(TMPDIR)/main.wasm $(RUSTC) foo.rs --target wasm32-unknown-unknown -C lto $(NODE) verify.js $(TMPDIR)/foo.wasm + $(RUSTC) main.rs --target wasm32-unknown-unknown -C lto + $(NODE) verify.js $(TMPDIR)/main.wasm diff --git a/src/test/run-make/wasm-export-all-symbols/main.rs b/src/test/run-make/wasm-export-all-symbols/main.rs new file mode 100644 index 0000000000000..0edda7d7b8842 --- /dev/null +++ b/src/test/run-make/wasm-export-all-symbols/main.rs @@ -0,0 +1,3 @@ +extern crate bar; + +fn main() {} diff --git a/src/test/run-make/wasm-export-all-symbols/verify.js b/src/test/run-make/wasm-export-all-symbols/verify.js index 0f56fa45c223d..7b6fc7a45682b 100644 --- a/src/test/run-make/wasm-export-all-symbols/verify.js +++ b/src/test/run-make/wasm-export-all-symbols/verify.js @@ -16,7 +16,13 @@ for (const entry of list) { nexports += 1; } -if (nexports != 1) - throw new Error("should only have one function export"); if (my_exports.foo === undefined) throw new Error("`foo` wasn't defined"); + +if (my_exports.main === undefined) { + if (nexports != 1) + throw new Error("should only have one function export"); +} else { + if (nexports != 2) + throw new Error("should only have two function exports"); +} From ea178e47b95119fc626b88f0b61187242b3ae487 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 4 May 2019 03:26:52 +0200 Subject: [PATCH 025/212] Enforce sorting of accepted and removed features. --- src/libsyntax/feature_gate.rs | 39 ++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 2a1f3c4801406..40cf181543f4e 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -108,8 +108,8 @@ macro_rules! declare_features { // was set. This is most important for knowing when a particular feature became // stable (active). // -// Note that the features should be grouped into internal/user-facing -// and then sorted by version inside those groups. This is inforced with tidy. +// Note that the features are grouped into internal/user-facing and then +// sorted by version inside those groups. This is inforced with tidy. // // N.B., `tools/tidy/src/features.rs` parses this information directly out of the // source, so take care when modifying it. @@ -197,9 +197,6 @@ declare_features! ( // Allows using `#[unsafe_destructor_blind_to_params]` (RFC 1238). (active, dropck_parametricity, "1.3.0", Some(28498), None), - // FIXME(Centril): Investigate whether this gate actually has any effect. - (active, needs_allocator, "1.4.0", Some(27389), None), - // no tracking issue START // Allows using `#[omit_gdb_pretty_printer_section]`. @@ -567,6 +564,10 @@ const INCOMPLETE_FEATURES: &[&str] = &[ ]; declare_features! ( + // ------------------------------------------------------------------------- + // feature-group-start: removed features + // ------------------------------------------------------------------------- + (removed, import_shadowing, "1.0.0", None, None, None), (removed, managed_boxes, "1.0.0", None, None, None), // Allows use of unary negate on unsigned integers, e.g., -e for e: u8 @@ -581,7 +582,6 @@ declare_features! ( (removed, unsafe_no_drop_flag, "1.0.0", None, None, None), // Allows using items which are missing stability attributes (removed, unmarked_api, "1.0.0", None, None, None), - (removed, pushpop_unsafe, "1.2.0", None, None, None), (removed, allocator, "1.0.0", None, None, None), (removed, simd, "1.0.0", Some(27731), None, Some("removed in favor of `#[repr(simd)]`")), @@ -589,6 +589,9 @@ declare_features! ( Some("merged into `#![feature(slice_patterns)]`")), (removed, macro_reexport, "1.0.0", Some(29638), None, Some("subsumed by `pub use`")), + (removed, pushpop_unsafe, "1.2.0", None, None, None), + (removed, needs_allocator, "1.4.0", Some(27389), None, + Some("subsumed by `#![feature(allocator_internals)]`")), (removed, proc_macro_mod, "1.27.0", Some(54727), None, Some("subsumed by `#![feature(proc_macro_hygiene)]`")), (removed, proc_macro_expr, "1.27.0", Some(54727), None, @@ -600,12 +603,16 @@ declare_features! ( (removed, panic_implementation, "1.28.0", Some(44489), None, Some("subsumed by `#[panic_handler]`")), // Allows the use of `#[derive(Anything)]` as sugar for `#[derive_Anything]`. - (removed, custom_derive, "1.0.0", Some(29644), None, + (removed, custom_derive, "1.32.0", Some(29644), None, Some("subsumed by `#[proc_macro_derive]`")), // Paths of the form: `extern::foo::bar` (removed, extern_in_paths, "1.33.0", Some(55600), None, Some("subsumed by `::foo::bar` paths")), - (removed, quote, "1.0.0", Some(29601), None, None), + (removed, quote, "1.33.0", Some(29601), None, None), + + // ------------------------------------------------------------------------- + // feature-group-end: removed features + // ------------------------------------------------------------------------- ); declare_features! ( @@ -613,6 +620,10 @@ declare_features! ( ); declare_features! ( + // ------------------------------------------------------------------------- + // feature-group-start: for testing purposes + // ------------------------------------------------------------------------- + // A temporary feature gate used to enable parser extensions needed // to bootstrap fix for #5723. (accepted, issue_5723_bootstrap, "1.0.0", None, None), @@ -620,6 +631,14 @@ declare_features! ( // they don't actually mean anything. (accepted, test_accepted_feature, "1.0.0", None, None), + // ------------------------------------------------------------------------- + // feature-group-end: for testing purposes + // ------------------------------------------------------------------------- + + // ------------------------------------------------------------------------- + // feature-group-start: accepted features + // ------------------------------------------------------------------------- + // Allows using associated `type`s in `trait`s. (accepted, associated_types, "1.0.0", None, None), // Allows using assigning a default type to type parameters in algebraic data type definitions. @@ -809,6 +828,10 @@ declare_features! ( (accepted, extern_crate_self, "1.34.0", Some(56409), None), // Allows arbitrary delimited token streams in non-macro attributes. (accepted, unrestricted_attribute_tokens, "1.34.0", Some(55208), None), + + // ------------------------------------------------------------------------- + // feature-group-end: accepted features + // ------------------------------------------------------------------------- ); // If you change this, please modify `src/doc/unstable-book` as well. You must From d7acf596cf01d01ec916752aa26a6e1c83dd4634 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 4 May 2019 03:34:05 +0200 Subject: [PATCH 026/212] Rename 'no tracking issue START' to fit better with tidy. --- src/libsyntax/feature_gate.rs | 16 ++++++++-------- src/tools/tidy/src/features.rs | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 40cf181543f4e..ae297f9a4a3fd 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -119,7 +119,7 @@ declare_features! ( // feature-group-start: internal feature gates // ------------------------------------------------------------------------- - // no tracking issue START + // no-tracking-issue-start // Allows using the `rust-intrinsic`'s "ABI". (active, intrinsics, "1.0.0", None, None), @@ -152,7 +152,7 @@ declare_features! ( // lets a function to be `const` when opted into with `#![feature(foo)]`. (active, rustc_const_unstable, "1.0.0", None, None), - // no tracking issue END + // no-tracking-issue-end // Allows using `#[link_name="llvm.*"]`. (active, link_llvm_intrinsics, "1.0.0", Some(29602), None), @@ -187,17 +187,17 @@ declare_features! ( // Allows using `box` in patterns (RFC 469). (active, box_patterns, "1.0.0", Some(29641), None), - // no tracking issue START + // no-tracking-issue-start // Allows using `#[prelude_import]` on glob `use` items. (active, prelude_import, "1.2.0", None, None), - // no tracking issue END + // no-tracking-issue-end // Allows using `#[unsafe_destructor_blind_to_params]` (RFC 1238). (active, dropck_parametricity, "1.3.0", Some(28498), None), - // no tracking issue START + // no-tracking-issue-start // Allows using `#[omit_gdb_pretty_printer_section]`. (active, omit_gdb_pretty_printer_section, "1.5.0", None, None), @@ -205,7 +205,7 @@ declare_features! ( // Allows using the `vectorcall` ABI. (active, abi_vectorcall, "1.7.0", None, None), - // no tracking issue END + // no-tracking-issue-end // Allows using `#[structural_match]` which indicates that a type is structurally matchable. (active, structural_match, "1.8.0", Some(31434), None), @@ -219,7 +219,7 @@ declare_features! ( // Allows declaring with `#![needs_panic_runtime]` that a panic runtime is needed. (active, needs_panic_runtime, "1.10.0", Some(32837), None), - // no tracking issue START + // no-tracking-issue-start // Allows identifying the `compiler_builtins` crate. (active, compiler_builtins, "1.13.0", None, None), @@ -242,7 +242,7 @@ declare_features! ( // Allows using the `format_args_nl` macro. (active, format_args_nl, "1.29.0", None, None), - // no tracking issue END + // no-tracking-issue-end // Added for testing E0705; perma-unstable. (active, test_2018_feature, "1.31.0", Some(0), Some(Edition::Edition2018)), diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index 3144df6dd4cdf..a1a8ab806ea40 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -191,7 +191,7 @@ pub fn collect_lang_features(base_src_path: &Path, bad: &mut bool) -> Features { // We allow rustc-internal features to omit a tracking issue. // To make tidy accept omitting a tracking issue, group the list of features - // without one inside `// no tracking issue START` and `// no tracking issue END`. + // without one inside `// no-tracking-issue` and `// no-tracking-issue-end`. let mut next_feature_omits_tracking_issue = false; let mut in_feature_group = false; @@ -201,13 +201,13 @@ pub fn collect_lang_features(base_src_path: &Path, bad: &mut bool) -> Features { .filter_map(|(line, line_number)| { let line = line.trim(); - // Within START and END, the tracking issue can be omitted. + // Within -start and -end, the tracking issue can be omitted. match line { - "// no tracking issue START" => { + "// no-tracking-issue-start" => { next_feature_omits_tracking_issue = true; return None; } - "// no tracking issue END" => { + "// no-tracking-issue-end" => { next_feature_omits_tracking_issue = false; return None; } From e5b9f54cd99b425ffe99e732995b9fd3be7b1d36 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 3 May 2019 21:51:24 +0300 Subject: [PATCH 027/212] rustc: collapse relevant DefPathData variants into TypeNs. --- src/librustc/hir/map/def_collector.rs | 20 ++++----- src/librustc/hir/map/definitions.rs | 32 -------------- src/librustc/ty/print/pretty.rs | 4 +- src/librustc/ty/util.rs | 13 ++---- src/librustc_metadata/encoder.rs | 7 ++- src/librustc_mir/monomorphize/partitioning.rs | 44 ++++++++----------- src/librustc_traits/lowering/mod.rs | 25 ++++++++--- src/test/ui/symbol-names/basic.stderr | 2 +- src/test/ui/symbol-names/impl1.stderr | 4 +- 9 files changed, 61 insertions(+), 90 deletions(-) diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 78de85398594e..e3e451a61f578 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -139,14 +139,13 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { // information we encapsulate into, the better let def_data = match i.node { ItemKind::Impl(..) => DefPathData::Impl, - ItemKind::Trait(..) => DefPathData::Trait(i.ident.as_interned_str()), - ItemKind::TraitAlias(..) => DefPathData::TraitAlias(i.ident.as_interned_str()), - ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | - ItemKind::Existential(..) | ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | - ItemKind::Ty(..) => DefPathData::TypeNs(i.ident.as_interned_str()), ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => { return visit::walk_item(self, i); } + ItemKind::Mod(..) | ItemKind::Trait(..) | ItemKind::TraitAlias(..) | + ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | + ItemKind::Existential(..) | ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | + ItemKind::Ty(..) => DefPathData::TypeNs(i.ident.as_interned_str()), ItemKind::Fn( ref decl, ref header, @@ -163,7 +162,6 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { body, ) } - ItemKind::Mod(..) => DefPathData::Module(i.ident.as_interned_str()), ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) => DefPathData::ValueNs(i.ident.as_interned_str()), ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.as_interned_str()), @@ -211,7 +209,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_variant(&mut self, v: &'a Variant, g: &'a Generics, item_id: NodeId) { let def = self.create_def(v.node.id, - DefPathData::EnumVariant(v.node.ident.as_interned_str()), + DefPathData::TypeNs(v.node.ident.as_interned_str()), REGULAR_SPACE, v.span); self.with_parent(def, |this| { @@ -239,7 +237,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { let name = param.ident.as_interned_str(); let def_path_data = match param.kind { GenericParamKind::Lifetime { .. } => DefPathData::LifetimeParam(name), - GenericParamKind::Type { .. } => DefPathData::TypeParam(name), + GenericParamKind::Type { .. } => DefPathData::TypeNs(name), GenericParamKind::Const { .. } => DefPathData::ConstParam(name), }; self.create_def(param.id, def_path_data, REGULAR_SPACE, param.ident.span); @@ -252,7 +250,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { TraitItemKind::Method(..) | TraitItemKind::Const(..) => DefPathData::ValueNs(ti.ident.as_interned_str()), TraitItemKind::Type(..) => { - DefPathData::AssocTypeInTrait(ti.ident.as_interned_str()) + DefPathData::TypeNs(ti.ident.as_interned_str()) }, TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id), }; @@ -279,9 +277,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { } ImplItemKind::Method(..) | ImplItemKind::Const(..) => DefPathData::ValueNs(ii.ident.as_interned_str()), - ImplItemKind::Type(..) => DefPathData::AssocTypeInImpl(ii.ident.as_interned_str()), + ImplItemKind::Type(..) | ImplItemKind::Existential(..) => { - DefPathData::AssocExistentialInImpl(ii.ident.as_interned_str()) + DefPathData::TypeNs(ii.ident.as_interned_str()) }, ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id), }; diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 1006d813e65ed..99b3865c82a1a 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -337,33 +337,19 @@ pub enum DefPathData { // Different kinds of items and item-like things: /// An impl Impl, - /// A trait - Trait(InternedString), - /// An associated type **declaration** (i.e., in a trait) - AssocTypeInTrait(InternedString), - /// An associated type **value** (i.e., in an impl) - AssocTypeInImpl(InternedString), - /// An existential associated type **value** (i.e., in an impl) - AssocExistentialInImpl(InternedString), /// Something in the type NS TypeNs(InternedString), /// Something in the value NS ValueNs(InternedString), - /// A module declaration - Module(InternedString), /// A macro rule MacroDef(InternedString), /// A closure expression ClosureExpr, // Subportions of items - /// A type (generic) parameter - TypeParam(InternedString), /// A lifetime (generic) parameter LifetimeParam(InternedString), /// A const (generic) parameter ConstParam(InternedString), - /// A variant of a enum - EnumVariant(InternedString), /// A struct field Field(InternedString), /// Implicit ctor for a unit or tuple-like struct or enum variant. @@ -376,8 +362,6 @@ pub enum DefPathData { /// a whole crate (as opposed to just one item). GlobalMetaData components /// are only supposed to show up right below the crate root. GlobalMetaData(InternedString), - /// A trait alias. - TraitAlias(InternedString), } #[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, @@ -633,18 +617,10 @@ impl DefPathData { use self::DefPathData::*; match *self { TypeNs(name) | - Trait(name) | - TraitAlias(name) | - AssocTypeInTrait(name) | - AssocTypeInImpl(name) | - AssocExistentialInImpl(name) | ValueNs(name) | - Module(name) | MacroDef(name) | - TypeParam(name) | LifetimeParam(name) | ConstParam(name) | - EnumVariant(name) | Field(name) | GlobalMetaData(name) => Some(name), @@ -662,18 +638,10 @@ impl DefPathData { use self::DefPathData::*; let s = match *self { TypeNs(name) | - Trait(name) | - TraitAlias(name) | - AssocTypeInTrait(name) | - AssocTypeInImpl(name) | - AssocExistentialInImpl(name) | ValueNs(name) | - Module(name) | MacroDef(name) | - TypeParam(name) | LifetimeParam(name) | ConstParam(name) | - EnumVariant(name) | Field(name) | GlobalMetaData(name) => { return name diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index d10da495ee72b..c66610c98d5e3 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -355,7 +355,6 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: // the children of the visible parent (as was done when computing // `visible_parent_map`), looking for the specific child we currently have and then // have access to the re-exported name. - DefPathData::Module(ref mut name) | DefPathData::TypeNs(ref mut name) if Some(visible_parent) != actual_parent => { let reexport = self.tcx().item_children(visible_parent) .iter() @@ -367,7 +366,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: } // Re-exported `extern crate` (#43189). DefPathData::CrateRoot => { - data = DefPathData::Module( + data = DefPathData::TypeNs( self.tcx().original_crate_name(def_id.krate).as_interned_str(), ); } @@ -860,7 +859,6 @@ impl TyCtxt<'_, '_, '_> { fn guess_def_namespace(self, def_id: DefId) -> Namespace { match self.def_key(def_id).disambiguated_data.data { DefPathData::ValueNs(..) | - DefPathData::EnumVariant(..) | DefPathData::Field(..) | DefPathData::AnonConst | DefPathData::ConstParam(..) | diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 0cd1700dd0d75..4c8ed71a57ca6 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -1,6 +1,7 @@ //! Miscellaneous type-system utilities that are too small to deserve their own modules. use crate::hir; +use crate::hir::def::DefKind; use crate::hir::def_id::DefId; use crate::hir::map::DefPathData; use crate::mir::interpret::{sign_extend, truncate}; @@ -529,21 +530,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Returns `true` if `def_id` refers to a trait (i.e., `trait Foo { ... }`). pub fn is_trait(self, def_id: DefId) -> bool { - if let DefPathData::Trait(_) = self.def_key(def_id).disambiguated_data.data { - true - } else { - false - } + self.def_kind(def_id) == Some(DefKind::Trait) } /// Returns `true` if `def_id` refers to a trait alias (i.e., `trait Foo = ...;`), /// and `false` otherwise. pub fn is_trait_alias(self, def_id: DefId) -> bool { - if let DefPathData::TraitAlias(_) = self.def_key(def_id).disambiguated_data.data { - true - } else { - false - } + self.def_kind(def_id) == Some(DefKind::TraitAlias) } /// Returns `true` if this `DefId` refers to the implicit constructor for diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index f914184b34f54..0946dad53203d 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -586,8 +586,13 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { let data = VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, + // FIXME(eddyb) deduplicate these with `encode_enum_variant_ctor`. ctor: variant.ctor_def_id.map(|did| did.index), - ctor_sig: None, + ctor_sig: if variant.ctor_kind == CtorKind::Fn { + variant.ctor_def_id.map(|ctor_def_id| self.lazy(&tcx.fn_sig(ctor_def_id))) + } else { + None + }, }; let enum_id = tcx.hir().as_local_hir_id(enum_did).unwrap(); diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index 368bcc333996f..f321e05d68115 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -99,11 +99,11 @@ use std::sync::Arc; use syntax::symbol::InternedString; use rustc::dep_graph::{WorkProductId, WorkProduct, DepNode, DepConstructor}; use rustc::hir::{CodegenFnAttrFlags, HirId}; +use rustc::hir::def::DefKind; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE, CRATE_DEF_INDEX}; -use rustc::hir::map::DefPathData; use rustc::mir::mono::{Linkage, Visibility, CodegenUnitNameBuilder}; use rustc::middle::exported_symbols::SymbolExportLevel; -use rustc::ty::{self, TyCtxt, InstanceDef}; +use rustc::ty::{self, DefIdTree, TyCtxt, InstanceDef}; use rustc::ty::print::characteristic_def_id_of_type; use rustc::ty::query::Providers; use rustc::util::common::time; @@ -805,33 +805,27 @@ fn compute_codegen_unit_name(tcx: TyCtxt<'_, '_, '_>, let mut cgu_def_id = None; // Walk backwards from the item we want to find the module for: loop { - let def_key = tcx.def_key(current_def_id); - - match def_key.disambiguated_data.data { - DefPathData::Module(..) => { - if cgu_def_id.is_none() { - cgu_def_id = Some(current_def_id); - } + if current_def_id.index == CRATE_DEF_INDEX { + if cgu_def_id.is_none() { + // If we have not found a module yet, take the crate root. + cgu_def_id = Some(DefId { + krate: def_id.krate, + index: CRATE_DEF_INDEX, + }); } - DefPathData::CrateRoot { .. } => { - if cgu_def_id.is_none() { - // If we have not found a module yet, take the crate root. - cgu_def_id = Some(DefId { - krate: def_id.krate, - index: CRATE_DEF_INDEX, - }); - } - break - } - _ => { - // If we encounter something that is not a module, throw away - // any module that we've found so far because we now know that - // it is nested within something else. - cgu_def_id = None; + break + } else if tcx.def_kind(current_def_id) == Some(DefKind::Mod) { + if cgu_def_id.is_none() { + cgu_def_id = Some(current_def_id); } + } else { + // If we encounter something that is not a module, throw away + // any module that we've found so far because we now know that + // it is nested within something else. + cgu_def_id = None; } - current_def_id.index = def_key.parent.unwrap(); + current_def_id = tcx.parent(current_def_id).unwrap(); } let cgu_def_id = cgu_def_id.unwrap(); diff --git a/src/librustc_traits/lowering/mod.rs b/src/librustc_traits/lowering/mod.rs index c3cbdb0376251..50c2130263295 100644 --- a/src/librustc_traits/lowering/mod.rs +++ b/src/librustc_traits/lowering/mod.rs @@ -1,5 +1,6 @@ mod environment; +use rustc::hir::def::DefKind; use rustc::hir::def_id::DefId; use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc::hir::map::definitions::DefPathData; @@ -157,13 +158,27 @@ crate fn program_clauses_for<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, ) -> Clauses<'tcx> { + // FIXME(eddyb) this should only be using `def_kind`. match tcx.def_key(def_id).disambiguated_data.data { - DefPathData::Trait(_) | - DefPathData::TraitAlias(_) => program_clauses_for_trait(tcx, def_id), + DefPathData::TypeNs(..) => match tcx.def_kind(def_id) { + Some(DefKind::Trait) + | Some(DefKind::TraitAlias) => program_clauses_for_trait(tcx, def_id), + // FIXME(eddyb) deduplicate this `associated_item` call with + // `program_clauses_for_associated_type_{value,def}`. + Some(DefKind::AssociatedTy) => match tcx.associated_item(def_id).container { + ty::AssociatedItemContainer::ImplContainer(_) => + program_clauses_for_associated_type_value(tcx, def_id), + ty::AssociatedItemContainer::TraitContainer(_) => + program_clauses_for_associated_type_def(tcx, def_id) + }, + Some(DefKind::Struct) + | Some(DefKind::Enum) + | Some(DefKind::TyAlias) + | Some(DefKind::Union) + | Some(DefKind::Existential) => program_clauses_for_type_def(tcx, def_id), + _ => List::empty(), + }, DefPathData::Impl => program_clauses_for_impl(tcx, def_id), - DefPathData::AssocTypeInImpl(..) => program_clauses_for_associated_type_value(tcx, def_id), - DefPathData::AssocTypeInTrait(..) => program_clauses_for_associated_type_def(tcx, def_id), - DefPathData::TypeNs(..) => program_clauses_for_type_def(tcx, def_id), _ => List::empty(), } } diff --git a/src/test/ui/symbol-names/basic.stderr b/src/test/ui/symbol-names/basic.stderr index 6ddd93d632e15..7539cbada8b7b 100644 --- a/src/test/ui/symbol-names/basic.stderr +++ b/src/test/ui/symbol-names/basic.stderr @@ -1,4 +1,4 @@ -error: symbol-name(_ZN5basic4main17h08bcaf310214ed52E) +error: symbol-name(_ZN5basic4main17hd72940ef9669d526E) --> $DIR/basic.rs:3:1 | LL | #[rustc_symbol_name] diff --git a/src/test/ui/symbol-names/impl1.stderr b/src/test/ui/symbol-names/impl1.stderr index eda8646b5b4de..20e48782a3a9e 100644 --- a/src/test/ui/symbol-names/impl1.stderr +++ b/src/test/ui/symbol-names/impl1.stderr @@ -1,4 +1,4 @@ -error: symbol-name(_ZN5impl13foo3Foo3bar17hc487d6ec13fe9124E) +error: symbol-name(_ZN5impl13foo3Foo3bar17he53b9bee7600ed8dE) --> $DIR/impl1.rs:8:9 | LL | #[rustc_symbol_name] @@ -10,7 +10,7 @@ error: def-path(foo::Foo::bar) LL | #[rustc_def_path] | ^^^^^^^^^^^^^^^^^ -error: symbol-name(_ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz17h38577281258e1527E) +error: symbol-name(_ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz17h86c41f0462d901d4E) --> $DIR/impl1.rs:18:9 | LL | #[rustc_symbol_name] From 2efeb485a99dc3a769f21f111310a6541b21d8b2 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 3 May 2019 22:28:29 +0300 Subject: [PATCH 028/212] rustc: collapse relevant DefPathData variants into ValueNs. --- src/librustc/hir/map/def_collector.rs | 4 ++-- src/librustc/hir/map/definitions.rs | 8 -------- src/librustc/ty/print/pretty.rs | 2 -- 3 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index e3e451a61f578..3b2bdfc8b89f8 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -226,7 +226,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { let name = field.ident.map(|ident| ident.name) .unwrap_or_else(|| Symbol::intern(&index.to_string())); let def = self.create_def(field.id, - DefPathData::Field(name.as_interned_str()), + DefPathData::ValueNs(name.as_interned_str()), REGULAR_SPACE, field.span); self.with_parent(def, |this| this.visit_struct_field(field)); @@ -238,7 +238,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { let def_path_data = match param.kind { GenericParamKind::Lifetime { .. } => DefPathData::LifetimeParam(name), GenericParamKind::Type { .. } => DefPathData::TypeNs(name), - GenericParamKind::Const { .. } => DefPathData::ConstParam(name), + GenericParamKind::Const { .. } => DefPathData::ValueNs(name), }; self.create_def(param.id, def_path_data, REGULAR_SPACE, param.ident.span); diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 99b3865c82a1a..ddc76140167f4 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -348,10 +348,6 @@ pub enum DefPathData { // Subportions of items /// A lifetime (generic) parameter LifetimeParam(InternedString), - /// A const (generic) parameter - ConstParam(InternedString), - /// A struct field - Field(InternedString), /// Implicit ctor for a unit or tuple-like struct or enum variant. Ctor, /// A constant expression (see {ast,hir}::AnonConst). @@ -620,8 +616,6 @@ impl DefPathData { ValueNs(name) | MacroDef(name) | LifetimeParam(name) | - ConstParam(name) | - Field(name) | GlobalMetaData(name) => Some(name), Impl | @@ -641,8 +635,6 @@ impl DefPathData { ValueNs(name) | MacroDef(name) | LifetimeParam(name) | - ConstParam(name) | - Field(name) | GlobalMetaData(name) => { return name } diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index c66610c98d5e3..5836e510cadf4 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -859,9 +859,7 @@ impl TyCtxt<'_, '_, '_> { fn guess_def_namespace(self, def_id: DefId) -> Namespace { match self.def_key(def_id).disambiguated_data.data { DefPathData::ValueNs(..) | - DefPathData::Field(..) | DefPathData::AnonConst | - DefPathData::ConstParam(..) | DefPathData::ClosureExpr | DefPathData::Ctor => Namespace::ValueNS, From 60f1944ebf29d738d870df86ee46c92cb3f09448 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 3 May 2019 22:45:36 +0300 Subject: [PATCH 029/212] rustc: rename DefPathData::{MacroDef,LifetimeParam} to {Macro,Lifetime}Ns. --- src/librustc/hir/lowering.rs | 4 ++-- src/librustc/hir/map/def_collector.rs | 4 ++-- src/librustc/hir/map/definitions.rs | 16 ++++++++-------- src/librustc/ty/print/pretty.rs | 14 +++++++++----- src/librustc_metadata/decoder.rs | 2 +- 5 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 8361a62c07e48..0ac9429de1392 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -952,7 +952,7 @@ impl<'a> LoweringContext<'a> { self.resolver.definitions().create_def_with_parent( parent_index, node_id, - DefPathData::LifetimeParam(str_name), + DefPathData::LifetimeNs(str_name), DefIndexAddressSpace::High, Mark::root(), span, @@ -1749,7 +1749,7 @@ impl<'a> LoweringContext<'a> { self.context.resolver.definitions().create_def_with_parent( self.parent, def_node_id, - DefPathData::LifetimeParam(name.ident().as_interned_str()), + DefPathData::LifetimeNs(name.ident().as_interned_str()), DefIndexAddressSpace::High, Mark::root(), lifetime.span, diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 3b2bdfc8b89f8..fadd29d3d0c6c 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -164,7 +164,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { } ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) => DefPathData::ValueNs(i.ident.as_interned_str()), - ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.as_interned_str()), + ItemKind::MacroDef(..) => DefPathData::MacroNs(i.ident.as_interned_str()), ItemKind::Mac(..) => return self.visit_macro_invoc(i.id), ItemKind::GlobalAsm(..) => DefPathData::Misc, ItemKind::Use(..) => { @@ -236,7 +236,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_generic_param(&mut self, param: &'a GenericParam) { let name = param.ident.as_interned_str(); let def_path_data = match param.kind { - GenericParamKind::Lifetime { .. } => DefPathData::LifetimeParam(name), + GenericParamKind::Lifetime { .. } => DefPathData::LifetimeNs(name), GenericParamKind::Type { .. } => DefPathData::TypeNs(name), GenericParamKind::Const { .. } => DefPathData::ValueNs(name), }; diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index ddc76140167f4..fc9d6d86500ba 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -341,13 +341,13 @@ pub enum DefPathData { TypeNs(InternedString), /// Something in the value NS ValueNs(InternedString), - /// A macro rule - MacroDef(InternedString), + /// Something in the macro NS + MacroNs(InternedString), + /// Something in the lifetime NS + LifetimeNs(InternedString), /// A closure expression ClosureExpr, // Subportions of items - /// A lifetime (generic) parameter - LifetimeParam(InternedString), /// Implicit ctor for a unit or tuple-like struct or enum variant. Ctor, /// A constant expression (see {ast,hir}::AnonConst). @@ -614,8 +614,8 @@ impl DefPathData { match *self { TypeNs(name) | ValueNs(name) | - MacroDef(name) | - LifetimeParam(name) | + MacroNs(name) | + LifetimeNs(name) | GlobalMetaData(name) => Some(name), Impl | @@ -633,8 +633,8 @@ impl DefPathData { let s = match *self { TypeNs(name) | ValueNs(name) | - MacroDef(name) | - LifetimeParam(name) | + MacroNs(name) | + LifetimeNs(name) | GlobalMetaData(name) => { return name } diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 5836e510cadf4..e09dcd16bd3dc 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -858,12 +858,16 @@ impl TyCtxt<'_, '_, '_> { // (but also some things just print a `DefId` generally so maybe we need this?) fn guess_def_namespace(self, def_id: DefId) -> Namespace { match self.def_key(def_id).disambiguated_data.data { - DefPathData::ValueNs(..) | - DefPathData::AnonConst | - DefPathData::ClosureExpr | - DefPathData::Ctor => Namespace::ValueNS, + DefPathData::TypeNs(..) + | DefPathData::CrateRoot + | DefPathData::ImplTrait => Namespace::TypeNS, - DefPathData::MacroDef(..) => Namespace::MacroNS, + DefPathData::ValueNs(..) + | DefPathData::AnonConst + | DefPathData::ClosureExpr + | DefPathData::Ctor => Namespace::ValueNS, + + DefPathData::MacroNs(..) => Namespace::MacroNS, _ => Namespace::TypeNS, } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index ad28f47ba0444..048acf56ea7a7 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -459,7 +459,7 @@ crate fn proc_macro_def_path_table(crate_root: &CrateRoot, let def_index = definitions.create_def_with_parent( crate_root, ast::DUMMY_NODE_ID, - DefPathData::MacroDef(name.as_interned_str()), + DefPathData::MacroNs(name.as_interned_str()), DefIndexAddressSpace::High, Mark::root(), DUMMY_SP); From 639e452c5f0a76b11ebe3703a04b6ae13d96c887 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 4 May 2019 04:20:55 +0200 Subject: [PATCH 030/212] Remove unused feature(need_allocator). --- src/liballoc/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index eb673488170b6..2edd946ff11cf 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -87,7 +87,6 @@ #![feature(fundamental)] #![feature(lang_items)] #![feature(libc)] -#![feature(needs_allocator)] #![feature(nll)] #![feature(optin_builtin_traits)] #![feature(pattern)] From 99b98068e86605cb3c188ada3e72e9f42f91c824 Mon Sep 17 00:00:00 2001 From: Gianluca Recchia Date: Sat, 4 May 2019 07:44:30 +0200 Subject: [PATCH 031/212] Correct code points to match their textual description --- src/libstd/primitive_docs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index 94fece10e0fbc..24f728158c472 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -279,7 +279,7 @@ mod prim_never { } /// /// As always, remember that a human intuition for 'character' may not map to /// Unicode's definitions. For example, despite looking similar, the 'é' -/// character is one Unicode code point while 'é' is two Unicode code points: +/// character is one Unicode code point while 'é' is two Unicode code points: /// /// ``` /// let mut chars = "é".chars(); From 78b53db2868eaad41ac884989f7b470f352c65b2 Mon Sep 17 00:00:00 2001 From: Fabian Drinck Date: Sat, 27 Apr 2019 19:23:00 +0200 Subject: [PATCH 032/212] Remove obsolete comment --- src/librustc/hir/map/mod.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 9c895198ddde9..fbdb0e07ac1c7 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -174,15 +174,6 @@ pub struct Map<'hir> { /// The SVH of the local crate. pub crate_hash: Svh, - /// `NodeId`s are sequential integers from 0, so we can be - /// super-compact by storing them in a vector. Not everything with - /// a `NodeId` is in the map, but empirically the occupancy is about - /// 75-80%, so there's not too much overhead (certainly less than - /// a hashmap, since they (at the time of writing) have a maximum - /// of 75% occupancy). - /// - /// Also, indexing is pretty quick when you've got a vector and - /// plain old integers. map: FxHashMap>, definitions: &'hir Definitions, From fa7582d1dd37d0bdb08033bcb810274084bc26ca Mon Sep 17 00:00:00 2001 From: Fabian Drinck Date: Sat, 27 Apr 2019 19:24:45 +0200 Subject: [PATCH 033/212] Replace `NodeId` variant of `read` --- src/librustc/hir/map/mod.rs | 30 +++++++++++--------------- src/librustc_metadata/index_builder.rs | 4 ++-- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index fbdb0e07ac1c7..56c14faef2302 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -190,13 +190,7 @@ impl<'hir> Map<'hir> { /// otherwise have had access to those contents, and hence needs a /// read recorded). If the function just returns a DefId or /// NodeId, no actual content was returned, so no read is needed. - pub fn read(&self, id: NodeId) { - let hir_id = self.node_to_hir_id(id); - self.read_by_hir_id(hir_id); - } - - // FIXME(@ljedrz): replace the NodeId variant - pub fn read_by_hir_id(&self, hir_id: HirId) { + pub fn read(&self, hir_id: HirId) { if let Some(entry) = self.map.get(&hir_id) { self.dep_graph.read_index(entry.dep_node); } else { @@ -402,7 +396,7 @@ impl<'hir> Map<'hir> { } pub fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem { - self.read_by_hir_id(id.hir_id); + self.read(id.hir_id); // N.B., intentionally bypass `self.forest.krate()` so that we // do not trigger a read of the whole krate here @@ -410,7 +404,7 @@ impl<'hir> Map<'hir> { } pub fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem { - self.read_by_hir_id(id.hir_id); + self.read(id.hir_id); // N.B., intentionally bypass `self.forest.krate()` so that we // do not trigger a read of the whole krate here @@ -418,7 +412,7 @@ impl<'hir> Map<'hir> { } pub fn body(&self, id: BodyId) -> &'hir Body { - self.read_by_hir_id(id.hir_id); + self.read(id.hir_id); // N.B., intentionally bypass `self.forest.krate()` so that we // do not trigger a read of the whole krate here @@ -551,7 +545,7 @@ impl<'hir> Map<'hir> { pub fn get_module(&self, module: DefId) -> (&'hir Mod, Span, HirId) { let hir_id = self.as_local_hir_id(module).unwrap(); - self.read_by_hir_id(hir_id); + self.read(hir_id); match self.find_entry(hir_id).unwrap().node { Node::Item(&Item { span, @@ -566,13 +560,15 @@ impl<'hir> Map<'hir> { pub fn visit_item_likes_in_module(&self, module: DefId, visitor: &mut V) where V: ItemLikeVisitor<'hir> { - let node_id = self.as_local_node_id(module).unwrap(); + let hir_id = self.as_local_hir_id(module).unwrap(); // Read the module so we'll be re-executed if new items // appear immediately under in the module. If some new item appears // in some nested item in the module, we'll be re-executed due to reads // in the expect_* calls the loops below - self.read(node_id); + self.read(hir_id); + + let node_id = self.hir_to_node_id[&hir_id]; let module = &self.forest.krate.modules[&node_id]; @@ -650,7 +646,7 @@ impl<'hir> Map<'hir> { } }); if result.is_some() { - self.read_by_hir_id(hir_id); + self.read(hir_id); } result } @@ -884,7 +880,7 @@ impl<'hir> Map<'hir> { if let Entry { node: Node::Item(Item { node: ItemKind::ForeignMod(ref nm), .. }), .. } = entry { - self.read_by_hir_id(hir_id); // reveals some of the content of a node + self.read(hir_id); // reveals some of the content of a node return nm.abi; } } @@ -992,7 +988,7 @@ impl<'hir> Map<'hir> { // FIXME(@ljedrz): replace the NodeId variant pub fn attrs_by_hir_id(&self, id: HirId) -> &'hir [ast::Attribute] { - self.read_by_hir_id(id); // reveals attributes on the node + self.read(id); // reveals attributes on the node let attrs = match self.find_entry(id).map(|entry| entry.node) { Some(Node::Local(l)) => Some(&l.attrs[..]), Some(Node::Item(i)) => Some(&i.attrs[..]), @@ -1037,7 +1033,7 @@ impl<'hir> Map<'hir> { // FIXME(@ljedrz): replace the NodeId variant pub fn span_by_hir_id(&self, hir_id: HirId) -> Span { - self.read_by_hir_id(hir_id); // reveals span from node + self.read(hir_id); // reveals span from node match self.find_entry(hir_id).map(|entry| entry.node) { Some(Node::Item(item)) => item.span, Some(Node::ForeignItem(foreign_item)) => foreign_item.span, diff --git a/src/librustc_metadata/index_builder.rs b/src/librustc_metadata/index_builder.rs index 8343171b99f4b..b77feeee06f57 100644 --- a/src/librustc_metadata/index_builder.rs +++ b/src/librustc_metadata/index_builder.rs @@ -185,7 +185,7 @@ macro_rules! read_hir { ($t:ty) => { impl<'tcx> DepGraphRead for &'tcx $t { fn read(&self, tcx: TyCtxt<'_, '_, '_>) { - tcx.hir().read_by_hir_id(self.hir_id); + tcx.hir().read(self.hir_id); } } } @@ -219,6 +219,6 @@ pub struct FromId(pub hir::HirId, pub T); impl DepGraphRead for FromId { fn read(&self, tcx: TyCtxt<'_, '_, '_>) { - tcx.hir().read_by_hir_id(self.0); + tcx.hir().read(self.0); } } From 164988c1297c4c28a8f38561cbf1481c25a1c5b8 Mon Sep 17 00:00:00 2001 From: Fabian Drinck Date: Sat, 27 Apr 2019 22:39:17 +0200 Subject: [PATCH 034/212] Remove `def_path_from_id`, `node_id_to_string` --- src/librustc/hir/map/mod.rs | 51 ++++++++++++++--------------------- src/librustc_driver/pretty.rs | 5 +++- 2 files changed, 24 insertions(+), 32 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 56c14faef2302..a59170e96669c 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -208,17 +208,12 @@ impl<'hir> Map<'hir> { self.definitions.def_key(def_id.index) } - pub fn def_path_from_id(&self, id: NodeId) -> Option { - self.opt_local_def_id(id).map(|def_id| { + pub fn def_path_from_hir_id(&self, id: HirId) -> Option { + self.opt_local_def_id_from_hir_id(id).map(|def_id| { self.def_path(def_id) }) } - // FIXME(@ljedrz): replace the NodeId variant - pub fn def_path_from_hir_id(&self, id: HirId) -> DefPath { - self.def_path(self.local_def_id_from_hir_id(id)) - } - pub fn def_path(&self, def_id: DefId) -> DefPath { assert!(def_id.is_local()); self.definitions.def_path(def_id.index) @@ -1075,7 +1070,7 @@ impl<'hir> Map<'hir> { } pub fn node_to_string(&self, id: NodeId) -> String { - node_id_to_string(self, id, true) + hir_id_to_string(self, self.node_to_hir_id(id), true) } // FIXME(@ljedrz): replace the NodeId variant @@ -1084,7 +1079,7 @@ impl<'hir> Map<'hir> { } pub fn node_to_user_string(&self, id: NodeId) -> String { - node_id_to_string(self, id, false) + hir_id_to_string(self, self.node_to_hir_id(id), false) } // FIXME(@ljedrz): replace the NodeId variant @@ -1303,8 +1298,8 @@ impl<'a> print::State<'a> { } } -fn node_id_to_string(map: &Map<'_>, id: NodeId, include_id: bool) -> String { - let id_str = format!(" (id={})", id); +fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String { + let id_str = format!(" (hir_id={})", id); let id_str = if include_id { &id_str[..] } else { "" }; let path_str = || { @@ -1312,9 +1307,9 @@ fn node_id_to_string(map: &Map<'_>, id: NodeId, include_id: bool) -> String { // the user-friendly path, otherwise fall back to stringifying DefPath. crate::ty::tls::with_opt(|tcx| { if let Some(tcx) = tcx { - let def_id = map.local_def_id(id); + let def_id = map.local_def_id_from_hir_id(id); tcx.def_path_str(def_id) - } else if let Some(path) = map.def_path_from_id(id) { + } else if let Some(path) = map.def_path_from_hir_id(id) { path.data.into_iter().map(|elem| { elem.data.to_string() }).collect::>().join("::") @@ -1324,7 +1319,7 @@ fn node_id_to_string(map: &Map<'_>, id: NodeId, include_id: bool) -> String { }) }; - match map.find(id) { + match map.find_by_hir_id(id) { Some(Node::Item(item)) => { let item_str = match item.node { ItemKind::ExternCrate(..) => "extern crate", @@ -1385,40 +1380,40 @@ fn node_id_to_string(map: &Map<'_>, id: NodeId, include_id: bool) -> String { path_str(), id_str) } Some(Node::AnonConst(_)) => { - format!("const {}{}", map.node_to_pretty_string(id), id_str) + format!("const {}{}", map.hir_to_pretty_string(id), id_str) } Some(Node::Expr(_)) => { - format!("expr {}{}", map.node_to_pretty_string(id), id_str) + format!("expr {}{}", map.hir_to_pretty_string(id), id_str) } Some(Node::Stmt(_)) => { - format!("stmt {}{}", map.node_to_pretty_string(id), id_str) + format!("stmt {}{}", map.hir_to_pretty_string(id), id_str) } Some(Node::PathSegment(_)) => { - format!("path segment {}{}", map.node_to_pretty_string(id), id_str) + format!("path segment {}{}", map.hir_to_pretty_string(id), id_str) } Some(Node::Ty(_)) => { - format!("type {}{}", map.node_to_pretty_string(id), id_str) + format!("type {}{}", map.hir_to_pretty_string(id), id_str) } Some(Node::TraitRef(_)) => { - format!("trait_ref {}{}", map.node_to_pretty_string(id), id_str) + format!("trait_ref {}{}", map.hir_to_pretty_string(id), id_str) } Some(Node::Binding(_)) => { - format!("local {}{}", map.node_to_pretty_string(id), id_str) + format!("local {}{}", map.hir_to_pretty_string(id), id_str) } Some(Node::Pat(_)) => { - format!("pat {}{}", map.node_to_pretty_string(id), id_str) + format!("pat {}{}", map.hir_to_pretty_string(id), id_str) } Some(Node::Block(_)) => { - format!("block {}{}", map.node_to_pretty_string(id), id_str) + format!("block {}{}", map.hir_to_pretty_string(id), id_str) } Some(Node::Local(_)) => { - format!("local {}{}", map.node_to_pretty_string(id), id_str) + format!("local {}{}", map.hir_to_pretty_string(id), id_str) } Some(Node::Ctor(..)) => { format!("ctor {}{}", path_str(), id_str) } Some(Node::Lifetime(_)) => { - format!("lifetime {}{}", map.node_to_pretty_string(id), id_str) + format!("lifetime {}{}", map.hir_to_pretty_string(id), id_str) } Some(Node::GenericParam(ref param)) => { format!("generic_param {:?}{}", param, id_str) @@ -1434,12 +1429,6 @@ fn node_id_to_string(map: &Map<'_>, id: NodeId, include_id: bool) -> String { } } -// FIXME(@ljedrz): replace the NodeId variant -fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String { - let node_id = map.hir_to_node_id(id); - node_id_to_string(map, node_id, include_id) -} - pub fn def_kind(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Option { if let Some(node_id) = tcx.hir().as_local_node_id(def_id) { tcx.hir().def_kind(node_id) diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 5cefc35607db0..4fdcdafcab86c 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -255,7 +255,10 @@ trait HirPrinterSupport<'hir>: pprust_hir::PpAnn { /// Computes an user-readable representation of a path, if possible. fn node_path(&self, id: ast::NodeId) -> Option { - self.hir_map().and_then(|map| map.def_path_from_id(id)).map(|path| { + self.hir_map().and_then(|map| { + let hir_id = map.node_to_hir_id(id); + map.def_path_from_hir_id(hir_id) + }).map(|path| { path.data .into_iter() .map(|elem| elem.data.to_string()) From b7266c6008ea2497da20d92d0c49ccc16bd8a699 Mon Sep 17 00:00:00 2001 From: Daan de Graaf Date: Mon, 24 Dec 2018 17:52:50 +0100 Subject: [PATCH 035/212] Move pointee_info_at to TyLayoutMethods. The original implementation is still present at librustc_codegen_llvm/abi.rs, should be removed later to prevent code duplication. --- src/librustc/ty/layout.rs | 127 +++++++++++++++++++++++++++++++++ src/librustc_target/abi/mod.rs | 27 +++++++ 2 files changed, 154 insertions(+) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 21e4d8b07a19f..a67aa0e41b37b 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -12,6 +12,7 @@ use std::iter; use std::mem; use std::ops::Bound; +use hir; use crate::ich::StableHashingContext; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, @@ -1545,6 +1546,7 @@ impl<'gcx, 'tcx, T: HasTyCtxt<'gcx>> HasTyCtxt<'gcx> for LayoutCx<'tcx, T> { pub trait MaybeResult { fn from_ok(x: T) -> Self; fn map_same T>(self, f: F) -> Self; + fn ok(self) -> Option; } impl MaybeResult for T { @@ -1554,6 +1556,9 @@ impl MaybeResult for T { fn map_same T>(self, f: F) -> Self { f(self) } + fn ok(self) -> Option { + Some(self) + } } impl MaybeResult for Result { @@ -1563,6 +1568,9 @@ impl MaybeResult for Result { fn map_same T>(self, f: F) -> Self { self.map(f) } + fn ok(self) -> Option { + self.ok() + } } pub type TyLayout<'tcx> = ::rustc_target::abi::TyLayout<'tcx, Ty<'tcx>>; @@ -1824,6 +1832,125 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> } }) } + + fn pointee_info_at(this: TyLayout<'tcx>, cx: &C, offset: Size + ) -> Option { + let mut result = None; + match this.ty.sty { + ty::RawPtr(mt) if offset.bytes() == 0 => { + result = cx.layout_of(mt.ty).ok() + .map(|layout| PointeeInfo { + size: layout.size, + align: layout.align.abi, + safe: None, + }); + } + + ty::Ref(_, ty, mt) if offset.bytes() == 0 => { + let tcx = cx.tcx(); + let is_freeze = ty.is_freeze(tcx, ty::ParamEnv::reveal_all(), DUMMY_SP); + let kind = match mt { + hir::MutImmutable => if is_freeze { + PointerKind::Frozen + } else { + PointerKind::Shared + }, + hir::MutMutable => { + // Previously we would only emit noalias annotations for LLVM >= 6 or in + // panic=abort mode. That was deemed right, as prior versions had many bugs + // in conjunction with unwinding, but later versions didn’t seem to have + // said issues. See issue #31681. + // + // Alas, later on we encountered a case where noalias would generate wrong + // code altogether even with recent versions of LLVM in *safe* code with no + // unwinding involved. See #54462. + // + // For now, do not enable mutable_noalias by default at all, while the + // issue is being figured out. + let mutable_noalias = tcx.sess.opts.debugging_opts.mutable_noalias + .unwrap_or(false); + if mutable_noalias { + PointerKind::UniqueBorrowed + } else { + PointerKind::Shared + } + } + }; + + result = cx.layout_of(ty).ok() + .map(|layout| PointeeInfo { + size: layout.size, + align: layout.align.abi, + safe: Some(kind), + }); + } + + _ => { + let mut data_variant = match this.variants { + Variants::NicheFilling { dataful_variant, .. } => { + // Only the niche itthis is always initialized, + // so only check for a pointer at its offset. + // + // If the niche is a pointer, it's either valid + // (according to its type), or null (which the + // niche field's scalar validity range encodes). + // This allows using `dereferenceable_or_null` + // for e.g., `Option<&T>`, and this will continue + // to work as long as we don't start using more + // niches than just null (e.g., the first page + // of the address space, or unaligned pointers). + if this.fields.offset(0) == offset { + Some(this.for_variant(cx, dataful_variant)) + } else { + None + } + } + _ => Some(this) + }; + + if let Some(variant) = data_variant { + // We're not interested in any unions. + if let FieldPlacement::Union(_) = variant.fields { + data_variant = None; + } + } + + if let Some(variant) = data_variant { + let ptr_end = offset + Pointer.size(cx); + for i in 0..variant.fields.count() { + let field_start = variant.fields.offset(i); + if field_start <= offset { + let field = variant.field(cx, i); + result = field.ok() + .and_then(|field| { + if ptr_end <= field_start + field.size { + // We found the right field, look inside it. + Self::pointee_info_at(field, cx, offset - field_start) + } else { + None + } + }); + if result.is_some() { + break; + } + } + } + } + + // FIXME(eddyb) This should be for `ptr::Unique`, not `Box`. + if let Some(ref mut pointee) = result { + if let ty::Adt(def, _) = this.ty.sty { + if def.is_box() && offset.bytes() == 0 { + pointee.safe = Some(PointerKind::UniqueOwned); + } + } + } + } + } + + result + } + } struct Niche { diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 59eda97a2f9f5..74257cb3f6480 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -910,6 +910,28 @@ pub trait LayoutOf { fn layout_of(&self, ty: Self::Ty) -> Self::TyLayout; } +#[derive(Copy, Clone, PartialEq, Eq)] +pub enum PointerKind { + /// Most general case, we know no restrictions to tell LLVM. + Shared, + + /// `&T` where `T` contains no `UnsafeCell`, is `noalias` and `readonly`. + Frozen, + + /// `&mut T`, when we know `noalias` is safe for LLVM. + UniqueBorrowed, + + /// `Box`, unlike `UniqueBorrowed`, it also has `noalias` on returns. + UniqueOwned +} + +#[derive(Copy, Clone)] +pub struct PointeeInfo { + pub size: Size, + pub align: Align, + pub safe: Option, +} + pub trait TyLayoutMethods<'a, C: LayoutOf>: Sized { fn for_variant( this: TyLayout<'a, Self>, @@ -917,6 +939,11 @@ pub trait TyLayoutMethods<'a, C: LayoutOf>: Sized { variant_index: VariantIdx, ) -> TyLayout<'a, Self>; fn field(this: TyLayout<'a, Self>, cx: &C, i: usize) -> C::TyLayout; + fn pointee_info_at( + this: TyLayout<'a, Self>, + cx: &C, + offset: Size + ) -> Option; } impl<'a, Ty> TyLayout<'a, Ty> { From e395026aba4d0739ec06264dabb97a614ec8d0dc Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 28 Dec 2018 12:23:23 +0100 Subject: [PATCH 036/212] Fix typo in src/librustc/ty/layout.rs Co-Authored-By: wildarch --- src/librustc/ty/layout.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index a67aa0e41b37b..c05e0aaf3bafc 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1888,7 +1888,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> _ => { let mut data_variant = match this.variants { Variants::NicheFilling { dataful_variant, .. } => { - // Only the niche itthis is always initialized, + // Only the niche in this is always initialized, // so only check for a pointer at its offset. // // If the niche is a pointer, it's either valid From ed716d4c8960bb5e5127375ac023c698613b27bd Mon Sep 17 00:00:00 2001 From: Daan de Graaf Date: Fri, 28 Dec 2018 12:52:31 +0100 Subject: [PATCH 037/212] Return instead of collecting to mut result. --- src/librustc/ty/layout.rs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index c05e0aaf3bafc..472747a71707e 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1833,17 +1833,19 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> }) } - fn pointee_info_at(this: TyLayout<'tcx>, cx: &C, offset: Size + fn pointee_info_at( + this: TyLayout<'tcx>, + cx: &C, + offset: Size, ) -> Option { - let mut result = None; match this.ty.sty { ty::RawPtr(mt) if offset.bytes() == 0 => { - result = cx.layout_of(mt.ty).ok() + cx.layout_of(mt.ty).ok() .map(|layout| PointeeInfo { size: layout.size, align: layout.align.abi, safe: None, - }); + }) } ty::Ref(_, ty, mt) if offset.bytes() == 0 => { @@ -1877,12 +1879,12 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> } }; - result = cx.layout_of(ty).ok() + cx.layout_of(ty).ok() .map(|layout| PointeeInfo { size: layout.size, align: layout.align.abi, safe: Some(kind), - }); + }) } _ => { @@ -1915,6 +1917,8 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> } } + let mut result = None; + if let Some(variant) = data_variant { let ptr_end = offset + Pointer.size(cx); for i in 0..variant.fields.count() { @@ -1945,10 +1949,10 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> } } } + + result } } - - result } } From f1f9343c3df715392e1c0d28c8b2982d8dd6cf96 Mon Sep 17 00:00:00 2001 From: Daan de Graaf Date: Fri, 28 Dec 2018 13:15:39 +0100 Subject: [PATCH 038/212] Remove old pointee_info_at body. --- src/librustc_codegen_llvm/abi.rs | 8 +- src/librustc_codegen_llvm/context.rs | 2 +- src/librustc_codegen_llvm/type_of.rs | 135 +-------------------------- 3 files changed, 13 insertions(+), 132 deletions(-) diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index 2c4a1ded97f39..7a7008822372d 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -7,13 +7,19 @@ use crate::value::Value; use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::mir::operand::OperandValue; +<<<<<<< HEAD +======= +use type_::Type; +use type_of::{LayoutLlvmExt}; +use value::Value; +>>>>>>> Remove old pointee_info_at body. use rustc_target::abi::call::ArgType; use rustc_codegen_ssa::traits::*; use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TyLayout, Abi as LayoutAbi}; use rustc::ty::{self, Ty, Instance}; -use rustc::ty::layout; +use rustc::ty::layout::{self, PointerKind}; use libc::c_uint; diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index f6956bd5736eb..55b2868272591 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -16,7 +16,7 @@ use rustc_data_structures::small_c_str::SmallCStr; use rustc::mir::mono::Stats; use rustc::session::config::{self, DebugInfo}; use rustc::session::Session; -use rustc::ty::layout::{LayoutError, LayoutOf, Size, TyLayout, VariantIdx}; +use rustc::ty::layout::{LayoutError, LayoutOf, PointeeInfo, Size, TyLayout, VariantIdx}; use rustc::ty::{self, Ty, TyCtxt}; use rustc::util::nodemap::FxHashMap; use rustc_target::spec::{HasTargetSpec, Target}; diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index cbcc457fda9a2..e1c3c42add816 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -2,9 +2,11 @@ use crate::abi::{FnType, FnTypeExt}; use crate::common::*; use crate::type_::Type; use rustc::hir; +use abi::{FnType, FnTypeExt}; +use common::*; use rustc::ty::{self, Ty, TypeFoldable}; -use rustc::ty::layout::{self, Align, LayoutOf, Size, TyLayout}; -use rustc_target::abi::FloatTy; +use rustc::ty::layout::{self, Align, LayoutOf, PointeeInfo, Size, TyLayout}; +use rustc_target::abi::{FloatTy, TyLayoutMethods}; use rustc_mir::monomorphize::item::DefPathBasedNames; use rustc_codegen_ssa::traits::*; @@ -174,28 +176,6 @@ impl<'a, 'tcx> CodegenCx<'a, 'tcx> { } } -#[derive(Copy, Clone, PartialEq, Eq)] -pub enum PointerKind { - /// Most general case, we know no restrictions to tell LLVM. - Shared, - - /// `&T` where `T` contains no `UnsafeCell`, is `noalias` and `readonly`. - Frozen, - - /// `&mut T`, when we know `noalias` is safe for LLVM. - UniqueBorrowed, - - /// `Box`, unlike `UniqueBorrowed`, it also has `noalias` on returns. - UniqueOwned -} - -#[derive(Copy, Clone)] -pub struct PointeeInfo { - pub size: Size, - pub align: Align, - pub safe: Option, -} - pub trait LayoutLlvmExt<'tcx> { fn is_llvm_immediate(&self) -> bool; fn is_llvm_scalar_pair<'a>(&self) -> bool; @@ -406,112 +386,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { return pointee; } - let mut result = None; - match self.ty.sty { - ty::RawPtr(mt) if offset.bytes() == 0 => { - let (size, align) = cx.size_and_align_of(mt.ty); - result = Some(PointeeInfo { - size, - align, - safe: None - }); - } - - ty::Ref(_, ty, mt) if offset.bytes() == 0 => { - let (size, align) = cx.size_and_align_of(ty); - - let kind = match mt { - hir::MutImmutable => if cx.type_is_freeze(ty) { - PointerKind::Frozen - } else { - PointerKind::Shared - }, - hir::MutMutable => { - // Previously we would only emit noalias annotations for LLVM >= 6 or in - // panic=abort mode. That was deemed right, as prior versions had many bugs - // in conjunction with unwinding, but later versions didn’t seem to have - // said issues. See issue #31681. - // - // Alas, later on we encountered a case where noalias would generate wrong - // code altogether even with recent versions of LLVM in *safe* code with no - // unwinding involved. See #54462. - // - // For now, do not enable mutable_noalias by default at all, while the - // issue is being figured out. - let mutable_noalias = cx.tcx.sess.opts.debugging_opts.mutable_noalias - .unwrap_or(false); - if mutable_noalias { - PointerKind::UniqueBorrowed - } else { - PointerKind::Shared - } - } - }; - - result = Some(PointeeInfo { - size, - align, - safe: Some(kind) - }); - } - - _ => { - let mut data_variant = match self.variants { - // Within the discriminant field, only the niche itself is - // always initialized, so we only check for a pointer at its - // offset. - // - // If the niche is a pointer, it's either valid (according - // to its type), or null (which the niche field's scalar - // validity range encodes). This allows using - // `dereferenceable_or_null` for e.g., `Option<&T>`, and - // this will continue to work as long as we don't start - // using more niches than just null (e.g., the first page of - // the address space, or unaligned pointers). - layout::Variants::Multiple { - discr_kind: layout::DiscriminantKind::Niche { - dataful_variant, - .. - }, - discr_index, - .. - } if self.fields.offset(discr_index) == offset => - Some(self.for_variant(cx, dataful_variant)), - _ => Some(*self), - }; - - if let Some(variant) = data_variant { - // We're not interested in any unions. - if let layout::FieldPlacement::Union(_) = variant.fields { - data_variant = None; - } - } - - if let Some(variant) = data_variant { - let ptr_end = offset + layout::Pointer.size(cx); - for i in 0..variant.fields.count() { - let field_start = variant.fields.offset(i); - if field_start <= offset { - let field = variant.field(cx, i); - if ptr_end <= field_start + field.size { - // We found the right field, look inside it. - result = field.pointee_info_at(cx, offset - field_start); - break; - } - } - } - } - - // FIXME(eddyb) This should be for `ptr::Unique`, not `Box`. - if let Some(ref mut pointee) = result { - if let ty::Adt(def, _) = self.ty.sty { - if def.is_box() && offset.bytes() == 0 { - pointee.safe = Some(PointerKind::UniqueOwned); - } - } - } - } - } + let result = Ty::pointee_info_at(*self, cx, offset); cx.pointee_infos.borrow_mut().insert((self.ty, offset), result); result From d47ec57a4faf627a10058e31abecf5786bd799b3 Mon Sep 17 00:00:00 2001 From: Daan de Graaf Date: Fri, 28 Dec 2018 15:19:23 +0100 Subject: [PATCH 039/212] Add param_env parameter to pointee_info_at. An associated type ParamEnv has been added to TyLayoutMethods to facilitate this. --- src/librustc/ty/layout.rs | 7 +++++-- src/librustc_codegen_llvm/type_of.rs | 2 +- src/librustc_target/abi/mod.rs | 5 ++++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 472747a71707e..0473d3d02f8be 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1666,6 +1666,8 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> where C: LayoutOf> + HasTyCtxt<'tcx>, C::TyLayout: MaybeResult> { + type ParamEnv = ty::ParamEnv<'tcx>; + fn for_variant(this: TyLayout<'tcx>, cx: &C, variant_index: VariantIdx) -> TyLayout<'tcx> { let details = match this.variants { Variants::Single { index } if index == variant_index => this.details, @@ -1837,6 +1839,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> this: TyLayout<'tcx>, cx: &C, offset: Size, + param_env: Self::ParamEnv, ) -> Option { match this.ty.sty { ty::RawPtr(mt) if offset.bytes() == 0 => { @@ -1850,7 +1853,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> ty::Ref(_, ty, mt) if offset.bytes() == 0 => { let tcx = cx.tcx(); - let is_freeze = ty.is_freeze(tcx, ty::ParamEnv::reveal_all(), DUMMY_SP); + let is_freeze = ty.is_freeze(tcx, param_env, DUMMY_SP); let kind = match mt { hir::MutImmutable => if is_freeze { PointerKind::Frozen @@ -1929,7 +1932,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> .and_then(|field| { if ptr_end <= field_start + field.size { // We found the right field, look inside it. - Self::pointee_info_at(field, cx, offset - field_start) + Self::pointee_info_at(field, cx, offset - field_start, param_env) } else { None } diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index e1c3c42add816..fd15fdf21764d 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -386,7 +386,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { return pointee; } - let result = Ty::pointee_info_at(*self, cx, offset); + let result = Ty::pointee_info_at(*self, cx, offset, ty::ParamEnv::reveal_all()); cx.pointee_infos.borrow_mut().insert((self.ty, offset), result); result diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 74257cb3f6480..1cdef7b006421 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -933,6 +933,8 @@ pub struct PointeeInfo { } pub trait TyLayoutMethods<'a, C: LayoutOf>: Sized { + type ParamEnv; + fn for_variant( this: TyLayout<'a, Self>, cx: &C, @@ -942,7 +944,8 @@ pub trait TyLayoutMethods<'a, C: LayoutOf>: Sized { fn pointee_info_at( this: TyLayout<'a, Self>, cx: &C, - offset: Size + offset: Size, + param_env: Self::ParamEnv, ) -> Option; } From 7257fc34de8c2c66cf0fa1d628af54f50d368caf Mon Sep 17 00:00:00 2001 From: Daan de Graaf Date: Fri, 11 Jan 2019 11:26:47 +0100 Subject: [PATCH 040/212] Make line fit within 100 character limit. --- src/librustc/ty/layout.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 0473d3d02f8be..3ad316f8f6d1c 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1931,8 +1931,9 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> result = field.ok() .and_then(|field| { if ptr_end <= field_start + field.size { + let off = offset - field_start; // We found the right field, look inside it. - Self::pointee_info_at(field, cx, offset - field_start, param_env) + Self::pointee_info_at(field, cx, off, param_env) } else { None } From 82410e800f864684ec5009ea0cecd9614155ca06 Mon Sep 17 00:00:00 2001 From: Daan de Graaf Date: Mon, 11 Mar 2019 21:26:49 +0100 Subject: [PATCH 041/212] impl `pointee_info_at` in TyLayout. --- src/librustc_codegen_llvm/abi.rs | 4 ++-- src/librustc_target/abi/mod.rs | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index 7a7008822372d..a59f756570f48 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -18,7 +18,7 @@ use rustc_target::abi::call::ArgType; use rustc_codegen_ssa::traits::*; use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TyLayout, Abi as LayoutAbi}; -use rustc::ty::{self, Ty, Instance}; +use rustc::ty::{self, Ty, Instance, ParamEnv}; use rustc::ty::layout::{self, PointerKind}; use libc::c_uint; @@ -484,7 +484,7 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> { } } - if let Some(pointee) = layout.pointee_info_at(cx, offset) { + if let Some(pointee) = layout.pointee_info_at(cx, offset, ParamEnv::reveal_all()) { if let Some(kind) = pointee.safe { attrs.pointee_size = pointee.size; attrs.pointee_align = Some(pointee.align); diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 1cdef7b006421..6dd622b3f0f31 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -958,6 +958,10 @@ impl<'a, Ty> TyLayout<'a, Ty> { where Ty: TyLayoutMethods<'a, C>, C: LayoutOf { Ty::field(self, cx, i) } + pub fn pointee_info_at(self, cx: &C, offset: Size, param_env: Ty::ParamEnv) -> Option + where Ty: TyLayoutMethods<'a, C>, C: LayoutOf { + Ty::pointee_info_at(self, cx, offset, param_env) + } } impl<'a, Ty> TyLayout<'a, Ty> { From 199ff02dacae8a00902bbd2bca3ec65652444598 Mon Sep 17 00:00:00 2001 From: Saleem Jaffer Date: Wed, 24 Apr 2019 20:29:46 +0530 Subject: [PATCH 042/212] resolving conflicts --- src/librustc/ty/layout.rs | 45 ++++++++++++++-------------- src/librustc_codegen_llvm/abi.rs | 8 +---- src/librustc_codegen_llvm/context.rs | 1 - src/librustc_codegen_llvm/type_of.rs | 3 -- 4 files changed, 24 insertions(+), 33 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 3ad316f8f6d1c..b063159855412 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -12,7 +12,7 @@ use std::iter; use std::mem; use std::ops::Bound; -use hir; +use crate::hir; use crate::ich::StableHashingContext; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, @@ -1892,25 +1892,27 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> _ => { let mut data_variant = match this.variants { - Variants::NicheFilling { dataful_variant, .. } => { - // Only the niche in this is always initialized, - // so only check for a pointer at its offset. - // - // If the niche is a pointer, it's either valid - // (according to its type), or null (which the - // niche field's scalar validity range encodes). - // This allows using `dereferenceable_or_null` - // for e.g., `Option<&T>`, and this will continue - // to work as long as we don't start using more - // niches than just null (e.g., the first page - // of the address space, or unaligned pointers). - if this.fields.offset(0) == offset { - Some(this.for_variant(cx, dataful_variant)) - } else { - None - } - } - _ => Some(this) + // Within the discriminant field, only the niche itself is + // always initialized, so we only check for a pointer at its + // offset. + // + // If the niche is a pointer, it's either valid (according + // to its type), or null (which the niche field's scalar + // validity range encodes). This allows using + // `dereferenceable_or_null` for e.g., `Option<&T>`, and + // this will continue to work as long as we don't start + // using more niches than just null (e.g., the first page of + // the address space, or unaligned pointers). + Variants::Multiple { + discr_kind: DiscriminantKind::Niche { + dataful_variant, + .. + }, + discr_index, + .. + } if this.fields.offset(discr_index) == offset => + Some(this.for_variant(cx, dataful_variant)), + _ => Some(this), }; if let Some(variant) = data_variant { @@ -1931,9 +1933,8 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> result = field.ok() .and_then(|field| { if ptr_end <= field_start + field.size { - let off = offset - field_start; // We found the right field, look inside it. - Self::pointee_info_at(field, cx, off, param_env) + field.pointee_info_at(cx, offset - field_start, param_env) } else { None } diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index a59f756570f48..1be0736791451 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -2,17 +2,11 @@ use crate::llvm::{self, AttributePlace}; use crate::builder::Builder; use crate::context::CodegenCx; use crate::type_::Type; -use crate::type_of::{LayoutLlvmExt, PointerKind}; use crate::value::Value; +use crate::type_of::{LayoutLlvmExt}; use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::mir::operand::OperandValue; -<<<<<<< HEAD -======= -use type_::Type; -use type_of::{LayoutLlvmExt}; -use value::Value; ->>>>>>> Remove old pointee_info_at body. use rustc_target::abi::call::ArgType; use rustc_codegen_ssa::traits::*; diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 55b2868272591..7cf78a41feb72 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -8,7 +8,6 @@ use rustc::hir; use crate::monomorphize::partitioning::CodegenUnit; use crate::type_::Type; -use crate::type_of::PointeeInfo; use rustc_codegen_ssa::traits::*; use rustc_data_structures::base_n; diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index fd15fdf21764d..3f717754e327a 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -1,9 +1,6 @@ use crate::abi::{FnType, FnTypeExt}; use crate::common::*; use crate::type_::Type; -use rustc::hir; -use abi::{FnType, FnTypeExt}; -use common::*; use rustc::ty::{self, Ty, TypeFoldable}; use rustc::ty::layout::{self, Align, LayoutOf, PointeeInfo, Size, TyLayout}; use rustc_target::abi::{FloatTy, TyLayoutMethods}; From 35bd58b4e85791e9c94f1eea7387f59c5feb6b60 Mon Sep 17 00:00:00 2001 From: Saleem Jaffer Date: Wed, 24 Apr 2019 21:25:56 +0530 Subject: [PATCH 043/212] tidy fixes --- src/librustc_target/abi/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 6dd622b3f0f31..d69b4b6d2bdca 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -958,7 +958,9 @@ impl<'a, Ty> TyLayout<'a, Ty> { where Ty: TyLayoutMethods<'a, C>, C: LayoutOf { Ty::field(self, cx, i) } - pub fn pointee_info_at(self, cx: &C, offset: Size, param_env: Ty::ParamEnv) -> Option + pub fn pointee_info_at( + self, cx: &C, offset: Size, param_env: Ty::ParamEnv + ) -> Option where Ty: TyLayoutMethods<'a, C>, C: LayoutOf { Ty::pointee_info_at(self, cx, offset, param_env) } From 8e3d9f1039df40a959d8d63e71dec5ecfecd56c7 Mon Sep 17 00:00:00 2001 From: Saleem Jaffer Date: Thu, 25 Apr 2019 18:22:34 +0530 Subject: [PATCH 044/212] add to_result to ty::MaybeResult --- src/librustc/ty/layout.rs | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index b063159855412..7f879cd77fdff 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -5,6 +5,7 @@ use syntax::ast::{self, Ident, IntTy, UintTy}; use syntax::attr; use syntax_pos::DUMMY_SP; +// use std::convert::From; use std::cmp; use std::fmt; use std::i128; @@ -1544,32 +1545,38 @@ impl<'gcx, 'tcx, T: HasTyCtxt<'gcx>> HasTyCtxt<'gcx> for LayoutCx<'tcx, T> { } pub trait MaybeResult { + type Item; + fn from_ok(x: T) -> Self; fn map_same T>(self, f: F) -> Self; - fn ok(self) -> Option; + fn to_result(self) -> Result; } impl MaybeResult for T { + type Item = !; + fn from_ok(x: T) -> Self { x } fn map_same T>(self, f: F) -> Self { f(self) } - fn ok(self) -> Option { - Some(self) + fn to_result(self) -> Result { + Ok(self) } } impl MaybeResult for Result { + type Item = E; + fn from_ok(x: T) -> Self { Ok(x) } fn map_same T>(self, f: F) -> Self { self.map(f) } - fn ok(self) -> Option { - self.ok() + fn to_result(self) -> Result { + self } } @@ -1843,7 +1850,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> ) -> Option { match this.ty.sty { ty::RawPtr(mt) if offset.bytes() == 0 => { - cx.layout_of(mt.ty).ok() + cx.layout_of(mt.ty).to_result().ok() .map(|layout| PointeeInfo { size: layout.size, align: layout.align.abi, @@ -1882,7 +1889,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> } }; - cx.layout_of(ty).ok() + cx.layout_of(ty).to_result().ok() .map(|layout| PointeeInfo { size: layout.size, align: layout.align.abi, @@ -1930,7 +1937,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> let field_start = variant.fields.offset(i); if field_start <= offset { let field = variant.field(cx, i); - result = field.ok() + result = field.to_result().ok() .and_then(|field| { if ptr_end <= field_start + field.size { // We found the right field, look inside it. From 9bd6a7a6809cb1fc18401bf6c89e9dbe28aeb008 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 4 May 2019 11:47:37 +0200 Subject: [PATCH 045/212] submodules: update clippy from 2ed0b3bf to fc96aa03 Changes: ```` Rustup to rustc 1.36.0-nightly (13fde05b1 2019-05-03) Fix link in into_iter_on_array documentation remove function body from "too many args" span check closure arguments before use it format code fix suggestion for search_is_some fix suggestion for search_is_some naively change |&x| to |x| in stderr file cargo fmt useless_let_if_seq handle interior mutability ```` --- src/tools/clippy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/clippy b/src/tools/clippy index 2ed0b3bfa05c7..fc96aa0368841 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit 2ed0b3bfa05c796c6645ed1814cd372e73f45c66 +Subproject commit fc96aa036884183ddc68d2659f4633e6f138b4e0 From 852dd491efde37dfecacd803d843592a15f9eab6 Mon Sep 17 00:00:00 2001 From: Saleem Jaffer Date: Tue, 30 Apr 2019 12:19:53 +0530 Subject: [PATCH 046/212] removing map_same from MaybeResult --- src/librustc/ty/layout.rs | 44 +++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 7f879cd77fdff..319db52fe208e 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -5,7 +5,6 @@ use syntax::ast::{self, Ident, IntTy, UintTy}; use syntax::attr; use syntax_pos::DUMMY_SP; -// use std::convert::From; use std::cmp; use std::fmt; use std::i128; @@ -1545,37 +1544,31 @@ impl<'gcx, 'tcx, T: HasTyCtxt<'gcx>> HasTyCtxt<'gcx> for LayoutCx<'tcx, T> { } pub trait MaybeResult { - type Item; + type Error; - fn from_ok(x: T) -> Self; - fn map_same T>(self, f: F) -> Self; - fn to_result(self) -> Result; + fn from(x: Result) -> Self; + fn to_result(self) -> Result; } impl MaybeResult for T { - type Item = !; + type Error = !; - fn from_ok(x: T) -> Self { + fn from(x: Result) -> Self { + let Ok(x) = x; x } - fn map_same T>(self, f: F) -> Self { - f(self) - } - fn to_result(self) -> Result { + fn to_result(self) -> Result { Ok(self) } } impl MaybeResult for Result { - type Item = E; + type Error = E; - fn from_ok(x: T) -> Self { - Ok(x) - } - fn map_same T>(self, f: F) -> Self { - self.map(f) + fn from(x: Result) -> Self { + x } - fn to_result(self) -> Result { + fn to_result(self) -> Result { self } } @@ -1681,10 +1674,9 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> Variants::Single { index } => { // Deny calling for_variant more than once for non-Single enums. - cx.layout_of(this.ty).map_same(|layout| { + if let Ok(layout) = cx.layout_of(this.ty).to_result() { assert_eq!(layout.variants, Variants::Single { index }); - layout - }); + } let fields = match this.ty.sty { ty::Adt(def, _) => def.variants[variant_index].fields.len(), @@ -1754,10 +1746,12 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> } else { tcx.mk_mut_ref(tcx.lifetimes.re_static, nil) }; - return cx.layout_of(ptr_ty).map_same(|mut ptr_layout| { - ptr_layout.ty = this.ty; - ptr_layout - }); + return MaybeResult::from( + cx.layout_of(ptr_ty).to_result().map(|mut ptr_layout| { + ptr_layout.ty = this.ty; + ptr_layout + }) + ); } match tcx.struct_tail(pointee).sty { From 8802dc037eb2fa84692588bc026bd550554e282b Mon Sep 17 00:00:00 2001 From: Saleem Jaffer Date: Fri, 3 May 2019 13:05:10 +0530 Subject: [PATCH 047/212] adding is_freeze to TyLayoutMethods --- src/librustc/ty/layout.rs | 8 ++++++++ src/librustc_target/abi/mod.rs | 9 +++++++++ 2 files changed, 17 insertions(+) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 319db52fe208e..e4f80838d84f8 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1961,6 +1961,14 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> } } + fn is_freeze( + this: TyLayout<'tcx>, + cx: &C, + param_env: Self::ParamEnv, + )-> bool { + this.ty.is_freeze(cx.tcx(), param_env, DUMMY_SP) + } + } struct Niche { diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index d69b4b6d2bdca..087d98d70318e 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -947,6 +947,11 @@ pub trait TyLayoutMethods<'a, C: LayoutOf>: Sized { offset: Size, param_env: Self::ParamEnv, ) -> Option; + fn is_freeze( + this: TyLayout<'a, Self>, + cx: &C, + param_env: Self::ParamEnv, + )-> bool; } impl<'a, Ty> TyLayout<'a, Ty> { @@ -964,6 +969,10 @@ impl<'a, Ty> TyLayout<'a, Ty> { where Ty: TyLayoutMethods<'a, C>, C: LayoutOf { Ty::pointee_info_at(self, cx, offset, param_env) } + pub fn is_freeze(self, cx: &C, param_env: Ty::ParamEnv) -> bool + where Ty: TyLayoutMethods<'a, C>, C: LayoutOf { + Ty::is_freeze(self, cx, param_env) + } } impl<'a, Ty> TyLayout<'a, Ty> { From 18679cdc54c91140499f4113f2d1122f200ac7fb Mon Sep 17 00:00:00 2001 From: Saleem Jaffer Date: Sat, 4 May 2019 15:02:22 +0530 Subject: [PATCH 048/212] adding HasParamEnv trait --- src/librustc/ty/layout.rs | 22 ++++++++++++---------- src/librustc_codegen_llvm/builder.rs | 6 ++++++ src/librustc_codegen_llvm/context.rs | 8 +++++++- src/librustc_codegen_ssa/traits/builder.rs | 4 +++- src/librustc_codegen_ssa/traits/mod.rs | 7 ++++++- src/librustc_mir/interpret/eval_context.rs | 8 ++++++++ src/librustc_passes/layout_test.rs | 7 +++++++ src/librustc_target/abi/mod.rs | 9 --------- 8 files changed, 49 insertions(+), 22 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index e4f80838d84f8..d4b93ed478502 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1662,9 +1662,20 @@ impl ty::query::TyCtxtAt<'a, 'tcx, '_> { } } +pub trait HasParamEnv<'tcx> { + fn param_env(&self) -> ty::ParamEnv<'tcx>; +} + +impl<'tcx, C> HasParamEnv<'tcx> for LayoutCx<'tcx, C> { + fn param_env(&self) -> ty::ParamEnv<'tcx> { + self.param_env + } +} + impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> where C: LayoutOf> + HasTyCtxt<'tcx>, - C::TyLayout: MaybeResult> + C::TyLayout: MaybeResult>, + C: HasParamEnv<'tcx> { type ParamEnv = ty::ParamEnv<'tcx>; @@ -1960,15 +1971,6 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> } } } - - fn is_freeze( - this: TyLayout<'tcx>, - cx: &C, - param_env: Self::ParamEnv, - )-> bool { - this.ty.is_freeze(cx.tcx(), param_env, DUMMY_SP) - } - } struct Niche { diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index 123fda1e215ff..bc2bb97a19e54 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -66,6 +66,12 @@ impl ty::layout::HasTyCtxt<'tcx> for Builder<'_, '_, 'tcx> { } } +impl ty::layout::HasParamEnv<'tcx> for Builder<'_, '_, 'tcx> { + fn param_env(&self) -> ty::ParamEnv<'tcx> { + self.cx.param_env() + } +} + impl ty::layout::LayoutOf for Builder<'_, '_, 'tcx> { type Ty = Ty<'tcx>; type TyLayout = TyLayout<'tcx>; diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 7cf78a41feb72..a225a11e94db0 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -15,7 +15,7 @@ use rustc_data_structures::small_c_str::SmallCStr; use rustc::mir::mono::Stats; use rustc::session::config::{self, DebugInfo}; use rustc::session::Session; -use rustc::ty::layout::{LayoutError, LayoutOf, PointeeInfo, Size, TyLayout, VariantIdx}; +use rustc::ty::layout::{LayoutError, LayoutOf, PointeeInfo, Size, TyLayout, VariantIdx, HasParamEnv}; use rustc::ty::{self, Ty, TyCtxt}; use rustc::util::nodemap::FxHashMap; use rustc_target::spec::{HasTargetSpec, Target}; @@ -861,3 +861,9 @@ impl LayoutOf for CodegenCx<'ll, 'tcx> { }) } } + +impl<'tcx, 'll> HasParamEnv<'tcx> for CodegenCx<'ll, 'tcx> { + fn param_env(&self) -> ty::ParamEnv<'tcx> { + panic!("asd") + } +} diff --git a/src/librustc_codegen_ssa/traits/builder.rs b/src/librustc_codegen_ssa/traits/builder.rs index 48142fc9fa9f4..a3f99cd869e28 100644 --- a/src/librustc_codegen_ssa/traits/builder.rs +++ b/src/librustc_codegen_ssa/traits/builder.rs @@ -10,7 +10,7 @@ use crate::mir::operand::OperandRef; use crate::mir::place::PlaceRef; use crate::MemFlags; use rustc::ty::Ty; -use rustc::ty::layout::{Align, Size}; +use rustc::ty::layout::{Align, Size, HasParamEnv}; use std::ops::Range; use std::iter::TrustedLen; @@ -29,6 +29,8 @@ pub trait BuilderMethods<'a, 'tcx: 'a>: + IntrinsicCallMethods<'tcx> + AsmBuilderMethods<'tcx> + StaticBuilderMethods<'tcx> + + HasParamEnv<'tcx> + { fn new_block<'b>(cx: &'a Self::CodegenCx, llfn: Self::Value, name: &'b str) -> Self; fn with_cx(cx: &'a Self::CodegenCx) -> Self; diff --git a/src/librustc_codegen_ssa/traits/mod.rs b/src/librustc_codegen_ssa/traits/mod.rs index 8fe8b7ecd4709..8c336b11a5d0a 100644 --- a/src/librustc_codegen_ssa/traits/mod.rs +++ b/src/librustc_codegen_ssa/traits/mod.rs @@ -41,6 +41,8 @@ pub use self::type_::{ ArgTypeMethods, BaseTypeMethods, DerivedTypeMethods, LayoutTypeMethods, TypeMethods, }; pub use self::write::{ModuleBufferMethods, ThinBufferMethods, WriteBackendMethods}; +use rustc::ty::layout::{HasParamEnv}; + use std::fmt; @@ -58,6 +60,7 @@ pub trait CodegenMethods<'tcx>: + DeclareMethods<'tcx> + AsmMethods<'tcx> + PreDefineMethods<'tcx> + + HasParamEnv<'tcx> { } @@ -72,6 +75,7 @@ impl<'tcx, T> CodegenMethods<'tcx> for T where + DeclareMethods<'tcx> + AsmMethods<'tcx> + PreDefineMethods<'tcx> + + HasParamEnv<'tcx> { } @@ -85,5 +89,6 @@ pub trait HasCodegen<'tcx>: Type = Self::Type, Funclet = Self::Funclet, DIScope = Self::DIScope, - >; + > + + HasParamEnv<'tcx>; } diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index ad4bc6a91f5a1..db827afdb94f4 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -175,6 +175,14 @@ impl<'a, 'mir, 'tcx, M> layout::HasTyCtxt<'tcx> for InterpretCx<'a, 'mir, 'tcx, } } +impl<'a, 'mir, 'tcx, M> layout::HasParamEnv<'tcx> for InterpretCx<'a, 'mir, 'tcx, M> + where M: Machine<'a, 'mir, 'tcx> +{ + fn param_env(&self) -> ty::ParamEnv<'tcx> { + self.param_env + } +} + impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> LayoutOf for InterpretCx<'a, 'mir, 'tcx, M> { diff --git a/src/librustc_passes/layout_test.rs b/src/librustc_passes/layout_test.rs index 6940f8f442ee9..7041a5593abbf 100644 --- a/src/librustc_passes/layout_test.rs +++ b/src/librustc_passes/layout_test.rs @@ -7,6 +7,7 @@ use rustc::ty::layout::HasTyCtxt; use rustc::ty::layout::LayoutOf; use rustc::ty::layout::TargetDataLayout; use rustc::ty::layout::TyLayout; +use rustc::ty::layout::HasParamEnv; use rustc::ty::ParamEnv; use rustc::ty::Ty; use rustc::ty::TyCtxt; @@ -122,6 +123,12 @@ impl<'me, 'tcx> HasTyCtxt<'tcx> for UnwrapLayoutCx<'me, 'tcx> { } } +impl<'me, 'tcx> HasParamEnv<'tcx> for UnwrapLayoutCx<'me, 'tcx> { + fn param_env(&self) -> ParamEnv<'tcx> { + self.param_env + } +} + impl<'me, 'tcx> HasDataLayout for UnwrapLayoutCx<'me, 'tcx> { fn data_layout(&self) -> &TargetDataLayout { self.tcx.data_layout() diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 087d98d70318e..d69b4b6d2bdca 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -947,11 +947,6 @@ pub trait TyLayoutMethods<'a, C: LayoutOf>: Sized { offset: Size, param_env: Self::ParamEnv, ) -> Option; - fn is_freeze( - this: TyLayout<'a, Self>, - cx: &C, - param_env: Self::ParamEnv, - )-> bool; } impl<'a, Ty> TyLayout<'a, Ty> { @@ -969,10 +964,6 @@ impl<'a, Ty> TyLayout<'a, Ty> { where Ty: TyLayoutMethods<'a, C>, C: LayoutOf { Ty::pointee_info_at(self, cx, offset, param_env) } - pub fn is_freeze(self, cx: &C, param_env: Ty::ParamEnv) -> bool - where Ty: TyLayoutMethods<'a, C>, C: LayoutOf { - Ty::is_freeze(self, cx, param_env) - } } impl<'a, Ty> TyLayout<'a, Ty> { From 94a48924da05d2c3c147ce7739d497fdcf33ca01 Mon Sep 17 00:00:00 2001 From: Saleem Jaffer Date: Sat, 4 May 2019 16:10:47 +0530 Subject: [PATCH 049/212] resolving conflicts --- src/librustc/ty/layout.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index d4b93ed478502..dc9eaf5592e39 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1720,10 +1720,9 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> let tcx = cx.tcx(); let discr_layout = |discr: &Scalar| -> C::TyLayout { let layout = LayoutDetails::scalar(cx, discr.clone()); - MaybeResult::from_ok(TyLayout { - details: tcx.intern_layout(layout), - ty: discr.value.to_ty(tcx) - }) + MaybeResult::from(Ok( + TyLayout {details: tcx.intern_layout(layout),ty: discr.value.to_ty(tcx)} + )) }; cx.layout_of(match this.ty.sty { From 64967b693cb2692f0c3f770a66bbde7eaa38153e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 4 May 2019 13:14:56 +0200 Subject: [PATCH 050/212] fix Miri visiting generators --- src/librustc_mir/interpret/validity.rs | 10 ++++- src/librustc_mir/interpret/visitor.rs | 60 +++++++++----------------- 2 files changed, 28 insertions(+), 42 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index bd6f005e8736c..807da7340f839 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -66,6 +66,7 @@ macro_rules! try_validation { pub enum PathElem { Field(Symbol), Variant(Symbol), + GeneratoreState(VariantIdx), ClosureVar(Symbol), ArrayElem(usize), TupleElem(usize), @@ -100,6 +101,7 @@ fn path_format(path: &Vec) -> String { match elem { Field(name) => write!(out, ".{}", name), Variant(name) => write!(out, ".", name), + GeneratoreState(idx) => write!(out, ".", idx.index()), ClosureVar(name) => write!(out, ".", name), TupleElem(idx) => write!(out, ".{}", idx), ArrayElem(idx) => write!(out, "[{}]", idx), @@ -262,8 +264,12 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> variant_id: VariantIdx, new_op: OpTy<'tcx, M::PointerTag> ) -> EvalResult<'tcx> { - let name = old_op.layout.ty.ty_adt_def().unwrap().variants[variant_id].ident.name; - self.visit_elem(new_op, PathElem::Variant(name)) + let name = match old_op.layout.ty.ty_adt_def() { + Some(def) => PathElem::Variant(def.variants[variant_id].ident.name), + // Generators also have variants but no def + None => PathElem::GeneratoreState(variant_id), + }; + self.visit_elem(new_op, name) } #[inline] diff --git a/src/librustc_mir/interpret/visitor.rs b/src/librustc_mir/interpret/visitor.rs index 05343ac66d966..cf67b0a97bcf8 100644 --- a/src/librustc_mir/interpret/visitor.rs +++ b/src/librustc_mir/interpret/visitor.rs @@ -147,7 +147,7 @@ macro_rules! make_value_visitor { { Ok(()) } - /// Visits this vale as an aggregate, you are even getting an iterator yielding + /// Visits this value as an aggregate, you are getting an iterator yielding /// all the fields (still in an `EvalResult`, you have to do error handling yourself). /// Recurses into the fields. #[inline(always)] @@ -160,7 +160,8 @@ macro_rules! make_value_visitor { } /// Called each time we recurse down to a field of a "product-like" aggregate - /// (structs, tuples, arrays and the like, but not enums), passing in old and new value. + /// (structs, tuples, arrays and the like, but not enums), passing in old (outer) + /// and new (inner) value. /// This gives the visitor the chance to track the stack of nested fields that /// we are descending through. #[inline(always)] @@ -173,18 +174,6 @@ macro_rules! make_value_visitor { self.visit_value(new_val) } - /// Called for recursing into the field of a generator. These are not known to be - /// initialized, so we treat them like unions. - #[inline(always)] - fn visit_generator_field( - &mut self, - _old_val: Self::V, - _field: usize, - new_val: Self::V, - ) -> EvalResult<'tcx> { - self.visit_union(new_val) - } - /// Called when recursing into an enum variant. #[inline(always)] fn visit_variant( @@ -238,7 +227,7 @@ macro_rules! make_value_visitor { fn walk_value(&mut self, v: Self::V) -> EvalResult<'tcx> { trace!("walk_value: type: {}", v.layout().ty); - // If this is a multi-variant layout, we have find the right one and proceed with + // If this is a multi-variant layout, we have to find the right one and proceed with // that. match v.layout().variants { layout::Variants::Multiple { .. } => { @@ -263,6 +252,13 @@ macro_rules! make_value_visitor { // recurse with the inner type return self.visit_field(v, 0, Value::from_mem_place(inner)); }, + ty::Generator(..) => { + // FIXME: Generator layout is lying: it claims a whole bunch of fields exist + // when really many of them can be uninitialized. + // Just treat them as a union for now, until hopefully the layout + // computation is fixed. + return self.visit_union(v); + } _ => {}, }; @@ -304,34 +300,18 @@ macro_rules! make_value_visitor { // Empty unions are not accepted by rustc. That's great, it means we can // use that as an unambiguous signal for detecting primitives. Make sure // we did not miss any primitive. - debug_assert!(fields > 0); + assert!(fields > 0); self.visit_union(v) }, layout::FieldPlacement::Arbitrary { ref offsets, .. } => { - // Special handling needed for generators: All but the first field - // (which is the state) are actually implicitly `MaybeUninit`, i.e., - // they may or may not be initialized, so we cannot visit them. - match v.layout().ty.sty { - ty::Generator(..) => { - let field = v.project_field(self.ecx(), 0)?; - self.visit_aggregate(v, std::iter::once(Ok(field)))?; - for i in 1..offsets.len() { - let field = v.project_field(self.ecx(), i as u64)?; - self.visit_generator_field(v, i, field)?; - } - Ok(()) - } - _ => { - // FIXME: We collect in a vec because otherwise there are lifetime - // errors: Projecting to a field needs access to `ecx`. - let fields: Vec> = - (0..offsets.len()).map(|i| { - v.project_field(self.ecx(), i as u64) - }) - .collect(); - self.visit_aggregate(v, fields.into_iter()) - } - } + // FIXME: We collect in a vec because otherwise there are lifetime + // errors: Projecting to a field needs access to `ecx`. + let fields: Vec> = + (0..offsets.len()).map(|i| { + v.project_field(self.ecx(), i as u64) + }) + .collect(); + self.visit_aggregate(v, fields.into_iter()) }, layout::FieldPlacement::Array { .. } => { // Let's get an mplace first. From c5c161e39497887abf78ef7da0d53c3dcf22a059 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 4 May 2019 13:49:04 +0200 Subject: [PATCH 051/212] match on type directlty --- src/librustc_mir/interpret/validity.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 807da7340f839..772cbcf9447ef 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -264,10 +264,11 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> variant_id: VariantIdx, new_op: OpTy<'tcx, M::PointerTag> ) -> EvalResult<'tcx> { - let name = match old_op.layout.ty.ty_adt_def() { - Some(def) => PathElem::Variant(def.variants[variant_id].ident.name), - // Generators also have variants but no def - None => PathElem::GeneratoreState(variant_id), + let name = match old_op.layout.ty.sty { + ty::Adt(adt, _) => PathElem::Variant(adt.variants[variant_id].ident.name), + // Generators also have variants + ty::Generator(..) => PathElem::GeneratoreState(variant_id), + _ => bug!("Unexpected type with variant: {:?}", old_op.layout.ty), }; self.visit_elem(new_op, name) } From 80d5478649b5c26846afb1a923c24f8103b887cf Mon Sep 17 00:00:00 2001 From: Saleem Jaffer Date: Sat, 4 May 2019 18:06:40 +0530 Subject: [PATCH 052/212] removing param_env from pointee_info_at --- src/librustc/ty/layout.rs | 7 ++----- src/librustc_codegen_llvm/abi.rs | 4 ++-- src/librustc_codegen_llvm/context.rs | 6 ++++-- src/librustc_codegen_llvm/type_of.rs | 2 +- src/librustc_target/abi/mod.rs | 9 ++------- 5 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index dc9eaf5592e39..9a5db20229607 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1677,8 +1677,6 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> C::TyLayout: MaybeResult>, C: HasParamEnv<'tcx> { - type ParamEnv = ty::ParamEnv<'tcx>; - fn for_variant(this: TyLayout<'tcx>, cx: &C, variant_index: VariantIdx) -> TyLayout<'tcx> { let details = match this.variants { Variants::Single { index } if index == variant_index => this.details, @@ -1850,7 +1848,6 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> this: TyLayout<'tcx>, cx: &C, offset: Size, - param_env: Self::ParamEnv, ) -> Option { match this.ty.sty { ty::RawPtr(mt) if offset.bytes() == 0 => { @@ -1864,7 +1861,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> ty::Ref(_, ty, mt) if offset.bytes() == 0 => { let tcx = cx.tcx(); - let is_freeze = ty.is_freeze(tcx, param_env, DUMMY_SP); + let is_freeze = ty.is_freeze(tcx, cx.param_env(), DUMMY_SP); let kind = match mt { hir::MutImmutable => if is_freeze { PointerKind::Frozen @@ -1945,7 +1942,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> .and_then(|field| { if ptr_end <= field_start + field.size { // We found the right field, look inside it. - field.pointee_info_at(cx, offset - field_start, param_env) + field.pointee_info_at(cx, offset - field_start) } else { None } diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index 1be0736791451..70d184240fccd 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -12,7 +12,7 @@ use rustc_target::abi::call::ArgType; use rustc_codegen_ssa::traits::*; use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TyLayout, Abi as LayoutAbi}; -use rustc::ty::{self, Ty, Instance, ParamEnv}; +use rustc::ty::{self, Ty, Instance}; use rustc::ty::layout::{self, PointerKind}; use libc::c_uint; @@ -478,7 +478,7 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> { } } - if let Some(pointee) = layout.pointee_info_at(cx, offset, ParamEnv::reveal_all()) { + if let Some(pointee) = layout.pointee_info_at(cx, offset) { if let Some(kind) = pointee.safe { attrs.pointee_size = pointee.size; attrs.pointee_align = Some(pointee.align); diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index a225a11e94db0..7bf8f705ea8ad 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -15,7 +15,9 @@ use rustc_data_structures::small_c_str::SmallCStr; use rustc::mir::mono::Stats; use rustc::session::config::{self, DebugInfo}; use rustc::session::Session; -use rustc::ty::layout::{LayoutError, LayoutOf, PointeeInfo, Size, TyLayout, VariantIdx, HasParamEnv}; +use rustc::ty::layout::{ + LayoutError, LayoutOf, PointeeInfo, Size, TyLayout, VariantIdx, HasParamEnv +}; use rustc::ty::{self, Ty, TyCtxt}; use rustc::util::nodemap::FxHashMap; use rustc_target::spec::{HasTargetSpec, Target}; @@ -864,6 +866,6 @@ impl LayoutOf for CodegenCx<'ll, 'tcx> { impl<'tcx, 'll> HasParamEnv<'tcx> for CodegenCx<'ll, 'tcx> { fn param_env(&self) -> ty::ParamEnv<'tcx> { - panic!("asd") + ty::ParamEnv::reveal_all() } } diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index 3f717754e327a..ff25ed9256613 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -383,7 +383,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { return pointee; } - let result = Ty::pointee_info_at(*self, cx, offset, ty::ParamEnv::reveal_all()); + let result = Ty::pointee_info_at(*self, cx, offset); cx.pointee_infos.borrow_mut().insert((self.ty, offset), result); result diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index d69b4b6d2bdca..4b61057e5cf6c 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -933,8 +933,6 @@ pub struct PointeeInfo { } pub trait TyLayoutMethods<'a, C: LayoutOf>: Sized { - type ParamEnv; - fn for_variant( this: TyLayout<'a, Self>, cx: &C, @@ -945,7 +943,6 @@ pub trait TyLayoutMethods<'a, C: LayoutOf>: Sized { this: TyLayout<'a, Self>, cx: &C, offset: Size, - param_env: Self::ParamEnv, ) -> Option; } @@ -958,11 +955,9 @@ impl<'a, Ty> TyLayout<'a, Ty> { where Ty: TyLayoutMethods<'a, C>, C: LayoutOf { Ty::field(self, cx, i) } - pub fn pointee_info_at( - self, cx: &C, offset: Size, param_env: Ty::ParamEnv - ) -> Option + pub fn pointee_info_at(self, cx: &C, offset: Size) -> Option where Ty: TyLayoutMethods<'a, C>, C: LayoutOf { - Ty::pointee_info_at(self, cx, offset, param_env) + Ty::pointee_info_at(self, cx, offset) } } From 0439efbbee8eae0fff98640697adb00d0b0b9357 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 3 May 2019 14:41:47 +0100 Subject: [PATCH 053/212] Improve subst error when parameter kinds mismatch --- src/librustc/ty/subst.rs | 53 ++++++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index ed3da31fb89bd..8d51fbc174a04 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -550,17 +550,32 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> { let opt_ty = self.substs.get(p.idx as usize).map(|k| k.unpack()); let ty = match opt_ty { Some(UnpackedKind::Type(ty)) => ty, - _ => { + Some(kind) => { let span = self.span.unwrap_or(DUMMY_SP); span_bug!( span, - "Type parameter `{:?}` ({:?}/{}) out of range \ + "expected type for `{:?}` ({:?}/{}) but found {:?} \ when substituting (root type={:?}) substs={:?}", p, source_ty, p.idx, + kind, self.root_ty, - self.substs); + self.substs, + ); + } + None => { + let span = self.span.unwrap_or(DUMMY_SP); + span_bug!( + span, + "type parameter `{:?}` ({:?}/{}) out of range \ + when substituting (root type={:?}) substs={:?}", + p, + source_ty, + p.idx, + self.root_ty, + self.substs, + ); } }; @@ -570,29 +585,41 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> { fn const_for_param( &self, p: ParamConst, - source_cn: &'tcx ty::Const<'tcx> + source_ct: &'tcx ty::Const<'tcx> ) -> &'tcx ty::Const<'tcx> { // Look up the const in the substitutions. It really should be in there. - let opt_cn = self.substs.get(p.index as usize).map(|k| k.unpack()); - let cn = match opt_cn { - Some(UnpackedKind::Const(cn)) => cn, - _ => { + let opt_ct = self.substs.get(p.index as usize).map(|k| k.unpack()); + let ct = match opt_ct { + Some(UnpackedKind::Const(ct)) => ct, + Some(kind) => { let span = self.span.unwrap_or(DUMMY_SP); span_bug!( span, - "Const parameter `{:?}` ({:?}/{}) out of range \ - when substituting (root type={:?}) substs={:?}", + "expected const for `{:?}` ({:?}/{}) but found {:?} \ + when substituting substs={:?}", p, - source_cn, + source_ct, + p.index, + kind, + self.substs, + ); + } + None => { + let span = self.span.unwrap_or(DUMMY_SP); + span_bug!( + span, + "const parameter `{:?}` ({:?}/{}) out of range \ + when substituting substs={:?}", + p, + source_ct, p.index, - self.root_ty, self.substs, ); } }; // FIXME(const_generics): shift const through binders - cn + ct } /// It is sometimes necessary to adjust the De Bruijn indices during substitution. This occurs From c187f7112059d2ec182dc216c45581328977f097 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 3 May 2019 14:42:04 +0100 Subject: [PATCH 054/212] Fix subst error for consts in astconv --- src/librustc_typeck/astconv.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 4932d77ef0477..16033c6c50fd0 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -553,7 +553,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { tcx.intern_substs(&substs) } - /// Given the type/region arguments provided to some path (along with + /// Given the type/lifetime/const arguments provided to some path (along with /// an implicit `Self`, if this is a trait reference) returns the complete /// set of substitutions. This may involve applying defaulted type parameters. /// @@ -678,7 +678,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { GenericParamDefKind::Const => { // FIXME(const_generics:defaults) // We've already errored above about the mismatch. - tcx.types.err.into() + tcx.consts.err.into() } } }, From 823293bf1654ad1a841f7cfd67338d9b9d4d0667 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 3 May 2019 14:42:32 +0100 Subject: [PATCH 055/212] Fix subst error for consts in wfcheck --- src/librustc_typeck/check/wfcheck.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 8ee30c0d2d31d..1420c66c73ea3 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -421,8 +421,8 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>( return_ty: Option>, ) { let predicates = fcx.tcx.predicates_of(def_id); - let generics = tcx.generics_of(def_id); + let is_our_default = |def: &ty::GenericParamDef| { match def.kind { GenericParamDefKind::Type { has_default, .. } => { @@ -465,6 +465,7 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>( // All regions are identity. fcx.tcx.mk_param_from_def(param) } + GenericParamDefKind::Type { .. } => { // If the param has a default, if is_our_default(param) { @@ -478,25 +479,24 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>( // Mark unwanted params as err. fcx.tcx.types.err.into() } + GenericParamDefKind::Const => { // FIXME(const_generics:defaults) - fcx.tcx.types.err.into() + fcx.tcx.consts.err.into() } } }); + // Now we build the substituted predicates. let default_obligations = predicates.predicates.iter().flat_map(|&(pred, _)| { #[derive(Default)] struct CountParams { params: FxHashSet } impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams { fn visit_ty(&mut self, t: Ty<'tcx>) -> bool { - match t.sty { - ty::Param(p) => { - self.params.insert(p.idx); - t.super_visit_with(self) - } - _ => t.super_visit_with(self) + if let ty::Param(param) = t.sty { + self.params.insert(param.idx); } + t.super_visit_with(self) } fn visit_region(&mut self, _: ty::Region<'tcx>) -> bool { From 47f373128a9727f299b3ae53cbf7d26da74abc75 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 3 May 2019 14:42:38 +0100 Subject: [PATCH 056/212] Add tests --- .../const-generics/const-param-in-trait-ungated.rs | 3 +++ .../const-param-in-trait-ungated.stderr | 12 ++++++++++++ src/test/ui/const-generics/const-param-in-trait.rs | 8 ++++++++ .../ui/const-generics/const-param-in-trait.stderr | 6 ++++++ 4 files changed, 29 insertions(+) create mode 100644 src/test/ui/const-generics/const-param-in-trait-ungated.rs create mode 100644 src/test/ui/const-generics/const-param-in-trait-ungated.stderr create mode 100644 src/test/ui/const-generics/const-param-in-trait.rs create mode 100644 src/test/ui/const-generics/const-param-in-trait.stderr diff --git a/src/test/ui/const-generics/const-param-in-trait-ungated.rs b/src/test/ui/const-generics/const-param-in-trait-ungated.rs new file mode 100644 index 0000000000000..8a81bcc1a80c8 --- /dev/null +++ b/src/test/ui/const-generics/const-param-in-trait-ungated.rs @@ -0,0 +1,3 @@ +trait Trait {} //~ ERROR const generics are unstable + +fn main() {} diff --git a/src/test/ui/const-generics/const-param-in-trait-ungated.stderr b/src/test/ui/const-generics/const-param-in-trait-ungated.stderr new file mode 100644 index 0000000000000..53bc973841416 --- /dev/null +++ b/src/test/ui/const-generics/const-param-in-trait-ungated.stderr @@ -0,0 +1,12 @@ +error[E0658]: const generics are unstable + --> $DIR/const-param-in-trait-ungated.rs:1:19 + | +LL | trait Trait {} + | ^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/44580 + = help: add #![feature(const_generics)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/const-generics/const-param-in-trait.rs b/src/test/ui/const-generics/const-param-in-trait.rs new file mode 100644 index 0000000000000..6e4f65fe6cac0 --- /dev/null +++ b/src/test/ui/const-generics/const-param-in-trait.rs @@ -0,0 +1,8 @@ +// run-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +trait Trait {} + +fn main() {} diff --git a/src/test/ui/const-generics/const-param-in-trait.stderr b/src/test/ui/const-generics/const-param-in-trait.stderr new file mode 100644 index 0000000000000..a48eefddaa844 --- /dev/null +++ b/src/test/ui/const-generics/const-param-in-trait.stderr @@ -0,0 +1,6 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/const-param-in-trait.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + From 917a0fbc1b73fe7dd5c65fd4b38759366e96c251 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 4 May 2019 15:18:58 +0300 Subject: [PATCH 057/212] Rename `PathResolution` to `PartialRes` Don't use `PartialRes` when `Res` is enough --- src/librustc/hir/def.rs | 29 ++--- src/librustc/hir/lowering.rs | 39 +++--- src/librustc/hir/mod.rs | 2 +- src/librustc_resolve/lib.rs | 156 +++++++++++------------- src/librustc_resolve/resolve_imports.rs | 7 +- 5 files changed, 103 insertions(+), 130 deletions(-) diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index 6366c1f93e671..6ff0c0fbb5008 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -1,5 +1,5 @@ use crate::hir::def_id::DefId; -use crate::util::nodemap::{NodeMap, DefIdMap}; +use crate::util::nodemap::DefIdMap; use syntax::ast; use syntax::ext::base::MacroKind; use syntax::ast::NodeId; @@ -151,7 +151,9 @@ pub enum Res { Err, } -/// The result of resolving a path before lowering to HIR. +/// The result of resolving a path before lowering to HIR, +/// with "module" segments resolved and associated item +/// segments deferred to type checking. /// `base_res` is the resolution of the resolved part of the /// path, `unresolved_segments` is the number of unresolved /// segments. @@ -166,19 +168,21 @@ pub enum Res { /// base_res unresolved_segments = 2 /// ``` #[derive(Copy, Clone, Debug)] -pub struct PathResolution { +pub struct PartialRes { base_res: Res, unresolved_segments: usize, } -impl PathResolution { - pub fn new(res: Res) -> Self { - PathResolution { base_res: res, unresolved_segments: 0 } +impl PartialRes { + #[inline] + pub fn new(base_res: Res) -> Self { + PartialRes { base_res, unresolved_segments: 0 } } - pub fn with_unresolved_segments(res: Res, mut unresolved_segments: usize) -> Self { - if res == Res::Err { unresolved_segments = 0 } - PathResolution { base_res: res, unresolved_segments: unresolved_segments } + #[inline] + pub fn with_unresolved_segments(base_res: Res, mut unresolved_segments: usize) -> Self { + if base_res == Res::Err { unresolved_segments = 0 } + PartialRes { base_res, unresolved_segments } } #[inline] @@ -269,17 +273,10 @@ impl PerNS> { } } -/// Definition mapping -pub type ResMap = NodeMap; - /// This is the replacement export map. It maps a module to all of the exports /// within. pub type ExportMap = DefIdMap>>; -/// Map used to track the `use` statements within a scope, matching it with all the items in every -/// namespace. -pub type ImportMap = NodeMap>>; - #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] pub struct Export { /// The name of the target. diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 8361a62c07e48..9ae9995be43ba 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -37,7 +37,7 @@ use crate::hir::{self, ParamName}; use crate::hir::HirVec; use crate::hir::map::{DefKey, DefPathData, Definitions}; use crate::hir::def_id::{DefId, DefIndex, DefIndexAddressSpace, CRATE_DEF_INDEX}; -use crate::hir::def::{Res, DefKind, PathResolution, PerNS}; +use crate::hir::def::{Res, DefKind, PartialRes, PerNS}; use crate::hir::{GenericArg, ConstArg}; use crate::lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES, ELIDED_LIFETIMES_IN_PATHS}; @@ -145,11 +145,11 @@ pub trait Resolver { is_value: bool, ) -> hir::Path; - /// Obtain the resolution for a `NodeId`. - fn get_resolution(&mut self, id: NodeId) -> Option; + /// Obtain resolution for a `NodeId` with a single resolution. + fn get_partial_res(&mut self, id: NodeId) -> Option; - /// Obtain the possible resolutions for the given `use` statement. - fn get_import(&mut self, id: NodeId) -> PerNS>; + /// Obtain per-namespace resolutions for `use` statement with the given `NoedId`. + fn get_import_res(&mut self, id: NodeId) -> PerNS>>; /// We must keep the set of definitions up to date as we add nodes that weren't in the AST. /// This should only return `None` during testing. @@ -821,7 +821,7 @@ impl<'a> LoweringContext<'a> { } fn expect_full_res(&mut self, id: NodeId) -> Res { - self.resolver.get_resolution(id).map_or(Res::Err, |pr| { + self.resolver.get_partial_res(id).map_or(Res::Err, |pr| { if pr.unresolved_segments() != 0 { bug!("path not fully resolved: {:?}", pr); } @@ -830,12 +830,7 @@ impl<'a> LoweringContext<'a> { } fn expect_full_res_from_use(&mut self, id: NodeId) -> impl Iterator> { - self.resolver.get_import(id).present_items().map(|pr| { - if pr.unresolved_segments() != 0 { - bug!("path not fully resolved: {:?}", pr); - } - pr.base_res() - }) + self.resolver.get_import_res(id).present_items() } fn diagnostic(&self) -> &errors::Handler { @@ -1842,13 +1837,13 @@ impl<'a> LoweringContext<'a> { let qself_position = qself.as_ref().map(|q| q.position); let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx.reborrow())); - let resolution = self.resolver - .get_resolution(id) - .unwrap_or_else(|| PathResolution::new(Res::Err)); + let partial_res = self.resolver + .get_partial_res(id) + .unwrap_or_else(|| PartialRes::new(Res::Err)); - let proj_start = p.segments.len() - resolution.unresolved_segments(); + let proj_start = p.segments.len() - partial_res.unresolved_segments(); let path = P(hir::Path { - res: self.lower_res(resolution.base_res()), + res: self.lower_res(partial_res.base_res()), segments: p.segments[..proj_start] .iter() .enumerate() @@ -1869,7 +1864,7 @@ impl<'a> LoweringContext<'a> { krate: def_id.krate, index: this.def_key(def_id).parent.expect("missing parent"), }; - let type_def_id = match resolution.base_res() { + let type_def_id = match partial_res.base_res() { Res::Def(DefKind::AssociatedTy, def_id) if i + 2 == proj_start => { Some(parent_def_id(self, def_id)) } @@ -1886,7 +1881,7 @@ impl<'a> LoweringContext<'a> { } _ => None, }; - let parenthesized_generic_args = match resolution.base_res() { + let parenthesized_generic_args = match partial_res.base_res() { // `a::b::Trait(Args)` Res::Def(DefKind::Trait, _) if i + 1 == proj_start => ParenthesizedGenericArgs::Ok, @@ -1940,7 +1935,7 @@ impl<'a> LoweringContext<'a> { // Simple case, either no projections, or only fully-qualified. // E.g., `std::mem::size_of` or `::Item`. - if resolution.unresolved_segments() == 0 { + if partial_res.unresolved_segments() == 0 { return hir::QPath::Resolved(qself, path); } @@ -2792,7 +2787,7 @@ impl<'a> LoweringContext<'a> { && bound_pred.bound_generic_params.is_empty() => { if let Some(Res::Def(DefKind::TyParam, def_id)) = self.resolver - .get_resolution(bound_pred.bounded_ty.id) + .get_partial_res(bound_pred.bounded_ty.id) .map(|d| d.base_res()) { if let Some(node_id) = @@ -3946,7 +3941,7 @@ impl<'a> LoweringContext<'a> { let node = match p.node { PatKind::Wild => hir::PatKind::Wild, PatKind::Ident(ref binding_mode, ident, ref sub) => { - match self.resolver.get_resolution(p.id).map(|d| d.base_res()) { + match self.resolver.get_partial_res(p.id).map(|d| d.base_res()) { // `None` can occur in body-less function signatures res @ None | res @ Some(Res::Local(_)) => { let canonical_id = match res { diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index ae7358df9d8fa..7399245b0a00f 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -2142,7 +2142,7 @@ pub enum UseKind { /// resolve maps each TraitRef's ref_id to its defining trait; that's all /// that the ref_id is for. Note that ref_id's value is not the NodeId of the /// trait being referred to but just a unique NodeId that serves as a key -/// within the ResMap. +/// within the resolution map. #[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct TraitRef { pub path: Path, diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index e0892f98d3147..131f26663c70b 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -24,7 +24,7 @@ use rustc::middle::cstore::CrateStore; use rustc::session::Session; use rustc::lint; use rustc::hir::def::{ - self, DefKind, PathResolution, CtorKind, CtorOf, NonMacroAttrKind, ResMap, ImportMap, ExportMap + self, DefKind, PartialRes, CtorKind, CtorOf, NonMacroAttrKind, ExportMap }; use rustc::hir::def::Namespace::*; use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; @@ -821,7 +821,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { let self_ty = keywords::SelfUpper.ident(); let res = self.resolve_ident_in_lexical_scope(self_ty, TypeNS, Some(ty.id), ty.span) .map_or(Res::Err, |d| d.res()); - self.record_res(ty.id, PathResolution::new(res)); + self.record_partial_res(ty.id, PartialRes::new(res)); } _ => (), } @@ -1146,7 +1146,7 @@ impl ModuleOrUniformRoot<'_> { #[derive(Clone, Debug)] enum PathResult<'a> { Module(ModuleOrUniformRoot<'a>), - NonModule(PathResolution), + NonModule(PartialRes), Indeterminate, Failed { span: Span, @@ -1659,8 +1659,11 @@ pub struct Resolver<'a> { /// The idents for the primitive types. primitive_type_table: PrimitiveTypeTable, - res_map: ResMap, - import_map: ImportMap, + /// Resolutions for nodes that have a single resolution. + partial_res_map: NodeMap, + /// Resolutions for import nodes, which have multiple resolutions in different namespaces. + import_res_map: NodeMap>>, + pub freevars: FreevarMap, freevars_seen: NodeMap>, pub export_map: ExportMap, @@ -1830,12 +1833,12 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> { self.resolve_hir_path(&path, is_value) } - fn get_resolution(&mut self, id: NodeId) -> Option { - self.res_map.get(&id).cloned() + fn get_partial_res(&mut self, id: NodeId) -> Option { + self.partial_res_map.get(&id).cloned() } - fn get_import(&mut self, id: NodeId) -> PerNS> { - self.import_map.get(&id).cloned().unwrap_or_default() + fn get_import_res(&mut self, id: NodeId) -> PerNS> { + self.import_res_map.get(&id).cloned().unwrap_or_default() } fn definitions(&mut self) -> &mut Definitions { @@ -1919,7 +1922,7 @@ impl<'a> Resolver<'a> { let segments: Vec<_> = segments.iter().map(|seg| { let mut hir_seg = hir::PathSegment::from_ident(seg.ident); - hir_seg.res = Some(self.res_map.get(&seg.id).map_or(def::Res::Err, |p| { + hir_seg.res = Some(self.partial_res_map.get(&seg.id).map_or(def::Res::Err, |p| { p.base_res().map_id(|_| panic!("unexpected node_id")) })); hir_seg @@ -2019,8 +2022,8 @@ impl<'a> Resolver<'a> { primitive_type_table: PrimitiveTypeTable::new(), - res_map: Default::default(), - import_map: Default::default(), + partial_res_map: Default::default(), + import_res_map: Default::default(), freevars: Default::default(), freevars_seen: Default::default(), export_map: FxHashMap::default(), @@ -2705,7 +2708,7 @@ impl<'a> Resolver<'a> { self.definitions.local_def_id(param.id), ); function_type_rib.bindings.insert(ident, res); - self.record_res(param.id, PathResolution::new(res)); + self.record_partial_res(param.id, PartialRes::new(res)); } GenericParamKind::Const { .. } => { let ident = param.ident.modern(); @@ -2726,7 +2729,7 @@ impl<'a> Resolver<'a> { self.definitions.local_def_id(param.id), ); function_value_rib.bindings.insert(ident, res); - self.record_res(param.id, PathResolution::new(res)); + self.record_partial_res(param.id, PartialRes::new(res)); } } } @@ -2994,7 +2997,8 @@ impl<'a> Resolver<'a> { pat.walk(&mut |pat| { if let PatKind::Ident(binding_mode, ident, ref sub_pat) = pat.node { - if sub_pat.is_some() || match self.res_map.get(&pat.id).map(|res| res.base_res()) { + if sub_pat.is_some() || match self.partial_res_map.get(&pat.id) + .map(|res| res.base_res()) { Some(Res::Local(..)) => true, _ => false, } { @@ -3146,7 +3150,7 @@ impl<'a> Resolver<'a> { outer_pat_id: NodeId, pat_src: PatternSource, bindings: &mut FxHashMap) - -> PathResolution { + -> Res { // Add the binding to the local ribs, if it // doesn't already exist in the bindings map. (We // must not add it if it's in the bindings map @@ -3193,7 +3197,7 @@ impl<'a> Resolver<'a> { } } - PathResolution::new(res) + res } fn resolve_pattern(&mut self, @@ -3213,7 +3217,7 @@ impl<'a> Resolver<'a> { let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, None, pat.span) .and_then(LexicalScopeBinding::item); - let resolution = binding.map(NameBinding::res).and_then(|res| { + let res = binding.map(NameBinding::res).and_then(|res| { let is_syntactic_ambiguity = opt_pat.is_none() && bmode == BindingMode::ByValue(Mutability::Immutable); match res { @@ -3222,7 +3226,7 @@ impl<'a> Resolver<'a> { // Disambiguate in favor of a unit struct/variant // or constant pattern. self.record_use(ident, ValueNS, binding.unwrap(), false); - Some(PathResolution::new(res)) + Some(res) } Res::Def(DefKind::Ctor(..), _) | Res::Def(DefKind::Const, _) @@ -3254,7 +3258,7 @@ impl<'a> Resolver<'a> { self.fresh_binding(ident, pat.id, outer_pat_id, pat_src, bindings) }); - self.record_res(pat.id, resolution); + self.record_partial_res(pat.id, PartialRes::new(res)); } PatKind::TupleStruct(ref path, ..) => { @@ -3286,35 +3290,15 @@ impl<'a> Resolver<'a> { id: NodeId, qself: Option<&QSelf>, path: &Path, - source: PathSource<'_>) - -> PathResolution { - self.smart_resolve_path_with_crate_lint(id, qself, path, source, CrateLint::SimplePath(id)) - } - - /// A variant of `smart_resolve_path` where you also specify extra - /// information about where the path came from; this extra info is - /// sometimes needed for the lint that recommends rewriting - /// absolute paths to `crate`, so that it knows how to frame the - /// suggestion. If you are just resolving a path like `foo::bar` - /// that appears in an arbitrary location, then you just want - /// `CrateLint::SimplePath`, which is what `smart_resolve_path` - /// already provides. - fn smart_resolve_path_with_crate_lint( - &mut self, - id: NodeId, - qself: Option<&QSelf>, - path: &Path, - source: PathSource<'_>, - crate_lint: CrateLint - ) -> PathResolution { + source: PathSource<'_>) { self.smart_resolve_path_fragment( id, qself, &Segment::from_path(path), path.span, source, - crate_lint, - ) + CrateLint::SimplePath(id), + ); } fn smart_resolve_path_fragment(&mut self, @@ -3324,7 +3308,7 @@ impl<'a> Resolver<'a> { span: Span, source: PathSource<'_>, crate_lint: CrateLint) - -> PathResolution { + -> PartialRes { let ns = source.namespace(); let is_expected = &|res| source.is_expected(res); @@ -3334,10 +3318,10 @@ impl<'a> Resolver<'a> { let node_id = this.definitions.as_local_node_id(def_id).unwrap(); let better = res.is_some(); this.use_injections.push(UseError { err, candidates, node_id, better }); - err_path_resolution() + PartialRes::new(Res::Err) }; - let resolution = match self.resolve_qpath_anywhere( + let partial_res = match self.resolve_qpath_anywhere( id, qself, path, @@ -3347,14 +3331,14 @@ impl<'a> Resolver<'a> { source.global_by_default(), crate_lint, ) { - Some(resolution) if resolution.unresolved_segments() == 0 => { - if is_expected(resolution.base_res()) || resolution.base_res() == Res::Err { - resolution + Some(partial_res) if partial_res.unresolved_segments() == 0 => { + if is_expected(partial_res.base_res()) || partial_res.base_res() == Res::Err { + partial_res } else { // Add a temporary hack to smooth the transition to new struct ctor // visibility rules. See #38932 for more details. let mut res = None; - if let Res::Def(DefKind::Struct, def_id) = resolution.base_res() { + if let Res::Def(DefKind::Struct, def_id) = partial_res.base_res() { if let Some((ctor_res, ctor_vis)) = self.struct_constructors.get(&def_id).cloned() { if is_expected(ctor_res) && self.is_accessible(ctor_vis) { @@ -3363,15 +3347,15 @@ impl<'a> Resolver<'a> { "private struct constructors are not usable through \ re-exports in outer modules", ); - res = Some(PathResolution::new(ctor_res)); + res = Some(PartialRes::new(ctor_res)); } } } - res.unwrap_or_else(|| report_errors(self, Some(resolution.base_res()))) + res.unwrap_or_else(|| report_errors(self, Some(partial_res.base_res()))) } } - Some(resolution) if source.defer_to_typeck() => { + Some(partial_res) if source.defer_to_typeck() => { // Not fully resolved associated item `T::A::B` or `::A::B` // or `::A::B`. If `B` should be resolved in value namespace then // it needs to be added to the trait map. @@ -3399,16 +3383,16 @@ impl<'a> Resolver<'a> { hm.insert(span, span); } } - resolution + partial_res } _ => report_errors(self, None) }; if let PathSource::TraitItem(..) = source {} else { // Avoid recording definition of `A::B` in `::B::C`. - self.record_res(id, resolution); + self.record_partial_res(id, partial_res); } - resolution + partial_res } /// Only used in a specific case of type ascription suggestions @@ -3523,7 +3507,7 @@ impl<'a> Resolver<'a> { defer_to_typeck: bool, global_by_default: bool, crate_lint: CrateLint, - ) -> Option { + ) -> Option { let mut fin_res = None; // FIXME: can't resolve paths in macro namespace yet, macros are // processed by the little special hack below. @@ -3532,9 +3516,10 @@ impl<'a> Resolver<'a> { match self.resolve_qpath(id, qself, path, ns, span, global_by_default, crate_lint) { // If defer_to_typeck, then resolution > no resolution, // otherwise full resolution > partial resolution > no resolution. - Some(res) if res.unresolved_segments() == 0 || defer_to_typeck => - return Some(res), - res => if fin_res.is_none() { fin_res = res }, + Some(partial_res) if partial_res.unresolved_segments() == 0 || + defer_to_typeck => + return Some(partial_res), + partial_res => if fin_res.is_none() { fin_res = partial_res }, }; } } @@ -3545,7 +3530,7 @@ impl<'a> Resolver<'a> { self.macro_use_prelude.get(&path[0].ident.name).cloned() .and_then(NameBinding::macro_kind) == Some(MacroKind::Bang)) { // Return some dummy definition, it's enough for error reporting. - return Some(PathResolution::new(Res::Def( + return Some(PartialRes::new(Res::Def( DefKind::Macro(MacroKind::Bang), DefId::local(CRATE_DEF_INDEX), ))); @@ -3563,7 +3548,7 @@ impl<'a> Resolver<'a> { span: Span, global_by_default: bool, crate_lint: CrateLint, - ) -> Option { + ) -> Option { debug!( "resolve_qpath(id={:?}, qself={:?}, path={:?}, \ ns={:?}, span={:?}, global_by_default={:?})", @@ -3580,7 +3565,7 @@ impl<'a> Resolver<'a> { // This is a case like `::B`, where there is no // trait to resolve. In that case, we leave the `B` // segment to be resolved by type-check. - return Some(PathResolution::with_unresolved_segments( + return Some(PartialRes::with_unresolved_segments( Res::Def(DefKind::Mod, DefId::local(CRATE_DEF_INDEX)), path.len() )); } @@ -3600,7 +3585,7 @@ impl<'a> Resolver<'a> { // name from a fully qualified path, and this also // contains the full span (the `CrateLint::QPathTrait`). let ns = if qself.position + 1 == path.len() { ns } else { TypeNS }; - let res = self.smart_resolve_path_fragment( + let partial_res = self.smart_resolve_path_fragment( id, None, &path[..=qself.position], @@ -3615,8 +3600,9 @@ impl<'a> Resolver<'a> { // The remaining segments (the `C` in our example) will // have to be resolved by type-check, since that requires doing // trait resolution. - return Some(PathResolution::with_unresolved_segments( - res.base_res(), res.unresolved_segments() + path.len() - qself.position - 1 + return Some(PartialRes::with_unresolved_segments( + partial_res.base_res(), + partial_res.unresolved_segments() + path.len() - qself.position - 1, )); } @@ -3629,7 +3615,7 @@ impl<'a> Resolver<'a> { ) { PathResult::NonModule(path_res) => path_res, PathResult::Module(ModuleOrUniformRoot::Module(module)) if !module.is_normal() => { - PathResolution::new(module.res().unwrap()) + PartialRes::new(module.res().unwrap()) } // In `a(::assoc_item)*` `a` cannot be a module. If `a` does resolve to a module we // don't report an error right away, but try to fallback to a primitive type. @@ -3649,13 +3635,13 @@ impl<'a> Resolver<'a> { self.primitive_type_table.primitive_types .contains_key(&path[0].ident.name) => { let prim = self.primitive_type_table.primitive_types[&path[0].ident.name]; - PathResolution::with_unresolved_segments(Res::PrimTy(prim), path.len() - 1) + PartialRes::with_unresolved_segments(Res::PrimTy(prim), path.len() - 1) } PathResult::Module(ModuleOrUniformRoot::Module(module)) => - PathResolution::new(module.res().unwrap()), + PartialRes::new(module.res().unwrap()), PathResult::Failed { is_error_from_last_segment: false, span, label, suggestion } => { resolve_error(self, span, ResolutionError::FailedToResolve { label, suggestion }); - err_path_resolution() + PartialRes::new(Res::Err) } PathResult::Module(..) | PathResult::Failed { .. } => return None, PathResult::Indeterminate => bug!("indetermined path result in resolve_qpath"), @@ -3731,9 +3717,9 @@ impl<'a> Resolver<'a> { let record_segment_res = |this: &mut Self, res| { if record_used { if let Some(id) = id { - if !this.res_map.contains_key(&id) { + if !this.partial_res_map.contains_key(&id) { assert!(id != ast::DUMMY_NODE_ID, "Trying to resolve dummy id"); - this.record_res(id, PathResolution::new(res)); + this.record_partial_res(id, PartialRes::new(res)); } } } @@ -3837,7 +3823,7 @@ impl<'a> Resolver<'a> { Some(LexicalScopeBinding::Res(res)) if opt_ns == Some(TypeNS) || opt_ns == Some(ValueNS) => { record_segment_res(self, res); - return PathResult::NonModule(PathResolution::with_unresolved_segments( + return PathResult::NonModule(PartialRes::with_unresolved_segments( res, path.len() - 1 )); } @@ -3864,9 +3850,9 @@ impl<'a> Resolver<'a> { ).emit(); } let res = Res::NonMacroAttr(NonMacroAttrKind::Tool); - return PathResult::NonModule(PathResolution::new(res)); + return PathResult::NonModule(PartialRes::new(res)); } else if res == Res::Err { - return PathResult::NonModule(err_path_resolution()); + return PathResult::NonModule(PartialRes::new(Res::Err)); } else if opt_ns.is_some() && (is_last || maybe_assoc) { self.lint_if_path_starts_with_module( crate_lint, @@ -3874,7 +3860,7 @@ impl<'a> Resolver<'a> { path_span, second_binding, ); - return PathResult::NonModule(PathResolution::with_unresolved_segments( + return PathResult::NonModule(PartialRes::with_unresolved_segments( res, path.len() - i - 1 )); } else { @@ -3897,7 +3883,7 @@ impl<'a> Resolver<'a> { Err(Determined) => { if let Some(ModuleOrUniformRoot::Module(module)) = module { if opt_ns.is_some() && !module.is_normal() { - return PathResult::NonModule(PathResolution::with_unresolved_segments( + return PathResult::NonModule(PartialRes::with_unresolved_segments( module.res().unwrap(), path.len() - i )); } @@ -3928,7 +3914,7 @@ impl<'a> Resolver<'a> { (format!("maybe a missing `extern crate {};`?", ident), None) } else { // the parser will already have complained about the keyword being used - return PathResult::NonModule(err_path_resolution()); + return PathResult::NonModule(PartialRes::new(Res::Err)); } } else if i == 0 { (format!("use of undeclared type or module `{}`", ident), None) @@ -4177,7 +4163,7 @@ impl<'a> Resolver<'a> { if filter_fn(Res::Local(ast::DUMMY_NODE_ID)) { if let Some(node_id) = self.current_self_type.as_ref().and_then(extract_node_id) { // Look for a field with the same name in the current self_type. - if let Some(resolution) = self.res_map.get(&node_id) { + if let Some(resolution) = self.partial_res_map.get(&node_id) { match resolution.base_res() { Res::Def(DefKind::Struct, did) | Res::Def(DefKind::Union, did) if resolution.unresolved_segments() == 0 => { @@ -4398,7 +4384,7 @@ impl<'a> Resolver<'a> { }); find_best_match_for_name(names, &*ident.as_str(), None) }); - self.record_res(expr.id, err_path_resolution()); + self.record_partial_res(expr.id, PartialRes::new(Res::Err)); resolve_error(self, label.ident.span, ResolutionError::UndeclaredLabel(&label.ident.as_str(), @@ -4406,7 +4392,7 @@ impl<'a> Resolver<'a> { } Some(Res::Label(id)) => { // Since this res is a label, it is never read. - self.record_res(expr.id, PathResolution::new(Res::Label(id))); + self.record_partial_res(expr.id, PartialRes::new(Res::Label(id))); self.unused_labels.remove(&id); } Some(_) => { @@ -4858,9 +4844,9 @@ impl<'a> Resolver<'a> { }) } - fn record_res(&mut self, node_id: NodeId, resolution: PathResolution) { + fn record_partial_res(&mut self, node_id: NodeId, resolution: PartialRes) { debug!("(recording res) recording {:?} for {}", resolution, node_id); - if let Some(prev_res) = self.res_map.insert(node_id, resolution) { + if let Some(prev_res) = self.partial_res_map.insert(node_id, resolution) { panic!("path resolved multiple times ({:?} before, {:?} now)", prev_res, resolution); } } @@ -5483,10 +5469,6 @@ fn module_to_string(module: Module<'_>) -> Option { .collect::>())) } -fn err_path_resolution() -> PathResolution { - PathResolution::new(Res::Err) -} - #[derive(Copy, Clone, Debug)] enum CrateLint { /// Do not issue the lint. diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 522a49ee2c1ea..9e6b8d035458d 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -21,7 +21,7 @@ use rustc::lint::builtin::{ UNUSED_IMPORTS, }; use rustc::hir::def_id::{CrateNum, DefId}; -use rustc::hir::def::{self, DefKind, PathResolution, Export}; +use rustc::hir::def::{self, DefKind, PartialRes, Export}; use rustc::session::DiagnosticMessageId; use rustc::util::nodemap::FxHashSet; use rustc::{bug, span_bug}; @@ -1233,8 +1233,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { res = Res::Err; } } - let import = this.import_map.entry(directive.id).or_default(); - import[ns] = Some(PathResolution::new(res)); + this.import_res_map.entry(directive.id).or_default()[ns] = Some(res); }); self.check_for_redundant_imports( @@ -1371,7 +1370,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } // Record the destination of this import - self.record_res(directive.id, PathResolution::new(module.res().unwrap())); + self.record_partial_res(directive.id, PartialRes::new(module.res().unwrap())); } // Miscellaneous post-processing, including recording re-exports, From 85ddd1dc587615a0dc76cef80ff7d88a1b4bc28e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 4 May 2019 15:22:00 +0300 Subject: [PATCH 058/212] Rename `Res::kind_name` to `Res::descr` for consistency --- src/librustc/hir/def.rs | 2 +- src/librustc_mir/hair/pattern/check_match.rs | 2 +- src/librustc_resolve/diagnostics.rs | 2 +- src/librustc_resolve/lib.rs | 8 ++++---- src/librustc_resolve/macros.rs | 4 ++-- src/librustc_typeck/check/_match.rs | 4 ++-- src/librustc_typeck/check/mod.rs | 2 +- src/librustdoc/passes/collect_intra_doc_links.rs | 10 +++++----- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index 6ff0c0fbb5008..87af450451e7e 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -370,7 +370,7 @@ impl Res { } /// A human readable name for the res kind ("function", "module", etc.). - pub fn kind_name(&self) -> &'static str { + pub fn descr(&self) -> &'static str { match *self { Res::Def(kind, _) => kind.descr(), Res::SelfCtor(..) => "self constructor", diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index b08499b981cd7..ed183acc93b74 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -286,7 +286,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { PatKind::Path(hir::QPath::Resolved(None, ref path)) if path.segments.len() == 1 && path.segments[0].args.is_none() => { format!("interpreted as {} {} pattern, not new variable", - path.res.article(), path.res.kind_name()) + path.res.article(), path.res.descr()) } _ => format!("pattern `{}` not covered", pattern_string), }; diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index bbfc39fc6eaf0..509aa95bb61df 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -41,7 +41,7 @@ impl<'a> Resolver<'a> { let item_str = path.last().unwrap().ident; let code = source.error_code(res.is_some()); let (base_msg, fallback_label, base_span) = if let Some(res) = res { - (format!("expected {}, found {} `{}`", expected, res.kind_name(), path_str), + (format!("expected {}, found {} `{}`", expected, res.descr(), path_str), format!("not a {}", expected), span) } else { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 131f26663c70b..88465535c2cb6 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1532,7 +1532,7 @@ impl<'a> NameBinding<'a> { } fn descr(&self) -> &'static str { - if self.is_extern_crate() { "extern crate" } else { self.res().kind_name() } + if self.is_extern_crate() { "extern crate" } else { self.res().descr() } } fn article(&self) -> &'static str { @@ -3868,7 +3868,7 @@ impl<'a> Resolver<'a> { "`{}` is {} {}, not a module", ident, res.article(), - res.kind_name(), + res.descr(), ); return PathResult::Failed { @@ -4220,7 +4220,7 @@ impl<'a> Resolver<'a> { names.push(TypoSuggestion { candidate: ident.name, article: binding.res().article(), - kind: binding.res().kind_name(), + kind: binding.res().descr(), }); } } @@ -4238,7 +4238,7 @@ impl<'a> Resolver<'a> { names.push(TypoSuggestion { candidate: ident.name, article: res.article(), - kind: res.kind_name(), + kind: res.descr(), }); } } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 18573a4594f4c..f1706a4616b06 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -333,7 +333,7 @@ impl<'a> Resolver<'a> { // Not only attributes, but anything in macro namespace can result in // `Res::NonMacroAttr` definition (e.g., `inline!()`), so we must report // an error for those cases. - let msg = format!("expected a macro, found {}", res.kind_name()); + let msg = format!("expected a macro, found {}", res.descr()); self.session.span_err(path.span, &msg); return Err(Determinacy::Determined); } @@ -913,7 +913,7 @@ impl<'a> Resolver<'a> { // (which is a best effort error recovery tool, basically), so we can't // promise their resolution won't change later. let msg = format!("inconsistent resolution for a macro: first {}, then {}", - initial_res.kind_name(), res.kind_name()); + initial_res.descr(), res.descr()); this.session.span_err(span, &msg); } else { span_bug!(span, "inconsistent resolution for a macro"); diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 62afbc44d07b6..e9e202ce37996 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -884,7 +884,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); }; let report_unexpected_res = |res: Res| { let msg = format!("expected tuple struct/variant, found {} `{}`", - res.kind_name(), + res.descr(), hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false))); struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg) .span_label(pat.span, "not a tuple variant or struct").emit(); @@ -947,7 +947,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); let fields_ending = if variant.fields.len() == 1 { "" } else { "s" }; struct_span_err!(tcx.sess, pat.span, E0023, "this pattern has {} field{}, but the corresponding {} has {} field{}", - subpats.len(), subpats_ending, res.kind_name(), + subpats.len(), subpats_ending, res.descr(), variant.fields.len(), fields_ending) .span_label(pat.span, format!("expected {} field{}, found {}", variant.fields.len(), fields_ending, subpats.len())) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 4ae75511322b6..e404a8e6972c8 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1902,7 +1902,7 @@ fn report_unexpected_variant_res<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, qpath: &QPath) { span_err!(tcx.sess, span, E0533, "expected unit struct/variant or constant, found {} `{}`", - res.kind_name(), + res.descr(), hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false))); } diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 705b222efe805..abf19a0a5efa4 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -513,18 +513,18 @@ fn ambiguity_error( msg += &format!( "both {} {} and {} {}", first_def.article(), - first_def.kind_name(), + first_def.descr(), second_def.article(), - second_def.kind_name(), + second_def.descr(), ); } _ => { let mut candidates = candidates.iter().peekable(); while let Some((res, _)) = candidates.next() { if candidates.peek().is_some() { - msg += &format!("{} {}, ", res.article(), res.kind_name()); + msg += &format!("{} {}, ", res.article(), res.descr()); } else { - msg += &format!("and {} {}", res.article(), res.kind_name()); + msg += &format!("and {} {}", res.article(), res.descr()); } } } @@ -575,7 +575,7 @@ fn ambiguity_error( diag.span_suggestion( sp, - &format!("to link to the {}, {}", res.kind_name(), action), + &format!("to link to the {}, {}", res.descr(), action), suggestion, Applicability::MaybeIncorrect, ); From 4d9b9e9038102ada95d1898d303038803d752f62 Mon Sep 17 00:00:00 2001 From: "@amit.chandra" <@amit.chandra> Date: Fri, 26 Apr 2019 19:53:18 +0530 Subject: [PATCH 059/212] wip nth_back on chunks Signed-off-by: wizAmit --- src/libcore/slice/mod.rs | 16 ++++++++++++++++ src/libcore/tests/slice.rs | 13 +++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 8731f48675356..049d38c158ce5 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -4152,6 +4152,22 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { Some(snd) } } + + #[inline] + fn nth_back(&mut self, n: usize) { + let (end, overflow) = self.v.len().overflowing_sub(n); + if end < self.v.len() || overflow { + self.v = &[]; + None + } else { + let start = match end.checked_sub(self.chunk_size) { + Some(sum) => cmp::min(self.v.len(), sum), + None => self.v.len(), + }; + let nth = &self.v[start..end]; + self.v = &self.v[end..]; + } + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index acf6b03791f01..0233b96d3a72d 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -134,6 +134,19 @@ fn test_chunks_nth() { assert_eq!(c2.next(), None); } +#[test] +fn test_chunks_nth_back() { + let v: &[i32] = &[0, 1, 2, 3, 4, 5]; + let mut c = v.chunks(2); + assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); + assert_eq!(c.next().unwrap(), &[4, 5]); + + let v2: &[i32] = &[0, 1, 2, 3, 4]; + let mut c2 = v2.chunks(3); + assert_eq!(c2.nth_back(1).unwrap(), &[0, 1]); + assert_eq!(c2.next(), None); +} + #[test] fn test_chunks_last() { let v: &[i32] = &[0, 1, 2, 3, 4, 5]; From 73ca8bc140d4b0935ecb0199ea65723ec6a6791f Mon Sep 17 00:00:00 2001 From: "@amit.chandra" <@amit.chandra> Date: Wed, 1 May 2019 23:34:07 +0530 Subject: [PATCH 060/212] hopefully working nth_back on chunks Signed-off-by: wizAmit --- src/libcore/slice/mod.rs | 17 +++++++++-------- src/libcore/tests/slice.rs | 9 ++++++++- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 049d38c158ce5..00dbe7104d1a4 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -4154,18 +4154,19 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { } #[inline] - fn nth_back(&mut self, n: usize) { - let (end, overflow) = self.v.len().overflowing_sub(n); - if end < self.v.len() || overflow { - self.v = &[]; + fn nth_back(&mut self, n: usize) -> Option { + let (end, overflow) = self.v.len().overflowing_sub(n * self.chunk_size); + if overflow { + self.v = &mut []; None } else { let start = match end.checked_sub(self.chunk_size) { - Some(sum) => cmp::min(self.v.len(), sum), - None => self.v.len(), + Some(res) => cmp::min(self.v.len(), res), + None => 0, }; - let nth = &self.v[start..end]; - self.v = &self.v[end..]; + let nth_back = &self.v[start..end]; + self.v = &self.v[..start]; + Some(nth_back) } } } diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index 0233b96d3a72d..edea405fad791 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -139,12 +139,19 @@ fn test_chunks_nth_back() { let v: &[i32] = &[0, 1, 2, 3, 4, 5]; let mut c = v.chunks(2); assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); - assert_eq!(c.next().unwrap(), &[4, 5]); + assert_eq!(c.next().unwrap(), &[0, 1]); + assert_eq!(c.next(), None); let v2: &[i32] = &[0, 1, 2, 3, 4]; let mut c2 = v2.chunks(3); assert_eq!(c2.nth_back(1).unwrap(), &[0, 1]); assert_eq!(c2.next(), None); + assert_eq!(c2.next_back(), None); + + let v3: &[i32] = &[0, 1, 2, 3, 4]; + let mut c3 = v3.chunks(10); + assert_eq!(c3.nth_back(0).unwrap(), &[0, 1, 2, 3, 4]); + assert_eq!(c3.next(), None); } #[test] From 7da9250fb51e71ecd3dbb4c760c24e836ed3530f Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 4 May 2019 17:22:00 +0300 Subject: [PATCH 061/212] Remove `Res::Label` Paths can never resolve to labels --- src/librustc/hir/def.rs | 4 ---- src/librustc/hir/lowering.rs | 5 ++++- src/librustc_resolve/lib.rs | 35 +++++++++++++++++-------------- src/librustc_save_analysis/lib.rs | 1 - src/librustc_save_analysis/sig.rs | 2 +- 5 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index 87af450451e7e..0719eb701a984 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -142,7 +142,6 @@ pub enum Res { Upvar(Id, // `HirId` of closed over local usize, // index in the `freevars` list of the closure ast::NodeId), // expr node that creates the closure - Label(ast::NodeId), // Macro namespace NonMacroAttr(NonMacroAttrKind), // e.g., `#[inline]` or `#[rustfmt::skip]` @@ -349,7 +348,6 @@ impl Res { Res::Local(..) | Res::Upvar(..) | - Res::Label(..) | Res::PrimTy(..) | Res::SelfTy(..) | Res::SelfCtor(..) | @@ -377,7 +375,6 @@ impl Res { Res::PrimTy(..) => "builtin type", Res::Local(..) => "local variable", Res::Upvar(..) => "closure capture", - Res::Label(..) => "label", Res::SelfTy(..) => "self type", Res::ToolMod => "tool module", Res::NonMacroAttr(attr_kind) => attr_kind.descr(), @@ -405,7 +402,6 @@ impl Res { index, closure ), - Res::Label(id) => Res::Label(id), Res::SelfTy(a, b) => Res::SelfTy(a, b), Res::ToolMod => Res::ToolMod, Res::NonMacroAttr(attr_kind) => Res::NonMacroAttr(attr_kind), diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 9ae9995be43ba..fc3987a4b1918 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -151,6 +151,9 @@ pub trait Resolver { /// Obtain per-namespace resolutions for `use` statement with the given `NoedId`. fn get_import_res(&mut self, id: NodeId) -> PerNS>>; + /// Obtain resolution for a label with the given `NodeId`. + fn get_label_res(&mut self, id: NodeId) -> Option; + /// We must keep the set of definitions up to date as we add nodes that weren't in the AST. /// This should only return `None` during testing. fn definitions(&mut self) -> &mut Definitions; @@ -1246,7 +1249,7 @@ impl<'a> LoweringContext<'a> { fn lower_loop_destination(&mut self, destination: Option<(NodeId, Label)>) -> hir::Destination { let target_id = match destination { Some((id, _)) => { - if let Res::Label(loop_id) = self.expect_full_res(id) { + if let Some(loop_id) = self.resolver.get_label_res(id) { Ok(self.lower_node_id(loop_id)) } else { Err(hir::LoopIdError::UnresolvedLabel) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 88465535c2cb6..0be26451ae4ae 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1071,13 +1071,13 @@ enum RibKind<'a> { /// The resolution keeps a separate stack of ribs as it traverses the AST for each namespace. When /// resolving, the name is looked up from inside out. #[derive(Debug)] -struct Rib<'a> { - bindings: FxHashMap, +struct Rib<'a, R = Res> { + bindings: FxHashMap, kind: RibKind<'a>, } -impl<'a> Rib<'a> { - fn new(kind: RibKind<'a>) -> Rib<'a> { +impl<'a, R> Rib<'a, R> { + fn new(kind: RibKind<'a>) -> Rib<'a, R> { Rib { bindings: Default::default(), kind, @@ -1638,7 +1638,7 @@ pub struct Resolver<'a> { ribs: PerNS>>, /// The current set of local scopes, for labels. - label_ribs: Vec>, + label_ribs: Vec>, /// The trait that the current context can refer to. current_trait_ref: Option<(Module<'a>, TraitRef)>, @@ -1663,6 +1663,8 @@ pub struct Resolver<'a> { partial_res_map: NodeMap, /// Resolutions for import nodes, which have multiple resolutions in different namespaces. import_res_map: NodeMap>>, + /// Resolutions for labels (node IDs of their corresponding blocks or loops). + label_res_map: NodeMap, pub freevars: FreevarMap, freevars_seen: NodeMap>, @@ -1841,6 +1843,10 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> { self.import_res_map.get(&id).cloned().unwrap_or_default() } + fn get_label_res(&mut self, id: NodeId) -> Option { + self.label_res_map.get(&id).cloned() + } + fn definitions(&mut self) -> &mut Definitions { &mut self.definitions } @@ -2024,6 +2030,7 @@ impl<'a> Resolver<'a> { partial_res_map: Default::default(), import_res_map: Default::default(), + label_res_map: Default::default(), freevars: Default::default(), freevars_seen: Default::default(), export_map: FxHashMap::default(), @@ -2490,7 +2497,7 @@ impl<'a> Resolver<'a> { /// /// Stops after meeting a closure. fn search_label(&self, mut ident: Ident, pred: P) -> Option - where P: Fn(&Rib<'_>, Ident) -> Option + where P: Fn(&Rib<'_, NodeId>, Ident) -> Option { for rib in self.label_ribs.iter().rev() { match rib.kind { @@ -4332,10 +4339,9 @@ impl<'a> Resolver<'a> { { if let Some(label) = label { self.unused_labels.insert(id, label.ident.span); - let res = Res::Label(id); self.with_label_rib(|this| { let ident = label.ident.modern_and_legacy(); - this.label_ribs.last_mut().unwrap().bindings.insert(ident, res); + this.label_ribs.last_mut().unwrap().bindings.insert(ident, id); f(this); }); } else { @@ -4366,10 +4372,10 @@ impl<'a> Resolver<'a> { } ExprKind::Break(Some(label), _) | ExprKind::Continue(Some(label)) => { - let res = self.search_label(label.ident, |rib, ident| { + let node_id = self.search_label(label.ident, |rib, ident| { rib.bindings.get(&ident.modern_and_legacy()).cloned() }); - match res { + match node_id { None => { // Search again for close matches... // Picks the first label that is "close enough", which is not necessarily @@ -4390,13 +4396,10 @@ impl<'a> Resolver<'a> { ResolutionError::UndeclaredLabel(&label.ident.as_str(), close_match)); } - Some(Res::Label(id)) => { + Some(node_id) => { // Since this res is a label, it is never read. - self.record_partial_res(expr.id, PartialRes::new(Res::Label(id))); - self.unused_labels.remove(&id); - } - Some(_) => { - span_bug!(expr.span, "label wasn't mapped to a label res!"); + self.label_res_map.insert(expr.id, node_id); + self.unused_labels.remove(&node_id); } } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index c242b4d6a4123..f3e0fb32ec2dc 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -796,7 +796,6 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } Res::PrimTy(..) | Res::SelfTy(..) | - Res::Label(..) | Res::Def(HirDefKind::Macro(..), _) | Res::ToolMod | Res::NonMacroAttr(..) | diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 4f759b8a73fcc..fa12d9c49dfc3 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -579,7 +579,7 @@ impl Sig for ast::Path { let res = scx.get_path_res(id.ok_or("Missing id for Path")?); let (name, start, end) = match res { - Res::Label(..) | Res::PrimTy(..) | Res::SelfTy(..) | Res::Err => { + Res::PrimTy(..) | Res::SelfTy(..) | Res::Err => { return Ok(Signature { text: pprust::path_to_string(self), defs: vec![], From 5deec307f70135d83839e98c64495f91d776bc27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20Steen=20M=C3=B8ller?= Date: Tue, 30 Apr 2019 15:59:29 +0200 Subject: [PATCH 062/212] Fix #45268 by saving all NodeId's for resolved traits. --- Cargo.lock | 16 +++++- src/librustc/hir/mod.rs | 9 +++- src/librustc/ich/impls_hir.rs | 21 ++++---- src/librustc_resolve/Cargo.toml | 1 + src/librustc_resolve/lib.rs | 41 ++++++++-------- src/librustc_typeck/check/method/mod.rs | 6 +-- src/librustc_typeck/check/method/probe.rs | 32 ++++++------ .../lint/unused_import_warning_issue_45268.rs | 49 +++++++++++++++++++ .../unused_import_warning_issue_45268.stderr | 12 +++++ 9 files changed, 137 insertions(+), 50 deletions(-) create mode 100644 src/test/ui/lint/unused_import_warning_issue_45268.rs create mode 100644 src/test/ui/lint/unused_import_warning_issue_45268.stderr diff --git a/Cargo.lock b/Cargo.lock index 7823c377b2ad8..f8dd4c91773be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -296,6 +296,18 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cargo_metadata" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cargo_metadata" version = "0.7.1" @@ -1612,7 +1624,7 @@ name = "miri" version = "0.1.0" dependencies = [ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cargo_metadata 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "compiletest_rs 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", "directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2957,6 +2969,7 @@ dependencies = [ "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "rustc_metadata 0.0.0", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -4066,6 +4079,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" "checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" "checksum bytesize 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "716960a18f978640f25101b5cbf1c6f6b0d3192fab36a2d98ca96f0ecbe41010" +"checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" "checksum cargo_metadata 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "585784cac9b05c93a53b17a0b24a5cdd1dfdda5256f030e089b549d2390cc720" "checksum cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)" = "5e5f3fee5eeb60324c2781f1e41286bdee933850fff9b3c672587fed5ec58c83" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index ae7358df9d8fa..8ef5b24a9f279 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -37,6 +37,7 @@ use rustc_macros::HashStable; use serialize::{self, Encoder, Encodable, Decoder, Decodable}; use std::collections::{BTreeSet, BTreeMap}; use std::fmt; +use smallvec::SmallVec; /// HIR doesn't commit to a concrete storage type and has its own alias for a vector. /// It can be `Vec`, `P<[T]>` or potentially `Box<[T]>`, or some other container with similar @@ -2505,10 +2506,16 @@ pub type FreevarMap = NodeMap>>; pub type CaptureModeMap = NodeMap; +pub type SmallHirIdVec = SmallVec<[HirId;1]>; +pub type SmallNodeIdVec = SmallVec<[NodeId;1]>; + + // The TraitCandidate's import_ids is empty if the trait is defined in the same module, and + // has length > 0 if the trait is found through an chain of imports, starting with the + // import/use statement in the scope where the trait is used. #[derive(Clone, Debug)] pub struct TraitCandidate { pub def_id: DefId, - pub import_id: Option, + pub import_ids: SmallNodeIdVec, } // Trait method resolution diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 65795d2b136b4..eb57f08003ced 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -391,13 +391,14 @@ impl<'a> HashStable> for hir::TraitCandidate { hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { - let hir::TraitCandidate { + let &hir::TraitCandidate { def_id, - import_id, - } = *self; + import_ids, + } = &self; def_id.hash_stable(hcx, hasher); - import_id.hash_stable(hcx, hasher); + // We only use the outermost import NodeId as key + import_ids.first().hash_stable(hcx, hasher); }); } } @@ -410,13 +411,13 @@ impl<'a> ToStableHashKey> for hir::TraitCandidate { -> Self::KeyType { let hir::TraitCandidate { def_id, - import_id, - } = *self; + import_ids, + } = self; - let import_id = import_id.map(|node_id| hcx.node_to_hir_id(node_id)) - .map(|hir_id| (hcx.local_def_path_hash(hir_id.owner), - hir_id.local_id)); - (hcx.def_path_hash(def_id), import_id) + let import_ids = import_ids.first().map(|node_id| hcx.node_to_hir_id(*node_id)) + .map(|hir_id| (hcx.local_def_path_hash(hir_id.owner), + hir_id.local_id)); + (hcx.def_path_hash(*def_id), import_ids) } } diff --git a/src/librustc_resolve/Cargo.toml b/src/librustc_resolve/Cargo.toml index 836b4ad38ca88..968a45e241e84 100644 --- a/src/librustc_resolve/Cargo.toml +++ b/src/librustc_resolve/Cargo.toml @@ -20,3 +20,4 @@ errors = { path = "../librustc_errors", package = "rustc_errors" } syntax_pos = { path = "../libsyntax_pos" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_metadata = { path = "../librustc_metadata" } +smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index e0892f98d3147..71721504d5add 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -17,6 +17,7 @@ pub use rustc::hir::def::{Namespace, PerNS}; use GenericParameters::*; use RibKind::*; +use smallvec::smallvec; use rustc::hir::map::{Definitions, DefCollector}; use rustc::hir::{self, PrimTy, Bool, Char, Float, Int, Uint, Str}; @@ -28,7 +29,7 @@ use rustc::hir::def::{ }; use rustc::hir::def::Namespace::*; use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; -use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap}; +use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap, SmallNodeIdVec}; use rustc::ty::{self, DefIdTree}; use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap}; use rustc::{bug, span_bug}; @@ -4582,7 +4583,7 @@ impl<'a> Resolver<'a> { module.span, ).is_ok() { let def_id = module.def_id().unwrap(); - found_traits.push(TraitCandidate { def_id: def_id, import_id: None }); + found_traits.push(TraitCandidate { def_id: def_id, import_ids: smallvec![] }); } } @@ -4641,37 +4642,35 @@ impl<'a> Resolver<'a> { false, module.span, ).is_ok() { - let import_id = match binding.kind { - NameBindingKind::Import { directive, .. } => { - self.maybe_unused_trait_imports.insert(directive.id); - self.add_to_glob_map(&directive, trait_name); - Some(directive.id) - } - _ => None, - }; + let import_ids = self.find_transitive_imports(&binding.kind, &trait_name); let trait_def_id = module.def_id().unwrap(); - found_traits.push(TraitCandidate { def_id: trait_def_id, import_id }); + found_traits.push(TraitCandidate { def_id: trait_def_id, import_ids }); } } else if let Res::Def(DefKind::TraitAlias, _) = binding.res() { // For now, just treat all trait aliases as possible candidates, since we don't // know if the ident is somewhere in the transitive bounds. - - let import_id = match binding.kind { - NameBindingKind::Import { directive, .. } => { - self.maybe_unused_trait_imports.insert(directive.id); - self.add_to_glob_map(&directive, trait_name); - Some(directive.id) - } - _ => None, - }; + let import_ids = self.find_transitive_imports(&binding.kind, &trait_name); let trait_def_id = binding.res().def_id(); - found_traits.push(TraitCandidate { def_id: trait_def_id, import_id }); + found_traits.push(TraitCandidate { def_id: trait_def_id, import_ids }); } else { bug!("candidate is not trait or trait alias?") } } } + fn find_transitive_imports(&mut self, kind: &NameBindingKind<'_>, + trait_name: &Ident) -> SmallNodeIdVec { + let mut import_ids = smallvec![]; + let mut kind = kind; + while let NameBindingKind::Import { directive, binding, .. } = *kind { + self.maybe_unused_trait_imports.insert(directive.id); + self.add_to_glob_map(&directive, *trait_name); + import_ids.push(directive.id); + kind = &binding.kind; + }; + import_ids + } + fn lookup_import_candidates_from_module(&mut self, lookup_ident: Ident, namespace: Namespace, diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index bbdc7df4441e8..a4b1687ea5301 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -195,8 +195,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ProbeScope::TraitsInScope )?; - if let Some(import_id) = pick.import_id { - let import_def_id = self.tcx.hir().local_def_id_from_hir_id(import_id); + for import_id in &pick.import_ids { + let import_def_id = self.tcx.hir().local_def_id_from_hir_id(*import_id); debug!("used_trait_import: {:?}", import_def_id); Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports) .unwrap().insert(import_def_id); @@ -434,7 +434,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let pick = self.probe_for_name(span, probe::Mode::Path, method_name, IsSuggestion(false), self_ty, expr_id, ProbeScope::TraitsInScope)?; debug!("resolve_ufcs: pick={:?}", pick); - if let Some(import_id) = pick.import_id { + for import_id in pick.import_ids { let import_def_id = tcx.hir().local_def_id_from_hir_id(import_id); debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id); Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports) diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 8c61a127d1014..148b7d5edb570 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -7,6 +7,7 @@ use crate::check::autoderef::{self, Autoderef}; use crate::check::FnCtxt; use crate::hir::def_id::DefId; use crate::hir::def::DefKind; +use crate::hir::SmallHirIdVec; use crate::namespace::Namespace; use rustc_data_structures::sync::Lrc; @@ -35,6 +36,8 @@ use std::mem; use std::ops::Deref; use std::cmp::max; +use smallvec::smallvec; + use self::CandidateKind::*; pub use self::PickKind::*; @@ -121,7 +124,7 @@ struct Candidate<'tcx> { xform_ret_ty: Option>, item: ty::AssociatedItem, kind: CandidateKind<'tcx>, - import_id: Option, + import_ids: SmallHirIdVec, } #[derive(Debug)] @@ -146,7 +149,7 @@ enum ProbeResult { pub struct Pick<'tcx> { pub item: ty::AssociatedItem, pub kind: PickKind<'tcx>, - pub import_id: Option, + pub import_ids: hir::SmallHirIdVec, // Indicates that the source expression should be autoderef'd N times // @@ -716,7 +719,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { self.push_candidate(Candidate { xform_self_ty, xform_ret_ty, item, kind: InherentImplCandidate(impl_substs, obligations), - import_id: None + import_ids: smallvec![] }, true); } } @@ -750,7 +753,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { this.push_candidate(Candidate { xform_self_ty, xform_ret_ty, item, kind: ObjectCandidate, - import_id: None + import_ids: smallvec![] }, true); }); } @@ -799,7 +802,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { this.push_candidate(Candidate { xform_self_ty, xform_ret_ty, item, kind: WhereClauseCandidate(poly_trait_ref), - import_id: None + import_ids: smallvec![] }, true); }); } @@ -838,9 +841,10 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { for trait_candidate in applicable_traits.iter() { let trait_did = trait_candidate.def_id; if duplicates.insert(trait_did) { - let import_id = trait_candidate.import_id.map(|node_id| - self.fcx.tcx.hir().node_to_hir_id(node_id)); - let result = self.assemble_extension_candidates_for_trait(import_id, trait_did); + let import_ids = trait_candidate.import_ids.iter().map(|node_id| + self.fcx.tcx.hir().node_to_hir_id(*node_id)).collect(); + let result = self.assemble_extension_candidates_for_trait(import_ids, + trait_did); result?; } } @@ -852,7 +856,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { let mut duplicates = FxHashSet::default(); for trait_info in suggest::all_traits(self.tcx) { if duplicates.insert(trait_info.def_id) { - self.assemble_extension_candidates_for_trait(None, trait_info.def_id)?; + self.assemble_extension_candidates_for_trait(smallvec![], trait_info.def_id)?; } } Ok(()) @@ -890,7 +894,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { } fn assemble_extension_candidates_for_trait(&mut self, - import_id: Option, + import_ids: SmallHirIdVec, trait_def_id: DefId) -> Result<(), MethodError<'tcx>> { debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})", @@ -907,7 +911,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { let (xform_self_ty, xform_ret_ty) = this.xform_self_ty(&item, new_trait_ref.self_ty(), new_trait_ref.substs); this.push_candidate(Candidate { - xform_self_ty, xform_ret_ty, item, import_id, + xform_self_ty, xform_ret_ty, item, import_ids: import_ids.clone(), kind: TraitCandidate(new_trait_ref), }, true); }); @@ -924,7 +928,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { let (xform_self_ty, xform_ret_ty) = self.xform_self_ty(&item, trait_ref.self_ty(), trait_substs); self.push_candidate(Candidate { - xform_self_ty, xform_ret_ty, item, import_id, + xform_self_ty, xform_ret_ty, item, import_ids: import_ids.clone(), kind: TraitCandidate(trait_ref), }, false); } @@ -1413,7 +1417,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { Some(Pick { item: probes[0].0.item.clone(), kind: TraitPick, - import_id: probes[0].0.import_id, + import_ids: probes[0].0.import_ids.clone(), autoderefs: 0, autoref: None, unsize: None, @@ -1652,7 +1656,7 @@ impl<'tcx> Candidate<'tcx> { WhereClausePick(trait_ref.clone()) } }, - import_id: self.import_id, + import_ids: self.import_ids.clone(), autoderefs: 0, autoref: None, unsize: None, diff --git a/src/test/ui/lint/unused_import_warning_issue_45268.rs b/src/test/ui/lint/unused_import_warning_issue_45268.rs new file mode 100644 index 0000000000000..9f3f5573a15d1 --- /dev/null +++ b/src/test/ui/lint/unused_import_warning_issue_45268.rs @@ -0,0 +1,49 @@ +// compile-pass + +#![warn(unused_imports)] // Warning explanation here, it's OK + +mod test { + pub trait A { + fn a(); + } + + impl A for () { + fn a() { } + } + + pub trait B { + fn b(self); + } + + impl B for () { + fn b(self) { } + } + + pub trait Unused { + } +} + +use test::Unused; // This is really unused, so warning is OK +use test::A; // This is used by the test2::func() through import of super::* +use test::B; // This is used by the test2::func() through import of super::* + +mod test2 { + use super::*; + pub fn func() { + let _ = <()>::a(); + let _ = ().b(); + test3::inner_func(); + } + mod test3 { + use super::*; + pub fn inner_func() { + let _ = <()>::a(); + let _ = ().b(); + } +} + +} + +fn main() { + test2::func(); +} diff --git a/src/test/ui/lint/unused_import_warning_issue_45268.stderr b/src/test/ui/lint/unused_import_warning_issue_45268.stderr new file mode 100644 index 0000000000000..7392e99f7aef3 --- /dev/null +++ b/src/test/ui/lint/unused_import_warning_issue_45268.stderr @@ -0,0 +1,12 @@ +warning: unused import: `test::Unused` + --> $DIR/unused_import_warning_issue_45268.rs:26:5 + | +LL | use test::Unused; // This is really unused, so warning is OK + | ^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/unused_import_warning_issue_45268.rs:3:9 + | +LL | #![warn(unused_imports)] // Warning explanation here, it's OK + | ^^^^^^^^^^^^^^ + From 5d2be7d1fa6e420b4265dfc27a622405bd4fc5b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20Steen=20M=C3=B8ller?= Date: Wed, 1 May 2019 15:17:43 +0200 Subject: [PATCH 063/212] Fix misleading indentation --- src/test/ui/lint/unused_import_warning_issue_45268.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/test/ui/lint/unused_import_warning_issue_45268.rs b/src/test/ui/lint/unused_import_warning_issue_45268.rs index 9f3f5573a15d1..0bd7751113593 100644 --- a/src/test/ui/lint/unused_import_warning_issue_45268.rs +++ b/src/test/ui/lint/unused_import_warning_issue_45268.rs @@ -35,15 +35,14 @@ mod test2 { test3::inner_func(); } mod test3 { - use super::*; - pub fn inner_func() { - let _ = <()>::a(); - let _ = ().b(); + use super::*; + pub fn inner_func() { + let _ = <()>::a(); + let _ = ().b(); + } } } -} - fn main() { test2::func(); } From a300cab526497909ebb3bb0f744bcf3279dd2762 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20Steen=20M=C3=B8ller?= Date: Thu, 2 May 2019 08:27:57 +0200 Subject: [PATCH 064/212] Revert the introduced typedefs --- src/librustc/hir/mod.rs | 5 +---- src/librustc_resolve/lib.rs | 8 ++++---- src/librustc_typeck/check/method/probe.rs | 9 ++++----- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 8ef5b24a9f279..9ce300ce0484a 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -2506,16 +2506,13 @@ pub type FreevarMap = NodeMap>>; pub type CaptureModeMap = NodeMap; -pub type SmallHirIdVec = SmallVec<[HirId;1]>; -pub type SmallNodeIdVec = SmallVec<[NodeId;1]>; - // The TraitCandidate's import_ids is empty if the trait is defined in the same module, and // has length > 0 if the trait is found through an chain of imports, starting with the // import/use statement in the scope where the trait is used. #[derive(Clone, Debug)] pub struct TraitCandidate { pub def_id: DefId, - pub import_ids: SmallNodeIdVec, + pub import_ids: SmallVec<[NodeId; 1]>, } // Trait method resolution diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 71721504d5add..635185fe2258a 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -29,7 +29,7 @@ use rustc::hir::def::{ }; use rustc::hir::def::Namespace::*; use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; -use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap, SmallNodeIdVec}; +use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap}; use rustc::ty::{self, DefIdTree}; use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap}; use rustc::{bug, span_bug}; @@ -67,6 +67,7 @@ use std::collections::BTreeSet; use std::mem::replace; use rustc_data_structures::ptr_key::PtrKey; use rustc_data_structures::sync::Lrc; +use smallvec::SmallVec; use diagnostics::{find_span_of_binding_until_next_binding, extend_span_to_previous_binding}; use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver}; @@ -4658,10 +4659,9 @@ impl<'a> Resolver<'a> { } } - fn find_transitive_imports(&mut self, kind: &NameBindingKind<'_>, - trait_name: &Ident) -> SmallNodeIdVec { + fn find_transitive_imports(&mut self, mut kind: &NameBindingKind<'_>, + trait_name: &Ident) -> SmallVec<[NodeId; 1]> { let mut import_ids = smallvec![]; - let mut kind = kind; while let NameBindingKind::Import { directive, binding, .. } = *kind { self.maybe_unused_trait_imports.insert(directive.id); self.add_to_glob_map(&directive, *trait_name); diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 148b7d5edb570..314f7e97cd28d 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -7,7 +7,6 @@ use crate::check::autoderef::{self, Autoderef}; use crate::check::FnCtxt; use crate::hir::def_id::DefId; use crate::hir::def::DefKind; -use crate::hir::SmallHirIdVec; use crate::namespace::Namespace; use rustc_data_structures::sync::Lrc; @@ -36,7 +35,7 @@ use std::mem; use std::ops::Deref; use std::cmp::max; -use smallvec::smallvec; +use smallvec::{smallvec, SmallVec}; use self::CandidateKind::*; pub use self::PickKind::*; @@ -124,7 +123,7 @@ struct Candidate<'tcx> { xform_ret_ty: Option>, item: ty::AssociatedItem, kind: CandidateKind<'tcx>, - import_ids: SmallHirIdVec, + import_ids: SmallVec<[hir::HirId; 1]>, } #[derive(Debug)] @@ -149,7 +148,7 @@ enum ProbeResult { pub struct Pick<'tcx> { pub item: ty::AssociatedItem, pub kind: PickKind<'tcx>, - pub import_ids: hir::SmallHirIdVec, + pub import_ids: SmallVec<[hir::HirId; 1]>, // Indicates that the source expression should be autoderef'd N times // @@ -894,7 +893,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { } fn assemble_extension_candidates_for_trait(&mut self, - import_ids: SmallHirIdVec, + import_ids: SmallVec<[hir::HirId; 1]>, trait_def_id: DefId) -> Result<(), MethodError<'tcx>> { debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})", From 719890502e47e09c86f7543e9efed55ed449af49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20Steen=20M=C3=B8ller?= Date: Thu, 2 May 2019 08:30:16 +0200 Subject: [PATCH 065/212] Improved name: first_import_id --- src/librustc/ich/impls_hir.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index eb57f08003ced..0869893fbad31 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -414,10 +414,10 @@ impl<'a> ToStableHashKey> for hir::TraitCandidate { import_ids, } = self; - let import_ids = import_ids.first().map(|node_id| hcx.node_to_hir_id(*node_id)) + let first_import_id = import_ids.first().map(|node_id| hcx.node_to_hir_id(*node_id)) .map(|hir_id| (hcx.local_def_path_hash(hir_id.owner), hir_id.local_id)); - (hcx.def_path_hash(*def_id), import_ids) + (hcx.def_path_hash(*def_id), first_import_id) } } From 42255d93efe160600dd02711b7b009ea240945b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20Steen=20M=C3=B8ller?= Date: Thu, 2 May 2019 08:31:15 +0200 Subject: [PATCH 066/212] Reuse 'kind' parameter. --- src/librustc_resolve/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 635185fe2258a..d351802266ebb 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -4662,7 +4662,7 @@ impl<'a> Resolver<'a> { fn find_transitive_imports(&mut self, mut kind: &NameBindingKind<'_>, trait_name: &Ident) -> SmallVec<[NodeId; 1]> { let mut import_ids = smallvec![]; - while let NameBindingKind::Import { directive, binding, .. } = *kind { + while let NameBindingKind::Import { directive, binding, .. } = kind { self.maybe_unused_trait_imports.insert(directive.id); self.add_to_glob_map(&directive, *trait_name); import_ids.push(directive.id); From 7dbb5e3b49b00c6bf0ce7b0e11a32eee38aeb8a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20Steen=20M=C3=B8ller?= Date: Thu, 2 May 2019 11:56:45 +0200 Subject: [PATCH 067/212] Use binding autoref, because we can. --- src/librustc/ich/impls_hir.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 0869893fbad31..5bd359ba1f6aa 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -391,10 +391,10 @@ impl<'a> HashStable> for hir::TraitCandidate { hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { - let &hir::TraitCandidate { + let hir::TraitCandidate { def_id, import_ids, - } = &self; + } = self; def_id.hash_stable(hcx, hasher); // We only use the outermost import NodeId as key From fc34d5f608e3476bc7c5c4127d4e1ad1ab4fd01a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20Steen=20M=C3=B8ller?= Date: Thu, 2 May 2019 13:40:12 +0200 Subject: [PATCH 068/212] Removed unneccesary reference for trait name --- src/librustc_resolve/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index d351802266ebb..c439ad9c315ee 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -4643,14 +4643,14 @@ impl<'a> Resolver<'a> { false, module.span, ).is_ok() { - let import_ids = self.find_transitive_imports(&binding.kind, &trait_name); + let import_ids = self.find_transitive_imports(&binding.kind, trait_name); let trait_def_id = module.def_id().unwrap(); found_traits.push(TraitCandidate { def_id: trait_def_id, import_ids }); } } else if let Res::Def(DefKind::TraitAlias, _) = binding.res() { // For now, just treat all trait aliases as possible candidates, since we don't // know if the ident is somewhere in the transitive bounds. - let import_ids = self.find_transitive_imports(&binding.kind, &trait_name); + let import_ids = self.find_transitive_imports(&binding.kind, trait_name); let trait_def_id = binding.res().def_id(); found_traits.push(TraitCandidate { def_id: trait_def_id, import_ids }); } else { @@ -4660,11 +4660,11 @@ impl<'a> Resolver<'a> { } fn find_transitive_imports(&mut self, mut kind: &NameBindingKind<'_>, - trait_name: &Ident) -> SmallVec<[NodeId; 1]> { + trait_name: Ident) -> SmallVec<[NodeId; 1]> { let mut import_ids = smallvec![]; while let NameBindingKind::Import { directive, binding, .. } = kind { self.maybe_unused_trait_imports.insert(directive.id); - self.add_to_glob_map(&directive, *trait_name); + self.add_to_glob_map(&directive, trait_name); import_ids.push(directive.id); kind = &binding.kind; }; From 6802082039285bc07736f8c9900a0410b5c1e7dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20Steen=20M=C3=B8ller?= Date: Thu, 2 May 2019 15:08:03 +0200 Subject: [PATCH 069/212] Hash all of the import_ids for the TraitCandidate. --- src/librustc/ich/impls_hir.rs | 12 ++++++------ src/librustc_data_structures/stable_hasher.rs | 12 ++++++++++++ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 5bd359ba1f6aa..5b2a1e783c039 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -7,6 +7,7 @@ use crate::hir::def_id::{DefId, LocalDefId, CrateNum, CRATE_DEF_INDEX}; use crate::ich::{StableHashingContext, NodeIdHashingMode, Fingerprint}; use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, StableHasher, StableHasherResult}; +use smallvec::SmallVec; use std::mem; use syntax::ast; use syntax::attr; @@ -397,14 +398,13 @@ impl<'a> HashStable> for hir::TraitCandidate { } = self; def_id.hash_stable(hcx, hasher); - // We only use the outermost import NodeId as key - import_ids.first().hash_stable(hcx, hasher); + import_ids.hash_stable(hcx, hasher); }); } } impl<'a> ToStableHashKey> for hir::TraitCandidate { - type KeyType = (DefPathHash, Option<(DefPathHash, hir::ItemLocalId)>); + type KeyType = (DefPathHash, SmallVec<[(DefPathHash, hir::ItemLocalId); 1]>); fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) @@ -414,10 +414,10 @@ impl<'a> ToStableHashKey> for hir::TraitCandidate { import_ids, } = self; - let first_import_id = import_ids.first().map(|node_id| hcx.node_to_hir_id(*node_id)) + let import_keys = import_ids.iter().map(|node_id| hcx.node_to_hir_id(*node_id)) .map(|hir_id| (hcx.local_def_path_hash(hir_id.owner), - hir_id.local_id)); - (hcx.def_path_hash(*def_id), first_import_id) + hir_id.local_id)).collect(); + (hcx.def_path_hash(*def_id), import_keys) } } diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs index 19343a9250df3..c777f1fa82949 100644 --- a/src/librustc_data_structures/stable_hasher.rs +++ b/src/librustc_data_structures/stable_hasher.rs @@ -1,6 +1,7 @@ use std::hash::{Hash, Hasher, BuildHasher}; use std::marker::PhantomData; use std::mem; +use smallvec::SmallVec; use crate::sip128::SipHasher128; use crate::indexed_vec; use crate::bit_set; @@ -318,6 +319,17 @@ impl, CTX> HashStable for Vec { } } +impl HashStable for SmallVec<[A; 1]> where A: HashStable { + #[inline] + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { + for item in self { + item.hash_stable(ctx, hasher); + } + } +} + impl, CTX> HashStable for Box { #[inline] fn hash_stable(&self, From 6da7649f61fae784e1df991be5c688026ade3c84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20Steen=20M=C3=B8ller?= Date: Thu, 2 May 2019 20:16:48 +0200 Subject: [PATCH 070/212] Delegate SmallVec's stable_hash to array's stable_hash. --- src/librustc_data_structures/stable_hasher.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs index c777f1fa82949..fa573907d4c73 100644 --- a/src/librustc_data_structures/stable_hasher.rs +++ b/src/librustc_data_structures/stable_hasher.rs @@ -324,9 +324,7 @@ impl HashStable for SmallVec<[A; 1]> where A: HashStable { fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - for item in self { - item.hash_stable(ctx, hasher); - } + (&self[..]).hash_stable(ctx, hasher); } } From f5b5ca8b2351791fd3c29223d3e663760b5065ae Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 5 May 2019 00:12:38 +0300 Subject: [PATCH 071/212] Revert Cargo.lock changes accidentally introduced during rebase --- Cargo.lock | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f8dd4c91773be..ffa33393c3025 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -296,18 +296,6 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "cargo_metadata" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "cargo_metadata" version = "0.7.1" @@ -1624,7 +1612,7 @@ name = "miri" version = "0.1.0" dependencies = [ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "compiletest_rs 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", "directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4079,7 +4067,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" "checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" "checksum bytesize 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "716960a18f978640f25101b5cbf1c6f6b0d3192fab36a2d98ca96f0ecbe41010" -"checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" "checksum cargo_metadata 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "585784cac9b05c93a53b17a0b24a5cdd1dfdda5256f030e089b549d2390cc720" "checksum cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)" = "5e5f3fee5eeb60324c2781f1e41286bdee933850fff9b3c672587fed5ec58c83" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" From 3e6787cb4cadc036cab3dfee5f7e25f553e6ab24 Mon Sep 17 00:00:00 2001 From: varkor Date: Sat, 4 May 2019 14:38:10 +0100 Subject: [PATCH 072/212] Early error for mixing order of const and type parameters --- src/librustc_passes/ast_validation.rs | 20 ++++++++++++++++--- .../const-param-before-other-params.rs | 8 ++++---- .../const-param-before-other-params.stderr | 12 +++++------ 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 1f5a6d7914125..6cb3161382af2 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -21,7 +21,7 @@ use syntax::visit::{self, Visitor}; use syntax::{span_err, struct_span_err, walk_list}; use syntax_ext::proc_macro_decls::is_proc_macro_attr; use syntax_pos::{Span, MultiSpan}; -use errors::Applicability; +use errors::{Applicability, FatalError}; use log::debug; #[derive(Copy, Clone, Debug)] @@ -368,6 +368,8 @@ fn validate_generics_order<'a>( let mut max_param: Option = None; let mut out_of_order = FxHashMap::default(); let mut param_idents = vec![]; + let mut found_type = false; + let mut found_const = false; for (kind, bounds, span, ident) in generics { if let Some(ident) = ident { @@ -381,6 +383,11 @@ fn validate_generics_order<'a>( } Some(_) | None => *max_param = Some(kind), }; + match kind { + ParamKindOrd::Type => found_type = true, + ParamKindOrd::Const => found_const = true, + _ => {} + } } let mut ordered_params = "<".to_string(); @@ -408,8 +415,8 @@ fn validate_generics_order<'a>( GenericPosition::Arg => "argument", }; - for (param_ord, (max_param, spans)) in out_of_order { - let mut err = handler.struct_span_err(spans, + for (param_ord, (max_param, spans)) in &out_of_order { + let mut err = handler.struct_span_err(spans.clone(), &format!( "{} {pos}s must be declared prior to {} {pos}s", param_ord, @@ -430,6 +437,13 @@ fn validate_generics_order<'a>( } err.emit(); } + + // FIXME(const_generics): we shouldn't have to abort here at all, but we currently get ICEs + // if we don't. Const parameters and type parameters can currently conflict if they + // are out-of-order. + if !out_of_order.is_empty() && found_type && found_const { + FatalError.raise(); + } } impl<'a> Visitor<'a> for AstValidator<'a> { diff --git a/src/test/ui/const-generics/const-param-before-other-params.rs b/src/test/ui/const-generics/const-param-before-other-params.rs index 188b5dce31ea8..2c81681b85e7d 100644 --- a/src/test/ui/const-generics/const-param-before-other-params.rs +++ b/src/test/ui/const-generics/const-param-before-other-params.rs @@ -1,12 +1,12 @@ #![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash -fn foo(_: &T) { - //~^ ERROR type parameters must be declared prior to const parameters -} - fn bar(_: &'a ()) { //~^ ERROR lifetime parameters must be declared prior to const parameters } +fn foo(_: &T) { + //~^ ERROR type parameters must be declared prior to const parameters +} + fn main() {} diff --git a/src/test/ui/const-generics/const-param-before-other-params.stderr b/src/test/ui/const-generics/const-param-before-other-params.stderr index 78f129e79ea24..33f981d1eba9b 100644 --- a/src/test/ui/const-generics/const-param-before-other-params.stderr +++ b/src/test/ui/const-generics/const-param-before-other-params.stderr @@ -4,17 +4,17 @@ warning: the feature `const_generics` is incomplete and may cause the compiler t LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ -error: type parameters must be declared prior to const parameters +error: lifetime parameters must be declared prior to const parameters --> $DIR/const-param-before-other-params.rs:4:21 | -LL | fn foo(_: &T) { - | --------------^- help: reorder the parameters: lifetimes, then types, then consts: `` +LL | fn bar(_: &'a ()) { + | --------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const X: ()>` -error: lifetime parameters must be declared prior to const parameters +error: type parameters must be declared prior to const parameters --> $DIR/const-param-before-other-params.rs:8:21 | -LL | fn bar(_: &'a ()) { - | --------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const X: ()>` +LL | fn foo(_: &T) { + | --------------^- help: reorder the parameters: lifetimes, then types, then consts: `` error: aborting due to 2 previous errors From 121caa927bc4dace0df64f728f62fbce42a15fe9 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sun, 5 May 2019 12:03:32 +0900 Subject: [PATCH 073/212] Correct handling of arguments in async fn --- src/libsyntax/parse/parser.rs | 33 +++++++++++++------- src/test/ui/async-await/argument-patterns.rs | 30 ++++++++++++++++++ src/test/ui/async-await/mutable-arguments.rs | 10 ------ 3 files changed, 52 insertions(+), 21 deletions(-) create mode 100644 src/test/ui/async-await/argument-patterns.rs delete mode 100644 src/test/ui/async-await/mutable-arguments.rs diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d46feeab33599..83f8b0e90c574 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1576,7 +1576,7 @@ impl<'a> Parser<'a> { let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; - let d = self.parse_fn_decl_with_self(|p: &mut Parser<'a>| { + let mut decl = self.parse_fn_decl_with_self(|p: &mut Parser<'a>| { // This is somewhat dubious; We don't want to allow // argument names to be left off if there is a // definition... @@ -1585,7 +1585,7 @@ impl<'a> Parser<'a> { p.parse_arg_general(p.span.rust_2018(), true, false) })?; generics.where_clause = self.parse_where_clause()?; - self.construct_async_arguments(&mut asyncness, &d); + self.construct_async_arguments(&mut asyncness, &mut decl); let sig = ast::MethodSig { header: FnHeader { @@ -1594,7 +1594,7 @@ impl<'a> Parser<'a> { abi, asyncness, }, - decl: d, + decl, }; let body = match self.token { @@ -6479,10 +6479,10 @@ impl<'a> Parser<'a> { -> PResult<'a, ItemInfo> { let (ident, mut generics) = self.parse_fn_header()?; let allow_c_variadic = abi == Abi::C && unsafety == Unsafety::Unsafe; - let decl = self.parse_fn_decl(allow_c_variadic)?; + let mut decl = self.parse_fn_decl(allow_c_variadic)?; generics.where_clause = self.parse_where_clause()?; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; - self.construct_async_arguments(&mut asyncness, &decl); + self.construct_async_arguments(&mut asyncness, &mut decl); let header = FnHeader { unsafety, asyncness, constness, abi }; Ok((ident, ItemKind::Fn(decl, header, generics, body), Some(inner_attrs))) } @@ -6666,9 +6666,9 @@ impl<'a> Parser<'a> { let (constness, unsafety, mut asyncness, abi) = self.parse_fn_front_matter()?; let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; - let decl = self.parse_fn_decl_with_self(|p| p.parse_arg())?; + let mut decl = self.parse_fn_decl_with_self(|p| p.parse_arg())?; generics.where_clause = self.parse_where_clause()?; - self.construct_async_arguments(&mut asyncness, &decl); + self.construct_async_arguments(&mut asyncness, &mut decl); *at_end = true; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; let header = ast::FnHeader { abi, unsafety, constness, asyncness }; @@ -8714,9 +8714,9 @@ impl<'a> Parser<'a> { /// /// The arguments of the function are replaced in HIR lowering with the arguments created by /// this function and the statements created here are inserted at the top of the closure body. - fn construct_async_arguments(&mut self, asyncness: &mut Spanned, decl: &FnDecl) { + fn construct_async_arguments(&mut self, asyncness: &mut Spanned, decl: &mut FnDecl) { if let IsAsync::Async { ref mut arguments, .. } = asyncness.node { - for (index, input) in decl.inputs.iter().enumerate() { + for (index, input) in decl.inputs.iter_mut().enumerate() { let id = ast::DUMMY_NODE_ID; let span = input.pat.span; @@ -8728,8 +8728,10 @@ impl<'a> Parser<'a> { // `let = __argN;` statement, instead just adding a `let = ;` // statement. let (binding_mode, ident, is_simple_pattern) = match input.pat.node { - PatKind::Ident(binding_mode, ident, _) => (binding_mode, ident, true), - _ => (BindingMode::ByValue(Mutability::Immutable), ident, false), + PatKind::Ident(binding_mode @ BindingMode::ByValue(_), ident, _) => { + (binding_mode, ident, true) + } + _ => (BindingMode::ByValue(Mutability::Mutable), ident, false), }; // Construct an argument representing `__argN: ` to replace the argument of the @@ -8796,6 +8798,15 @@ impl<'a> Parser<'a> { }) }; + // Remove mutability from arguments. If this is not a simple pattern, + // those arguments are replaced by `__argN`, so there is no need to do this. + if let PatKind::Ident(BindingMode::ByValue(mutability @ Mutability::Mutable), ..) = + &mut input.pat.node + { + assert!(is_simple_pattern); + *mutability = Mutability::Immutable; + } + let move_stmt = Stmt { id, node: StmtKind::Local(P(move_local)), span }; arguments.push(AsyncArgument { ident, arg, pat_stmt, move_stmt }); } diff --git a/src/test/ui/async-await/argument-patterns.rs b/src/test/ui/async-await/argument-patterns.rs new file mode 100644 index 0000000000000..3750c2bcb701a --- /dev/null +++ b/src/test/ui/async-await/argument-patterns.rs @@ -0,0 +1,30 @@ +// edition:2018 +// run-pass + +#![allow(unused_variables)] +#![deny(unused_mut)] +#![feature(async_await)] + +type A = Vec; + +async fn a(n: u32, mut vec: A) { + vec.push(n); +} + +async fn b(n: u32, ref mut vec: A) { + vec.push(n); +} + +async fn c(ref vec: A) { + vec.contains(&0); +} + +async fn d((a, mut b): (A, A)) { + b.push(1); +} + +async fn f((ref mut a, ref b): (A, A)) {} + +async fn g(((ref a, ref mut b), (ref mut c, ref d)): ((A, A), (A, A))) {} + +fn main() {} diff --git a/src/test/ui/async-await/mutable-arguments.rs b/src/test/ui/async-await/mutable-arguments.rs deleted file mode 100644 index 4d6dba74097ca..0000000000000 --- a/src/test/ui/async-await/mutable-arguments.rs +++ /dev/null @@ -1,10 +0,0 @@ -// edition:2018 -// run-pass - -#![feature(async_await)] - -async fn foo(n: u32, mut vec: Vec) { - vec.push(n); -} - -fn main() {} From e6da57f3e713b8b3adef209940335a8f6bfa642f Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 30 Apr 2019 21:51:55 +0100 Subject: [PATCH 074/212] Fix argument alias handling for -O and -C opt-level --- src/librustc/session/config.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index ad80e5d74bd2a..b6d3ee882b36c 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -2181,10 +2181,15 @@ pub fn build_session_options_and_crate_config( TargetTriple::from_triple(host_triple()) }; let opt_level = { - if matches.opt_present("O") { - if cg.opt_level.is_some() { - early_error(error_format, "-O and -C opt-level both provided"); + let max_o = matches.opt_positions("O").into_iter().max(); + let max_c = matches.opt_strs_pos("C").into_iter().flat_map(|(i, s)| { + if let Some("opt-level") = s.splitn(2, '=').next() { + Some(i) + } else { + None } + }).max(); + if max_o > max_c { OptLevel::Default } else { match cg.opt_level.as_ref().map(String::as_ref) { From e8e43c9e16d78e6fe26f67ba1c4218427acc583a Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 30 Apr 2019 21:52:05 +0100 Subject: [PATCH 075/212] Fix argument alias handling for -g and -C debuginfo --- src/librustc/session/config.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index b6d3ee882b36c..8e223170894dd 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -2214,10 +2214,15 @@ pub fn build_session_options_and_crate_config( } }; let debug_assertions = cg.debug_assertions.unwrap_or(opt_level == OptLevel::No); - let debuginfo = if matches.opt_present("g") { - if cg.debuginfo.is_some() { - early_error(error_format, "-g and -C debuginfo both provided"); + let max_g = matches.opt_positions("g").into_iter().max(); + let max_c = matches.opt_strs_pos("C").into_iter().flat_map(|(i, s)| { + if let Some("debuginfo") = s.splitn(2, '=').next() { + Some(i) + } else { + None } + }).max(); + let debuginfo = if max_g > max_c { DebugInfo::Full } else { match cg.debuginfo { From 11b1d483b2f0e65e049c491c34a0f8573553f4b4 Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 30 Apr 2019 21:52:54 +0100 Subject: [PATCH 076/212] Add a run-make test for command aliases --- .../run-make/override-aliased-flags/Makefile | 22 +++++++++++++++++++ .../run-make/override-aliased-flags/main.rs | 1 + 2 files changed, 23 insertions(+) create mode 100644 src/test/run-make/override-aliased-flags/Makefile create mode 100644 src/test/run-make/override-aliased-flags/main.rs diff --git a/src/test/run-make/override-aliased-flags/Makefile b/src/test/run-make/override-aliased-flags/Makefile new file mode 100644 index 0000000000000..866060ad998be --- /dev/null +++ b/src/test/run-make/override-aliased-flags/Makefile @@ -0,0 +1,22 @@ +-include ../../run-make-fulldeps/tools.mk + +# FIXME: it would be good to check that it's actually the rightmost flags +# that are used when multiple flags are specified, but I can't think of a +# reliable way to check this. + +all: + # Test that `-O` and `-C opt-level` can be specified multiple times. + # The rightmost flag will be used over any previous flags. + $(RUSTC) -O -O main.rs + $(RUSTC) -O -C opt-level=0 main.rs + $(RUSTC) -C opt-level=0 -O main.rs + $(RUSTC) -C opt-level=0 -C opt-level=2 main.rs + $(RUSTC) -C opt-level=2 -C opt-level=0 main.rs + + # Test that `-g` and `-C debuginfo` can be specified multiple times. + # The rightmost flag will be used over any previous flags. + $(RUSTC) -g -g main.rs + $(RUSTC) -g -C debuginfo=0 main.rs + $(RUSTC) -C debuginfo=0 -g main.rs + $(RUSTC) -C debuginfo=0 -C debuginfo=2 main.rs + $(RUSTC) -C debuginfo=2 -C debuginfo=0 main.rs diff --git a/src/test/run-make/override-aliased-flags/main.rs b/src/test/run-make/override-aliased-flags/main.rs new file mode 100644 index 0000000000000..f328e4d9d04c3 --- /dev/null +++ b/src/test/run-make/override-aliased-flags/main.rs @@ -0,0 +1 @@ +fn main() {} From d54cf00c7712c174a6f7efe8d33ca94e2f943e5d Mon Sep 17 00:00:00 2001 From: varkor Date: Wed, 1 May 2019 23:23:35 +0100 Subject: [PATCH 077/212] Add comments --- src/librustc/session/config.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 8e223170894dd..084a5429f26fa 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -2181,6 +2181,12 @@ pub fn build_session_options_and_crate_config( TargetTriple::from_triple(host_triple()) }; let opt_level = { + // The `-O` and `-C opt-level` flags specify the same setting, so we want to be able + // to use them interchangeably. However, because they're technically different flags, + // we need to work out manually which should take precedence if both are supplied (i.e. + // the rightmost flag). We do this by finding the (rightmost) position of both flags and + // comparing them. Note that if a flag is not found, its position will be `None`, which + // always compared less than `Some(_)`. let max_o = matches.opt_positions("O").into_iter().max(); let max_c = matches.opt_strs_pos("C").into_iter().flat_map(|(i, s)| { if let Some("opt-level") = s.splitn(2, '=').next() { @@ -2213,6 +2219,9 @@ pub fn build_session_options_and_crate_config( } } }; + // The `-g` and `-C debuginfo` flags specify the same setting, so we want to be able + // to use them interchangeably. See the note above (regarding `-O` and `-C opt-level`) + // for more details. let debug_assertions = cg.debug_assertions.unwrap_or(opt_level == OptLevel::No); let max_g = matches.opt_positions("g").into_iter().max(); let max_c = matches.opt_strs_pos("C").into_iter().flat_map(|(i, s)| { From ecd046817b44b933e17940332bda845f854fb554 Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 2 May 2019 10:32:56 +0100 Subject: [PATCH 078/212] Update getopts to 0.2.19 --- src/bootstrap/Cargo.toml | 2 +- src/libtest/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 9a410c339bf5f..3151b56d8e84e 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -39,7 +39,7 @@ build_helper = { path = "../build_helper" } cmake = "0.1.38" filetime = "0.2" num_cpus = "1.0" -getopts = "0.2.18" +getopts = "0.2.19" cc = "1.0.35" libc = "0.2" serde = "1.0.8" diff --git a/src/libtest/Cargo.toml b/src/libtest/Cargo.toml index 2e836b6772fda..a72e4c7050289 100644 --- a/src/libtest/Cargo.toml +++ b/src/libtest/Cargo.toml @@ -10,7 +10,7 @@ path = "lib.rs" crate-type = ["dylib", "rlib"] [dependencies] -getopts = "0.2.18" +getopts = "0.2.19" term = { path = "../libterm" } # not actually used but needed to always have proc_macro in the sysroot From 12f63ecd29e234cd28e1bc94ddc518d01a518be5 Mon Sep 17 00:00:00 2001 From: varkor Date: Sat, 4 May 2019 14:53:22 +0100 Subject: [PATCH 079/212] Move run-make test to run-make-fulldeps --- .../override-aliased-flags/Makefile | 2 +- .../override-aliased-flags/main.rs | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/test/{run-make => run-make-fulldeps}/override-aliased-flags/Makefile (95%) rename src/test/{run-make => run-make-fulldeps}/override-aliased-flags/main.rs (100%) diff --git a/src/test/run-make/override-aliased-flags/Makefile b/src/test/run-make-fulldeps/override-aliased-flags/Makefile similarity index 95% rename from src/test/run-make/override-aliased-flags/Makefile rename to src/test/run-make-fulldeps/override-aliased-flags/Makefile index 866060ad998be..bea610eeb9fd1 100644 --- a/src/test/run-make/override-aliased-flags/Makefile +++ b/src/test/run-make-fulldeps/override-aliased-flags/Makefile @@ -1,4 +1,4 @@ --include ../../run-make-fulldeps/tools.mk +-include ../tools.mk # FIXME: it would be good to check that it's actually the rightmost flags # that are used when multiple flags are specified, but I can't think of a diff --git a/src/test/run-make/override-aliased-flags/main.rs b/src/test/run-make-fulldeps/override-aliased-flags/main.rs similarity index 100% rename from src/test/run-make/override-aliased-flags/main.rs rename to src/test/run-make-fulldeps/override-aliased-flags/main.rs From 80f54ba8811901ae8de1cc9971f2eab418c76fdd Mon Sep 17 00:00:00 2001 From: varkor Date: Sat, 4 May 2019 16:08:34 +0100 Subject: [PATCH 080/212] Update Cargo.lock --- Cargo.lock | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ffa33393c3025..c930b628f4b37 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -169,7 +169,7 @@ dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -463,7 +463,7 @@ dependencies = [ "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -484,7 +484,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -974,7 +974,7 @@ dependencies = [ [[package]] name = "getopts" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1989,7 +1989,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2008,7 +2008,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3095,7 +3095,7 @@ dependencies = [ "dirs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "ignore 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3522,7 +3522,7 @@ dependencies = [ name = "test" version = "0.0.0" dependencies = [ - "getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "proc_macro 0.0.0", "term 0.0.0", ] @@ -3532,7 +3532,7 @@ name = "tester" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4132,7 +4132,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "1a70b146671de62ec8c8ed572219ca5d594d9b06c0b364d5e67b722fc559b48c" "checksum fwdansi 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34dd4c507af68d37ffef962063dfa1944ce0dd4d5b82043dbab1dabe088610c3" "checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" -"checksum getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0a7292d30132fb5424b354f5dc02512a86e4c516fe544bb7a25e7f266951b797" +"checksum getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "72327b15c228bfe31f1390f93dd5e9279587f0463836393c9df719ce62a3e450" "checksum git2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7339329bfa14a00223244311560d11f8f489b453fb90092af97f267a6090ab0" "checksum git2-curl 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d58551e903ed7e2d6fe3a2f3c7efa3a784ec29b19d0fbb035aaf0497c183fbdd" "checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" From 57ec63c76c97028b6627289caec3c6a83cea92a7 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Mon, 6 May 2019 00:01:20 +0900 Subject: [PATCH 081/212] Add tests for by-ref binding --- ...-for-async-fn-parameters-by-ref-binding.rs | 271 ++++++++++++++++++ .../drop-order-locals-are-hidden.rs | 5 + .../drop-order-locals-are-hidden.stderr | 14 +- 3 files changed, 289 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/async-await/drop-order-for-async-fn-parameters-by-ref-binding.rs diff --git a/src/test/ui/async-await/drop-order-for-async-fn-parameters-by-ref-binding.rs b/src/test/ui/async-await/drop-order-for-async-fn-parameters-by-ref-binding.rs new file mode 100644 index 0000000000000..c2b59eecb9993 --- /dev/null +++ b/src/test/ui/async-await/drop-order-for-async-fn-parameters-by-ref-binding.rs @@ -0,0 +1,271 @@ +// aux-build:arc_wake.rs +// edition:2018 +// run-pass + +#![allow(unused_variables)] +#![feature(async_await, await_macro)] + +// Test that the drop order for parameters in a fn and async fn matches up. Also test that +// parameters (used or unused) are not dropped until the async fn completes execution. +// See also #54716. + +extern crate arc_wake; + +use arc_wake::ArcWake; +use std::cell::RefCell; +use std::future::Future; +use std::marker::PhantomData; +use std::sync::Arc; +use std::rc::Rc; +use std::task::Context; + +struct EmptyWaker; + +impl ArcWake for EmptyWaker { + fn wake(self: Arc) {} +} + +#[derive(Debug, Eq, PartialEq)] +enum DropOrder { + Function, + Val(&'static str), +} + +type DropOrderListPtr = Rc>>; + +struct D(&'static str, DropOrderListPtr); + +impl Drop for D { + fn drop(&mut self) { + self.1.borrow_mut().push(DropOrder::Val(self.0)); + } +} + +/// Check that unused bindings are dropped after the function is polled. +async fn foo_async(ref mut x: D, ref mut _y: D) { + x.1.borrow_mut().push(DropOrder::Function); +} + +fn foo_sync(ref mut x: D, ref mut _y: D) { + x.1.borrow_mut().push(DropOrder::Function); +} + +/// Check that underscore patterns are dropped after the function is polled. +async fn bar_async(ref mut x: D, _: D) { + x.1.borrow_mut().push(DropOrder::Function); +} + +fn bar_sync(ref mut x: D, _: D) { + x.1.borrow_mut().push(DropOrder::Function); +} + +/// Check that underscore patterns within more complex patterns are dropped after the function +/// is polled. +async fn baz_async((ref mut x, _): (D, D)) { + x.1.borrow_mut().push(DropOrder::Function); +} + +fn baz_sync((ref mut x, _): (D, D)) { + x.1.borrow_mut().push(DropOrder::Function); +} + +/// Check that underscore and unused bindings within and outwith more complex patterns are dropped +/// after the function is polled. +async fn foobar_async(ref mut x: D, (ref mut a, _, ref mut _c): (D, D, D), _: D, ref mut _y: D) { + x.1.borrow_mut().push(DropOrder::Function); +} + +fn foobar_sync(ref mut x: D, (ref mut a, _, ref mut _c): (D, D, D), _: D, ref mut _y: D) { + x.1.borrow_mut().push(DropOrder::Function); +} + +struct Foo; + +impl Foo { + /// Check that unused bindings are dropped after the method is polled. + async fn foo_async(ref mut x: D, ref mut _y: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn foo_sync(ref mut x: D, ref mut _y: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + /// Check that underscore patterns are dropped after the method is polled. + async fn bar_async(ref mut x: D, _: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn bar_sync(ref mut x: D, _: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + /// Check that underscore patterns within more complex patterns are dropped after the method + /// is polled. + async fn baz_async((ref mut x, _): (D, D)) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn baz_sync((ref mut x, _): (D, D)) { + x.1.borrow_mut().push(DropOrder::Function); + } + + /// Check that underscore and unused bindings within and outwith more complex patterns are + /// dropped after the method is polled. + async fn foobar_async( + ref mut x: D, (ref mut a, _, ref mut _c): (D, D, D), _: D, ref mut _y: D, + ) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn foobar_sync( + ref mut x: D, (ref mut a, _, ref mut _c): (D, D, D), _: D, ref mut _y: D, + ) { + x.1.borrow_mut().push(DropOrder::Function); + } +} + +struct Bar<'a>(PhantomData<&'a ()>); + +impl<'a> Bar<'a> { + /// Check that unused bindings are dropped after the method with self is polled. + async fn foo_async(&'a self, ref mut x: D, ref mut _y: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn foo_sync(&'a self, ref mut x: D, ref mut _y: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + /// Check that underscore patterns are dropped after the method with self is polled. + async fn bar_async(&'a self, ref mut x: D, _: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn bar_sync(&'a self, ref mut x: D, _: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + /// Check that underscore patterns within more complex patterns are dropped after the method + /// with self is polled. + async fn baz_async(&'a self, (ref mut x, _): (D, D)) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn baz_sync(&'a self, (ref mut x, _): (D, D)) { + x.1.borrow_mut().push(DropOrder::Function); + } + + /// Check that underscore and unused bindings within and outwith more complex patterns are + /// dropped after the method with self is polled. + async fn foobar_async( + &'a self, ref mut x: D, (ref mut a, _, ref mut _c): (D, D, D), _: D, ref mut _y: D, + ) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn foobar_sync( + &'a self, ref mut x: D, (ref mut a, _, ref mut _c): (D, D, D), _: D, ref mut _y: D, + ) { + x.1.borrow_mut().push(DropOrder::Function); + } +} + +fn assert_drop_order_after_poll>( + f: impl FnOnce(DropOrderListPtr) -> Fut, + g: impl FnOnce(DropOrderListPtr), +) { + let empty = Arc::new(EmptyWaker); + let waker = ArcWake::into_waker(empty); + let mut cx = Context::from_waker(&waker); + + let actual_order = Rc::new(RefCell::new(Vec::new())); + let mut fut = Box::pin(f(actual_order.clone())); + let _ = fut.as_mut().poll(&mut cx); + + let expected_order = Rc::new(RefCell::new(Vec::new())); + g(expected_order.clone()); + + assert_eq!(*actual_order.borrow(), *expected_order.borrow()); +} + +fn main() { + // Free functions (see doc comment on function for what it tests). + assert_drop_order_after_poll(|l| foo_async(D("x", l.clone()), D("_y", l.clone())), + |l| foo_sync(D("x", l.clone()), D("_y", l.clone()))); + assert_drop_order_after_poll(|l| bar_async(D("x", l.clone()), D("_", l.clone())), + |l| bar_sync(D("x", l.clone()), D("_", l.clone()))); + assert_drop_order_after_poll(|l| baz_async((D("x", l.clone()), D("_", l.clone()))), + |l| baz_sync((D("x", l.clone()), D("_", l.clone())))); + assert_drop_order_after_poll( + |l| { + foobar_async( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, + |l| { + foobar_sync( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, + ); + + // Methods w/out self (see doc comment on function for what it tests). + assert_drop_order_after_poll(|l| Foo::foo_async(D("x", l.clone()), D("_y", l.clone())), + |l| Foo::foo_sync(D("x", l.clone()), D("_y", l.clone()))); + assert_drop_order_after_poll(|l| Foo::bar_async(D("x", l.clone()), D("_", l.clone())), + |l| Foo::bar_sync(D("x", l.clone()), D("_", l.clone()))); + assert_drop_order_after_poll(|l| Foo::baz_async((D("x", l.clone()), D("_", l.clone()))), + |l| Foo::baz_sync((D("x", l.clone()), D("_", l.clone())))); + assert_drop_order_after_poll( + |l| { + Foo::foobar_async( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, + |l| { + Foo::foobar_sync( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, + ); + + // Methods (see doc comment on function for what it tests). + let b = Bar(Default::default()); + assert_drop_order_after_poll(|l| b.foo_async(D("x", l.clone()), D("_y", l.clone())), + |l| b.foo_sync(D("x", l.clone()), D("_y", l.clone()))); + assert_drop_order_after_poll(|l| b.bar_async(D("x", l.clone()), D("_", l.clone())), + |l| b.bar_sync(D("x", l.clone()), D("_", l.clone()))); + assert_drop_order_after_poll(|l| b.baz_async((D("x", l.clone()), D("_", l.clone()))), + |l| b.baz_sync((D("x", l.clone()), D("_", l.clone())))); + assert_drop_order_after_poll( + |l| { + b.foobar_async( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, + |l| { + b.foobar_sync( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, + ); +} diff --git a/src/test/ui/async-await/drop-order-locals-are-hidden.rs b/src/test/ui/async-await/drop-order-locals-are-hidden.rs index 10dc5e27f6f9f..bcdb8878eb5d2 100644 --- a/src/test/ui/async-await/drop-order-locals-are-hidden.rs +++ b/src/test/ui/async-await/drop-order-locals-are-hidden.rs @@ -8,4 +8,9 @@ async fn foobar_async(x: u32, (a, _, _c): (u32, u32, u32), _: u32, _y: u32) { assert_eq!(__arg2, 4); //~ ERROR cannot find value `__arg2` in this scope [E0425] } +async fn baz_async(ref mut x: u32, ref y: u32) { + assert_eq!(__arg0, 1); //~ ERROR cannot find value `__arg0` in this scope [E0425] + assert_eq!(__arg1, 2); //~ ERROR cannot find value `__arg1` in this scope [E0425] +} + fn main() {} diff --git a/src/test/ui/async-await/drop-order-locals-are-hidden.stderr b/src/test/ui/async-await/drop-order-locals-are-hidden.stderr index ca0da6b7c962a..484e1f4f4269e 100644 --- a/src/test/ui/async-await/drop-order-locals-are-hidden.stderr +++ b/src/test/ui/async-await/drop-order-locals-are-hidden.stderr @@ -10,6 +10,18 @@ error[E0425]: cannot find value `__arg2` in this scope LL | assert_eq!(__arg2, 4); | ^^^^^^ not found in this scope -error: aborting due to 2 previous errors +error[E0425]: cannot find value `__arg0` in this scope + --> $DIR/drop-order-locals-are-hidden.rs:12:16 + | +LL | assert_eq!(__arg0, 1); + | ^^^^^^ not found in this scope + +error[E0425]: cannot find value `__arg1` in this scope + --> $DIR/drop-order-locals-are-hidden.rs:13:16 + | +LL | assert_eq!(__arg1, 2); + | ^^^^^^ not found in this scope + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0425`. From 125dc60dabfdc70a92a757cff9d7d93a5e5376a7 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 4 May 2019 03:47:16 +0300 Subject: [PATCH 082/212] rustc: replace uses of with_freevars with the freevars query. --- src/librustc/middle/expr_use_visitor.rs | 6 +-- src/librustc/middle/liveness.rs | 13 ++++--- src/librustc/mir/mod.rs | 8 ++-- src/librustc/ty/mod.rs | 14 +------ src/librustc/ty/print/pretty.rs | 4 +- .../borrow_check/error_reporting.rs | 39 +++++++------------ src/librustc_mir/hair/cx/expr.rs | 11 +++--- src/librustc_passes/rvalue_promotion.rs | 3 +- src/librustc_typeck/check/coercion.rs | 3 +- src/librustc_typeck/check/upvar.rs | 16 ++++---- src/librustc_typeck/collect.rs | 6 +-- 11 files changed, 49 insertions(+), 74 deletions(-) diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index cf3f613b08eb5..9f24644d91292 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -931,8 +931,8 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { debug!("walk_captures({:?})", closure_expr); let closure_def_id = self.tcx().hir().local_def_id_from_hir_id(closure_expr.hir_id); - self.tcx().with_freevars(closure_expr.hir_id, |freevars| { - for freevar in freevars { + if let Some(freevars) = self.tcx().freevars(closure_def_id) { + for freevar in freevars.iter() { let var_hir_id = freevar.var_id(); let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { hir_id: var_hir_id }, @@ -960,7 +960,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } } } - }); + } } fn cat_captured_var(&mut self, diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 15736218a7923..b1d60dd3a55d3 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -483,16 +483,17 @@ fn visit_expr<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, expr: &'tcx Expr) { // in better error messages than just pointing at the closure // construction site. let mut call_caps = Vec::new(); - ir.tcx.with_freevars(expr.hir_id, |freevars| { - call_caps.extend(freevars.iter().filter_map(|fv| { - if let Res::Local(rv) = fv.res { - let fv_ln = ir.add_live_node(FreeVarNode(fv.span)); - Some(CaptureInfo { ln: fv_ln, var_hid: rv }) + let closure_def_id = ir.tcx.hir().local_def_id_from_hir_id(expr.hir_id); + if let Some(freevars) = ir.tcx.freevars(closure_def_id) { + call_caps.extend(freevars.iter().filter_map(|freevar| { + if let Res::Local(rv) = freevar.res { + let freevar_ln = ir.add_live_node(FreeVarNode(freevar.span)); + Some(CaptureInfo { ln: freevar_ln, var_hid: rv }) } else { None } })); - }); + } ir.set_captures(expr.hir_id, call_caps); intravisit::walk_expr(ir, expr); diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 09e2b523fae83..3b60d0af736c9 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2572,12 +2572,12 @@ impl<'tcx> Debug for Rvalue<'tcx> { }; let mut struct_fmt = fmt.debug_struct(&name); - tcx.with_freevars(hir_id, |freevars| { + if let Some(freevars) = tcx.freevars(def_id) { for (freevar, place) in freevars.iter().zip(places) { let var_name = tcx.hir().name_by_hir_id(freevar.var_id()); struct_fmt.field(&var_name.as_str(), place); } - }); + } struct_fmt.finish() } else { @@ -2591,12 +2591,12 @@ impl<'tcx> Debug for Rvalue<'tcx> { tcx.hir().span_by_hir_id(hir_id)); let mut struct_fmt = fmt.debug_struct(&name); - tcx.with_freevars(hir_id, |freevars| { + if let Some(freevars) = tcx.freevars(def_id) { for (freevar, place) in freevars.iter().zip(places) { let var_name = tcx.hir().name_by_hir_id(freevar.var_id()); struct_fmt.field(&var_name.as_str(), place); } - }); + } struct_fmt.finish() } else { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index feedf5741f65b..9d3c4b5fba5c1 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -9,7 +9,7 @@ pub use self::IntVarValue::*; pub use self::fold::TypeFoldable; use crate::hir::{map as hir_map, FreevarMap, GlobMap, TraitMap}; -use crate::hir::{HirId, Node}; +use crate::hir::Node; use crate::hir::def::{Res, DefKind, CtorOf, CtorKind, ExportMap}; use crate::hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_data_structures::svh::Svh; @@ -3120,18 +3120,6 @@ impl Iterator for AssociatedItemsIterator<'_, '_, '_> { } } -impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { - pub fn with_freevars(self, fid: HirId, f: F) -> T where - F: FnOnce(&[hir::Freevar]) -> T, - { - let def_id = self.hir().local_def_id_from_hir_id(fid); - match self.freevars(def_id) { - None => f(&[]), - Some(d) => f(&d), - } - } -} - fn associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> AssociatedItem { let id = tcx.hir().as_local_hir_id(def_id).unwrap(); let parent_id = tcx.hir().get_parent_item(id); diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index e09dcd16bd3dc..f131f19379156 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -584,7 +584,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: let mut sep = " "; for (freevar, upvar_ty) in self.tcx().freevars(did) .as_ref() - .map_or(&[][..], |fv| &fv[..]) + .map_or(&[][..], |v| &v[..]) .iter() .zip(upvar_tys) { @@ -627,7 +627,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: let mut sep = " "; for (freevar, upvar_ty) in self.tcx().freevars(did) .as_ref() - .map_or(&[][..], |fv| &fv[..]) + .map_or(&[][..], |v| &v[..]) .iter() .zip(upvar_tys) { diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index ed42326d7d520..64b32114ebc62 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -1814,14 +1814,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ty::Array(ty, _) | ty::Slice(ty) => self.describe_field_from_ty(&ty, field, variant_index), ty::Closure(def_id, _) | ty::Generator(def_id, _, _) => { - // Convert the def-id into a node-id. node-ids are only valid for - // the local code in the current crate, so this returns an `Option` in case + // `tcx.freevars(def_id)` returns an `Option`, which is `None` in case // the closure comes from another crate. But in that case we wouldn't // be borrowck'ing it, so we can just unwrap: - let hir_id = self.infcx.tcx.hir().as_local_hir_id(def_id).unwrap(); - let freevar = self.infcx - .tcx - .with_freevars(hir_id, |fv| fv[field.index()]); + let freevar = self.infcx.tcx.freevars(def_id).unwrap()[field.index()]; self.infcx.tcx.hir().name_by_hir_id(freevar.var_id()).to_string() } @@ -2613,28 +2609,19 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { if let hir::ExprKind::Closure( .., args_span, _ ) = expr { - let var_span = self.infcx.tcx.with_freevars( - hir_id, - |freevars| { - for (v, place) in freevars.iter().zip(places) { - match place { - Operand::Copy(place) | - Operand::Move(place) if target_place == place => { - debug!("closure_span: found captured local {:?}", place); - return Some(v.span); - }, - _ => {} - } - } - - None - }, - )?; + for (v, place) in self.infcx.tcx.freevars(def_id)?.iter().zip(places) { + match place { + Operand::Copy(place) | + Operand::Move(place) if target_place == place => { + debug!("closure_span: found captured local {:?}", place); + return Some((*args_span, v.span)); + }, + _ => {} + } + } - Some((*args_span, var_span)) - } else { - None } + None } /// Helper to retrieve span(s) of given borrow from the current MIR diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 5ac1ccd8fade2..07557421779b4 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -516,12 +516,11 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, span_bug!(expr.span, "closure expr w/o closure type: {:?}", closure_ty); } }; - let upvars = cx.tcx.with_freevars(expr.hir_id, |freevars| { - freevars.iter() - .zip(substs.upvar_tys(def_id, cx.tcx)) - .map(|(fv, ty)| capture_freevar(cx, expr, fv, ty)) - .collect() - }); + let upvars = cx.tcx.freevars(def_id).iter() + .flat_map(|freevars| freevars.iter()) + .zip(substs.upvar_tys(def_id, cx.tcx)) + .map(|(freevar, ty)| capture_freevar(cx, expr, freevar, ty)) + .collect(); ExprKind::Closure { closure_id: def_id, substs, diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index b6e2aacd55954..642144c32439b 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -449,7 +449,8 @@ fn check_expr_kind<'a, 'tcx>( let nested_body_promotable = v.check_nested_body(body_id); // Paths in constant contexts cannot refer to local variables, // as there are none, and thus closures can't have upvars there. - if v.tcx.with_freevars(e.hir_id, |fv| !fv.is_empty()) { + let closure_def_id = v.tcx.hir().local_def_id_from_hir_id(e.hir_id); + if !v.tcx.freevars(closure_def_id).map_or(true, |v| v.is_empty()) { NotPromotable } else { nested_body_promotable diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 85eb0f9d49966..9f3a9de92cc71 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -721,9 +721,8 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { let b = self.shallow_resolve(b); - let hir_id_a = self.tcx.hir().as_local_hir_id(def_id_a).unwrap(); match b.sty { - ty::FnPtr(fn_ty) if self.tcx.with_freevars(hir_id_a, |v| v.is_empty()) => { + ty::FnPtr(fn_ty) if self.tcx.freevars(def_id_a).map_or(true, |v| v.is_empty()) => { // We coerce the closure, which has fn type // `extern "rust-call" fn((arg0,arg1,...)) -> _` // to diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index dc66c6c93d0e0..9cdfcad37212c 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -121,9 +121,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { None }; - self.tcx.with_freevars(closure_hir_id, |freevars| { + if let Some(freevars) = self.tcx.freevars(closure_def_id) { let mut freevar_list: Vec = Vec::with_capacity(freevars.len()); - for freevar in freevars { + for freevar in freevars.iter() { let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { hir_id: freevar.var_id(), @@ -155,14 +155,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } // Add the vector of freevars to the map keyed with the closure id. // This gives us an easier access to them without having to call - // with_freevars again.. + // tcx.freevars again.. if !freevar_list.is_empty() { self.tables .borrow_mut() .upvar_list .insert(closure_def_id, freevar_list); } - }); + } let body_owner_def_id = self.tcx.hir().body_owner_def_id(body.id()); let region_scope_tree = &self.tcx.region_scope_tree(body_owner_def_id); @@ -244,9 +244,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // This may change if abstract return types of some sort are // implemented. let tcx = self.tcx; - let closure_def_index = tcx.hir().local_def_id_from_hir_id(closure_id); + let closure_def_id = tcx.hir().local_def_id_from_hir_id(closure_id); - tcx.with_freevars(closure_id, |freevars| { + tcx.freevars(closure_def_id).iter().flat_map(|freevars| { freevars .iter() .map(|freevar| { @@ -254,7 +254,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let freevar_ty = self.node_ty(var_hir_id); let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { hir_id: var_hir_id }, - closure_expr_id: LocalDefId::from_def_id(closure_def_index), + closure_expr_id: LocalDefId::from_def_id(closure_def_id), }; let capture = self.tables.borrow().upvar_capture(upvar_id); @@ -274,8 +274,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ), } }) - .collect() }) + .collect() } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index ed8ac89912c12..a40012a4a7932 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1093,8 +1093,8 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty }), ); - tcx.with_freevars(hir_id, |fv| { - params.extend(fv.iter().zip((dummy_args.len() as u32)..).map(|(_, i)| { + if let Some(freevars) = tcx.freevars(def_id) { + params.extend(freevars.iter().zip((dummy_args.len() as u32)..).map(|(_, i)| { ty::GenericParamDef { index: type_start + i, name: Symbol::intern("").as_interned_str(), @@ -1107,7 +1107,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty }, } })); - }); + } } let param_def_id_to_index = params From 8d9f4a128c4cfb15cf61a5c4b87a042d496d11cf Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 4 May 2019 03:57:46 +0300 Subject: [PATCH 083/212] rustc: rename all occurences of "freevar" to "upvar". --- src/librustc/hir/def.rs | 2 +- src/librustc/hir/mod.rs | 16 ++++---- src/librustc/infer/error_reporting/note.rs | 4 +- src/librustc/infer/mod.rs | 6 +-- src/librustc/middle/expr_use_visitor.rs | 14 +++---- src/librustc/middle/liveness.rs | 16 ++++---- src/librustc/mir/mod.rs | 12 +++--- src/librustc/query/mod.rs | 2 +- src/librustc/ty/context.rs | 8 ++-- src/librustc/ty/mod.rs | 4 +- src/librustc/ty/print/pretty.rs | 8 ++-- src/librustc_interface/passes.rs | 4 +- .../borrow_check/error_reporting.rs | 8 ++-- src/librustc_mir/hair/cx/expr.rs | 18 ++++----- src/librustc_mir/interpret/validity.rs | 2 +- src/librustc_passes/rvalue_promotion.rs | 2 +- src/librustc_resolve/lib.rs | 16 ++++---- src/librustc_typeck/check/coercion.rs | 2 +- src/librustc_typeck/check/upvar.rs | 40 +++++++++---------- src/librustc_typeck/collect.rs | 4 +- 20 files changed, 94 insertions(+), 94 deletions(-) diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index 0719eb701a984..91256385232a9 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -140,7 +140,7 @@ pub enum Res { SelfCtor(DefId /* impl */), // `DefId` refers to the impl Local(Id), Upvar(Id, // `HirId` of closed over local - usize, // index in the `freevars` list of the closure + usize, // index in the `upvars` list of the closure ast::NodeId), // expr node that creates the closure // Macro namespace diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 3a98c4ea06121..1e357e1341710 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -2476,19 +2476,19 @@ impl ForeignItemKind { } } -/// A free variable referred to in a function. +/// A variable captured by a closure. #[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)] -pub struct Freevar { - /// The variable being accessed free. +pub struct Upvar { + /// The variable being captured. pub res: Res, // First span where it is accessed (there can be multiple). pub span: Span } -impl Freevar { - pub fn map_id(self, map: impl FnMut(Id) -> R) -> Freevar { - Freevar { +impl Upvar { + pub fn map_id(self, map: impl FnMut(Id) -> R) -> Upvar { + Upvar { res: self.res.map_id(map), span: self.span, } @@ -2497,12 +2497,12 @@ impl Freevar { pub fn var_id(&self) -> Id { match self.res { Res::Local(id) | Res::Upvar(id, ..) => id, - _ => bug!("Freevar::var_id: bad res ({:?})", self.res) + _ => bug!("Upvar::var_id: bad res ({:?})", self.res) } } } -pub type FreevarMap = NodeMap>>; +pub type UpvarMap = NodeMap>>; pub type CaptureModeMap = NodeMap; diff --git a/src/librustc/infer/error_reporting/note.rs b/src/librustc/infer/error_reporting/note.rs index c05c6567bbefa..9eb46aa3779d9 100644 --- a/src/librustc/infer/error_reporting/note.rs +++ b/src/librustc/infer/error_reporting/note.rs @@ -46,7 +46,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { err.span_note(span, "...so that pointer is not dereferenced outside its lifetime"); } - infer::FreeVariable(span, id) => { + infer::ClosureCapture(span, id) => { err.span_note(span, &format!("...so that captured variable `{}` does not outlive the \ enclosing closure", @@ -214,7 +214,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { "the reference is only valid for ", sup, ""); err } - infer::FreeVariable(span, id) => { + infer::ClosureCapture(span, id) => { let mut err = struct_span_err!(self.tcx.sess, span, E0474, diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 2044e5ddae90e..5846e604cfc09 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -264,8 +264,8 @@ pub enum SubregionOrigin<'tcx> { /// Dereference of reference must be within its lifetime DerefPointer(Span), - /// Closure bound must not outlive captured free variables - FreeVariable(Span, ast::NodeId), + /// Closure bound must not outlive captured variables + ClosureCapture(Span, ast::NodeId), /// Index into slice must be within its lifetime IndexSlice(Span), @@ -1660,7 +1660,7 @@ impl<'tcx> SubregionOrigin<'tcx> { InfStackClosure(a) => a, InvokeClosure(a) => a, DerefPointer(a) => a, - FreeVariable(a, _) => a, + ClosureCapture(a, _) => a, IndexSlice(a) => a, RelateObjectBound(a) => a, RelateParamBound(a, _) => a, diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 9f24644d91292..93ba4241c4725 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -931,9 +931,9 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { debug!("walk_captures({:?})", closure_expr); let closure_def_id = self.tcx().hir().local_def_id_from_hir_id(closure_expr.hir_id); - if let Some(freevars) = self.tcx().freevars(closure_def_id) { - for freevar in freevars.iter() { - let var_hir_id = freevar.var_id(); + if let Some(upvars) = self.tcx().upvars(closure_def_id) { + for upvar in upvars.iter() { + let var_hir_id = upvar.var_id(); let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { hir_id: var_hir_id }, closure_expr_id: closure_def_id.to_local(), @@ -941,14 +941,14 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { let upvar_capture = self.mc.tables.upvar_capture(upvar_id); let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.hir_id, fn_decl_span, - freevar)); + upvar)); match upvar_capture { ty::UpvarCapture::ByValue => { let mode = copy_or_move(&self.mc, self.param_env, &cmt_var, CaptureMove); - self.delegate.consume(closure_expr.hir_id, freevar.span, &cmt_var, mode); + self.delegate.consume(closure_expr.hir_id, upvar.span, &cmt_var, mode); } ty::UpvarCapture::ByRef(upvar_borrow) => { self.delegate.borrow(closure_expr.hir_id, @@ -956,7 +956,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { &cmt_var, upvar_borrow.region, upvar_borrow.kind, - ClosureCapture(freevar.span)); + ClosureCapture(upvar.span)); } } } @@ -966,7 +966,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { fn cat_captured_var(&mut self, closure_hir_id: hir::HirId, closure_span: Span, - upvar: &hir::Freevar) + upvar: &hir::Upvar) -> mc::McResult> { // Create the cmt for the variable being borrowed, from the // caller's perspective diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index b1d60dd3a55d3..4b458e474b299 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -144,7 +144,7 @@ impl LiveNode { #[derive(Copy, Clone, PartialEq, Debug)] enum LiveNodeKind { - FreeVarNode(Span), + UpvarNode(Span), ExprNode(Span), VarDefNode(Span), ExitNode @@ -153,8 +153,8 @@ enum LiveNodeKind { fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt<'_, '_, '_>) -> String { let cm = tcx.sess.source_map(); match lnk { - FreeVarNode(s) => { - format!("Free var node [{}]", cm.span_to_string(s)) + UpvarNode(s) => { + format!("Upvar node [{}]", cm.span_to_string(s)) } ExprNode(s) => { format!("Expr node [{}]", cm.span_to_string(s)) @@ -484,11 +484,11 @@ fn visit_expr<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, expr: &'tcx Expr) { // construction site. let mut call_caps = Vec::new(); let closure_def_id = ir.tcx.hir().local_def_id_from_hir_id(expr.hir_id); - if let Some(freevars) = ir.tcx.freevars(closure_def_id) { - call_caps.extend(freevars.iter().filter_map(|freevar| { - if let Res::Local(rv) = freevar.res { - let freevar_ln = ir.add_live_node(FreeVarNode(freevar.span)); - Some(CaptureInfo { ln: freevar_ln, var_hid: rv }) + if let Some(upvars) = ir.tcx.upvars(closure_def_id) { + call_caps.extend(upvars.iter().filter_map(|upvar| { + if let Res::Local(rv) = upvar.res { + let upvar_ln = ir.add_live_node(UpvarNode(upvar.span)); + Some(CaptureInfo { ln: upvar_ln, var_hid: rv }) } else { None } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 3b60d0af736c9..bd67aabfe8e5f 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2572,9 +2572,9 @@ impl<'tcx> Debug for Rvalue<'tcx> { }; let mut struct_fmt = fmt.debug_struct(&name); - if let Some(freevars) = tcx.freevars(def_id) { - for (freevar, place) in freevars.iter().zip(places) { - let var_name = tcx.hir().name_by_hir_id(freevar.var_id()); + if let Some(upvars) = tcx.upvars(def_id) { + for (upvar, place) in upvars.iter().zip(places) { + let var_name = tcx.hir().name_by_hir_id(upvar.var_id()); struct_fmt.field(&var_name.as_str(), place); } } @@ -2591,9 +2591,9 @@ impl<'tcx> Debug for Rvalue<'tcx> { tcx.hir().span_by_hir_id(hir_id)); let mut struct_fmt = fmt.debug_struct(&name); - if let Some(freevars) = tcx.freevars(def_id) { - for (freevar, place) in freevars.iter().zip(places) { - let var_name = tcx.hir().name_by_hir_id(freevar.var_id()); + if let Some(upvars) = tcx.upvars(def_id) { + for (upvar, place) in upvars.iter().zip(places) { + let var_name = tcx.hir().name_by_hir_id(upvar.var_id()); struct_fmt.field(&var_name.as_str(), place); } } diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index e1e115cfe177b..0e7b66b744499 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -824,7 +824,7 @@ rustc_queries! { desc { "generating a postorder list of CrateNums" } } - query freevars(_: DefId) -> Option>> { + query upvars(_: DefId) -> Option>> { eval_always } query maybe_unused_trait_import(_: DefId) -> bool { diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index fddae02409126..19440d0bc64ea 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1071,10 +1071,10 @@ pub struct GlobalCtxt<'tcx> { pub queries: query::Queries<'tcx>, - // Records the free variables referenced by every closure + // Records the captured variables referenced by every closure // expression. Do not track deps for this, just recompute it from // scratch every time. - freevars: FxHashMap>>, + upvars: FxHashMap>>, maybe_unused_trait_imports: FxHashSet, maybe_unused_extern_crates: Vec<(DefId, Span)>, @@ -1317,7 +1317,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { }).collect(); (k, Lrc::new(exports)) }).collect(), - freevars: resolutions.freevars.into_iter().map(|(k, v)| { + upvars: resolutions.upvars.into_iter().map(|(k, v)| { let vars: Vec<_> = v.into_iter().map(|e| { e.map_id(|id| hir.node_to_hir_id(id)) }).collect(); @@ -3055,7 +3055,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { assert_eq!(id, LOCAL_CRATE); Lrc::new(middle::lang_items::collect(tcx)) }; - providers.freevars = |tcx, id| tcx.gcx.freevars.get(&id).cloned(); + providers.upvars = |tcx, id| tcx.gcx.upvars.get(&id).cloned(); providers.maybe_unused_trait_import = |tcx, id| { tcx.maybe_unused_trait_imports.contains(&id) }; diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 9d3c4b5fba5c1..cb92e4b7470a5 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -8,7 +8,7 @@ pub use self::BorrowKind::*; pub use self::IntVarValue::*; pub use self::fold::TypeFoldable; -use crate::hir::{map as hir_map, FreevarMap, GlobMap, TraitMap}; +use crate::hir::{map as hir_map, UpvarMap, GlobMap, TraitMap}; use crate::hir::Node; use crate::hir::def::{Res, DefKind, CtorOf, CtorKind, ExportMap}; use crate::hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; @@ -122,7 +122,7 @@ mod sty; #[derive(Clone)] pub struct Resolutions { - pub freevars: FreevarMap, + pub upvars: UpvarMap, pub trait_map: TraitMap, pub maybe_unused_trait_imports: NodeSet, pub maybe_unused_extern_crates: Vec<(NodeId, Span)>, diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index f131f19379156..8e98d4d85b9cc 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -582,7 +582,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: if let Some(hir_id) = self.tcx().hir().as_local_hir_id(did) { p!(write("@{:?}", self.tcx().hir().span_by_hir_id(hir_id))); let mut sep = " "; - for (freevar, upvar_ty) in self.tcx().freevars(did) + for (upvar, upvar_ty) in self.tcx().upvars(did) .as_ref() .map_or(&[][..], |v| &v[..]) .iter() @@ -591,7 +591,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: p!( write("{}{}:", sep, - self.tcx().hir().name_by_hir_id(freevar.var_id())), + self.tcx().hir().name_by_hir_id(upvar.var_id())), print(upvar_ty)); sep = ", "; } @@ -625,7 +625,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: p!(write("@{:?}", self.tcx().hir().span_by_hir_id(hir_id))); } let mut sep = " "; - for (freevar, upvar_ty) in self.tcx().freevars(did) + for (upvar, upvar_ty) in self.tcx().upvars(did) .as_ref() .map_or(&[][..], |v| &v[..]) .iter() @@ -634,7 +634,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: p!( write("{}{}:", sep, - self.tcx().hir().name_by_hir_id(freevar.var_id())), + self.tcx().hir().name_by_hir_id(upvar.var_id())), print(upvar_ty)); sep = ", "; } diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 6d3115c621343..8543cca1dd545 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -180,7 +180,7 @@ impl ExpansionResult { ExpansionResult { defs: Steal::new(resolver.definitions), resolutions: Steal::new(Resolutions { - freevars: resolver.freevars, + upvars: resolver.upvars, export_map: resolver.export_map, trait_map: resolver.trait_map, glob_map: resolver.glob_map, @@ -199,7 +199,7 @@ impl ExpansionResult { ExpansionResult { defs: Steal::new(resolver.definitions.clone()), resolutions: Steal::new(Resolutions { - freevars: resolver.freevars.clone(), + upvars: resolver.upvars.clone(), export_map: resolver.export_map.clone(), trait_map: resolver.trait_map.clone(), glob_map: resolver.glob_map.clone(), diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 64b32114ebc62..8aa6456ebe77b 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -1814,12 +1814,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ty::Array(ty, _) | ty::Slice(ty) => self.describe_field_from_ty(&ty, field, variant_index), ty::Closure(def_id, _) | ty::Generator(def_id, _, _) => { - // `tcx.freevars(def_id)` returns an `Option`, which is `None` in case + // `tcx.upvars(def_id)` returns an `Option`, which is `None` in case // the closure comes from another crate. But in that case we wouldn't // be borrowck'ing it, so we can just unwrap: - let freevar = self.infcx.tcx.freevars(def_id).unwrap()[field.index()]; + let upvar = self.infcx.tcx.upvars(def_id).unwrap()[field.index()]; - self.infcx.tcx.hir().name_by_hir_id(freevar.var_id()).to_string() + self.infcx.tcx.hir().name_by_hir_id(upvar.var_id()).to_string() } _ => { // Might need a revision when the fields in trait RFC is implemented @@ -2609,7 +2609,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { if let hir::ExprKind::Closure( .., args_span, _ ) = expr { - for (v, place) in self.infcx.tcx.freevars(def_id)?.iter().zip(places) { + for (v, place) in self.infcx.tcx.upvars(def_id)?.iter().zip(places) { match place { Operand::Copy(place) | Operand::Move(place) if target_place == place => { diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 07557421779b4..5e646a49e0e42 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -516,10 +516,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, span_bug!(expr.span, "closure expr w/o closure type: {:?}", closure_ty); } }; - let upvars = cx.tcx.freevars(def_id).iter() - .flat_map(|freevars| freevars.iter()) + let upvars = cx.tcx.upvars(def_id).iter() + .flat_map(|upvars| upvars.iter()) .zip(substs.upvar_tys(def_id, cx.tcx)) - .map(|(freevar, ty)| capture_freevar(cx, expr, freevar, ty)) + .map(|(upvar, ty)| capture_upvar(cx, expr, upvar, ty)) .collect(); ExprKind::Closure { closure_id: def_id, @@ -1184,12 +1184,12 @@ fn overloaded_place<'a, 'gcx, 'tcx>( ExprKind::Deref { arg: ref_expr.to_ref() } } -fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, +fn capture_upvar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, closure_expr: &'tcx hir::Expr, - freevar: &hir::Freevar, - freevar_ty: Ty<'tcx>) + upvar: &hir::Upvar, + upvar_ty: Ty<'tcx>) -> ExprRef<'tcx> { - let var_hir_id = freevar.var_id(); + let var_hir_id = upvar.var_id(); let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { hir_id: var_hir_id }, closure_expr_id: cx.tcx.hir().local_def_id_from_hir_id(closure_expr.hir_id).to_local(), @@ -1201,7 +1201,7 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, temp_lifetime, ty: var_ty, span: closure_expr.span, - kind: convert_var(cx, closure_expr, freevar.res), + kind: convert_var(cx, closure_expr, upvar.res), }; match upvar_capture { ty::UpvarCapture::ByValue => captured_var.to_ref(), @@ -1213,7 +1213,7 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, }; Expr { temp_lifetime, - ty: freevar_ty, + ty: upvar_ty, span: closure_expr.span, kind: ExprKind::Borrow { borrow_kind, diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index bd6f005e8736c..3bc6ec0564c60 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -170,7 +170,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> ValidityVisitor<'rt, 'a, ' if def_id.is_local() { let tables = self.ecx.tcx.typeck_tables_of(def_id); if let Some(upvars) = tables.upvar_list.get(&def_id) { - // Sometimes the index is beyond the number of freevars (seen + // Sometimes the index is beyond the number of upvars (seen // for a generator). if let Some(upvar_id) = upvars.get(field) { let var_hir_id = upvar_id.var_path.hir_id; diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index 642144c32439b..0f651fafcd2ac 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -450,7 +450,7 @@ fn check_expr_kind<'a, 'tcx>( // Paths in constant contexts cannot refer to local variables, // as there are none, and thus closures can't have upvars there. let closure_def_id = v.tcx.hir().local_def_id_from_hir_id(e.hir_id); - if !v.tcx.freevars(closure_def_id).map_or(true, |v| v.is_empty()) { + if !v.tcx.upvars(closure_def_id).map_or(true, |v| v.is_empty()) { NotPromotable } else { nested_body_promotable diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index a2d30de9da117..f8f6e5b1cd012 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -29,7 +29,7 @@ use rustc::hir::def::{ }; use rustc::hir::def::Namespace::*; use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; -use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap}; +use rustc::hir::{Upvar, UpvarMap, TraitCandidate, TraitMap, GlobMap}; use rustc::ty::{self, DefIdTree}; use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap}; use rustc::{bug, span_bug}; @@ -1668,8 +1668,8 @@ pub struct Resolver<'a> { /// Resolutions for labels (node IDs of their corresponding blocks or loops). label_res_map: NodeMap, - pub freevars: FreevarMap, - freevars_seen: NodeMap>, + pub upvars: UpvarMap, + upvars_seen: NodeMap>, pub export_map: ExportMap, pub trait_map: TraitMap, @@ -2033,8 +2033,8 @@ impl<'a> Resolver<'a> { partial_res_map: Default::default(), import_res_map: Default::default(), label_res_map: Default::default(), - freevars: Default::default(), - freevars_seen: Default::default(), + upvars: Default::default(), + upvars_seen: Default::default(), export_map: FxHashMap::default(), trait_map: Default::default(), module_map, @@ -4054,21 +4054,21 @@ impl<'a> Resolver<'a> { ClosureRibKind(function_id) => { let prev_res = res; - let seen = self.freevars_seen + let seen = self.upvars_seen .entry(function_id) .or_default(); if let Some(&index) = seen.get(&node_id) { res = Res::Upvar(node_id, index, function_id); continue; } - let vec = self.freevars + let vec = self.upvars .entry(function_id) .or_default(); let depth = vec.len(); res = Res::Upvar(node_id, depth, function_id); if record_used { - vec.push(Freevar { + vec.push(Upvar { res: prev_res, span, }); diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 9f3a9de92cc71..d21ceb983f8f4 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -722,7 +722,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { let b = self.shallow_resolve(b); match b.sty { - ty::FnPtr(fn_ty) if self.tcx.freevars(def_id_a).map_or(true, |v| v.is_empty()) => { + ty::FnPtr(fn_ty) if self.tcx.upvars(def_id_a).map_or(true, |v| v.is_empty()) => { // We coerce the closure, which has fn type // `extern "rust-call" fn((arg0,arg1,...)) -> _` // to diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 9cdfcad37212c..c3861f964e453 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -121,28 +121,28 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { None }; - if let Some(freevars) = self.tcx.freevars(closure_def_id) { - let mut freevar_list: Vec = Vec::with_capacity(freevars.len()); - for freevar in freevars.iter() { + if let Some(upvars) = self.tcx.upvars(closure_def_id) { + let mut upvar_list: Vec = Vec::with_capacity(upvars.len()); + for upvar in upvars.iter() { let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { - hir_id: freevar.var_id(), + hir_id: upvar.var_id(), }, closure_expr_id: LocalDefId::from_def_id(closure_def_id), }; debug!("seed upvar_id {:?}", upvar_id); // Adding the upvar Id to the list of Upvars, which will be added // to the map for the closure at the end of the for loop. - freevar_list.push(upvar_id); + upvar_list.push(upvar_id); let capture_kind = match capture_clause { hir::CaptureByValue => ty::UpvarCapture::ByValue, hir::CaptureByRef => { let origin = UpvarRegion(upvar_id, span); - let freevar_region = self.next_region_var(origin); + let upvar_region = self.next_region_var(origin); let upvar_borrow = ty::UpvarBorrow { kind: ty::ImmBorrow, - region: freevar_region, + region: upvar_region, }; ty::UpvarCapture::ByRef(upvar_borrow) } @@ -153,14 +153,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { .upvar_capture_map .insert(upvar_id, capture_kind); } - // Add the vector of freevars to the map keyed with the closure id. + // Add the vector of upvars to the map keyed with the closure id. // This gives us an easier access to them without having to call - // tcx.freevars again.. - if !freevar_list.is_empty() { + // tcx.upvars again.. + if !upvar_list.is_empty() { self.tables .borrow_mut() .upvar_list - .insert(closure_def_id, freevar_list); + .insert(closure_def_id, upvar_list); } } @@ -246,12 +246,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let tcx = self.tcx; let closure_def_id = tcx.hir().local_def_id_from_hir_id(closure_id); - tcx.freevars(closure_def_id).iter().flat_map(|freevars| { - freevars + tcx.upvars(closure_def_id).iter().flat_map(|upvars| { + upvars .iter() - .map(|freevar| { - let var_hir_id = freevar.var_id(); - let freevar_ty = self.node_ty(var_hir_id); + .map(|upvar| { + let var_hir_id = upvar.var_id(); + let upvar_ty = self.node_ty(var_hir_id); let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { hir_id: var_hir_id }, closure_expr_id: LocalDefId::from_def_id(closure_def_id), @@ -259,16 +259,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let capture = self.tables.borrow().upvar_capture(upvar_id); debug!( - "var_id={:?} freevar_ty={:?} capture={:?}", - var_hir_id, freevar_ty, capture + "var_id={:?} upvar_ty={:?} capture={:?}", + var_hir_id, upvar_ty, capture ); match capture { - ty::UpvarCapture::ByValue => freevar_ty, + ty::UpvarCapture::ByValue => upvar_ty, ty::UpvarCapture::ByRef(borrow) => tcx.mk_ref( borrow.region, ty::TypeAndMut { - ty: freevar_ty, + ty: upvar_ty, mutbl: borrow.kind.to_mutbl_lossy(), }, ), diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index a40012a4a7932..4185999fdd6d7 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1093,8 +1093,8 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty }), ); - if let Some(freevars) = tcx.freevars(def_id) { - params.extend(freevars.iter().zip((dummy_args.len() as u32)..).map(|(_, i)| { + if let Some(upvars) = tcx.upvars(def_id) { + params.extend(upvars.iter().zip((dummy_args.len() as u32)..).map(|(_, i)| { ty::GenericParamDef { index: type_start + i, name: Symbol::intern("").as_interned_str(), From 91e0c253ed03f9ad58573f85553e635d8d9d69a7 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 5 May 2019 12:06:59 -0600 Subject: [PATCH 084/212] Update mailmap to proper syntax Also updates my entry to the proper name --- .mailmap | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.mailmap b/.mailmap index 120d1f1457e65..679e9d79847c2 100644 --- a/.mailmap +++ b/.mailmap @@ -53,7 +53,8 @@ Chris C Cerami Chris C Cerami Chris Thorn Chris Thorn Chris Vittal Christopher Vittal -Christian Poveda +Christian Poveda +Christian Poveda Clark Gaebel Clinton Ryan Corey Richardson Elaine "See More" Nemo @@ -79,7 +80,9 @@ Eric Holk Eric Holmes Eric Reed Erick Tryzelaar -Esteban Küber +Esteban Küber +Esteban Küber +Esteban Küber Evgeny Sologubov Falco Hirschenberger Felix S. Klock II Felix S Klock II @@ -146,7 +149,7 @@ NAKASHIMA, Makoto NAKASHIMA, Makoto Marcell Pardavi Margaret Meyerhofer -Mark Simulacrum +Mark Rousskov Mark Sinclair Mark Sinclair =Mark Sinclair <=125axel125@gmail.com> Markus Westerlind Markus @@ -226,7 +229,7 @@ Tim Joseph Dumol Torsten Weber Ty Overby Ulrik Sverdrup bluss -Ulrik Sverdrup bluss bluss +Ulrik Sverdrup bluss Ulrik Sverdrup Ulrik Sverdrup Vadim Petrochenkov Vadim Petrochenkov petrochenkov From 968eb7ff5a5db0d842527cba15be6dba741103a2 Mon Sep 17 00:00:00 2001 From: Saleem Jaffer Date: Sun, 5 May 2019 23:39:04 +0530 Subject: [PATCH 085/212] code review fixes --- src/librustc/ty/layout.rs | 37 +++++++++++++------------- src/librustc_codegen_ssa/traits/mod.rs | 3 +-- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 9a5db20229607..d1a8a9a34e155 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1519,6 +1519,10 @@ pub trait HasTyCtxt<'tcx>: HasDataLayout { fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx>; } +pub trait HasParamEnv<'tcx> { + fn param_env(&self) -> ty::ParamEnv<'tcx>; +} + impl<'a, 'gcx, 'tcx> HasDataLayout for TyCtxt<'a, 'gcx, 'tcx> { fn data_layout(&self) -> &TargetDataLayout { &self.data_layout @@ -1531,6 +1535,12 @@ impl<'a, 'gcx, 'tcx> HasTyCtxt<'gcx> for TyCtxt<'a, 'gcx, 'tcx> { } } +impl<'tcx, C> HasParamEnv<'tcx> for LayoutCx<'tcx, C> { + fn param_env(&self) -> ty::ParamEnv<'tcx> { + self.param_env + } +} + impl<'tcx, T: HasDataLayout> HasDataLayout for LayoutCx<'tcx, T> { fn data_layout(&self) -> &TargetDataLayout { self.tcx.data_layout() @@ -1662,16 +1672,6 @@ impl ty::query::TyCtxtAt<'a, 'tcx, '_> { } } -pub trait HasParamEnv<'tcx> { - fn param_env(&self) -> ty::ParamEnv<'tcx>; -} - -impl<'tcx, C> HasParamEnv<'tcx> for LayoutCx<'tcx, C> { - fn param_env(&self) -> ty::ParamEnv<'tcx> { - self.param_env - } -} - impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> where C: LayoutOf> + HasTyCtxt<'tcx>, C::TyLayout: MaybeResult>, @@ -1718,9 +1718,10 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> let tcx = cx.tcx(); let discr_layout = |discr: &Scalar| -> C::TyLayout { let layout = LayoutDetails::scalar(cx, discr.clone()); - MaybeResult::from(Ok( - TyLayout {details: tcx.intern_layout(layout),ty: discr.value.to_ty(tcx)} - )) + MaybeResult::from(Ok(TyLayout { + details: tcx.intern_layout(layout), + ty: discr.value.to_ty(tcx), + })) }; cx.layout_of(match this.ty.sty { @@ -1754,12 +1755,10 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> } else { tcx.mk_mut_ref(tcx.lifetimes.re_static, nil) }; - return MaybeResult::from( - cx.layout_of(ptr_ty).to_result().map(|mut ptr_layout| { - ptr_layout.ty = this.ty; - ptr_layout - }) - ); + return MaybeResult::from(cx.layout_of(ptr_ty).to_result().map(|mut ptr_layout| { + ptr_layout.ty = this.ty; + ptr_layout + })); } match tcx.struct_tail(pointee).sty { diff --git a/src/librustc_codegen_ssa/traits/mod.rs b/src/librustc_codegen_ssa/traits/mod.rs index 8c336b11a5d0a..c237cd8bd2645 100644 --- a/src/librustc_codegen_ssa/traits/mod.rs +++ b/src/librustc_codegen_ssa/traits/mod.rs @@ -89,6 +89,5 @@ pub trait HasCodegen<'tcx>: Type = Self::Type, Funclet = Self::Funclet, DIScope = Self::DIScope, - > - + HasParamEnv<'tcx>; + >; } From dc54cd0c60d079172c8655fc87c49a2250f5b199 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 5 May 2019 22:53:56 +0200 Subject: [PATCH 086/212] fix typo in enum variant name --- src/librustc_mir/interpret/validity.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 772cbcf9447ef..12708c074ca69 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -66,7 +66,7 @@ macro_rules! try_validation { pub enum PathElem { Field(Symbol), Variant(Symbol), - GeneratoreState(VariantIdx), + GeneratorState(VariantIdx), ClosureVar(Symbol), ArrayElem(usize), TupleElem(usize), @@ -101,7 +101,7 @@ fn path_format(path: &Vec) -> String { match elem { Field(name) => write!(out, ".{}", name), Variant(name) => write!(out, ".", name), - GeneratoreState(idx) => write!(out, ".", idx.index()), + GeneratorState(idx) => write!(out, ".", idx.index()), ClosureVar(name) => write!(out, ".", name), TupleElem(idx) => write!(out, ".{}", idx), ArrayElem(idx) => write!(out, "[{}]", idx), @@ -267,7 +267,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> let name = match old_op.layout.ty.sty { ty::Adt(adt, _) => PathElem::Variant(adt.variants[variant_id].ident.name), // Generators also have variants - ty::Generator(..) => PathElem::GeneratoreState(variant_id), + ty::Generator(..) => PathElem::GeneratorState(variant_id), _ => bug!("Unexpected type with variant: {:?}", old_op.layout.ty), }; self.visit_elem(new_op, name) From 764e3668b05eeee92e8d81ac748cbb1c76de1a44 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Mon, 15 Apr 2019 00:00:50 +0100 Subject: [PATCH 087/212] to_xe_bytes for isize and usize returns an array of different size ... on different platforms. Official rustdoc of [`usize::to_le_bytes`](https://doc.rust-lang.org/std/primitive.usize.html#method.to_le_bytes) displays signature ``` pub fn to_ne_bytes(self) -> [u8; 8] ``` which might be misleading: this function returns 4 bytes on 32-bit systems. --- src/libcore/num/mod.rs | 113 ++++++++++++++++++++++++++++++----------- 1 file changed, 83 insertions(+), 30 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index c1887a93490f8..562a7a4b3c719 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -214,11 +214,31 @@ pub mod diy_float; mod wrapping; +macro_rules! usize_isize_to_xe_bytes_doc { + () => {" + +**Note**: This function returns an array of length 2, 4 or 8 bytes +depending on the target pointer size. + +"} +} + + +macro_rules! usize_isize_from_xe_bytes_doc { + () => {" + +**Note**: This function takes an array of length 2, 4 or 8 bytes +depending on the target pointer size. + +"} +} + // `Int` + `SignedInt` implemented for signed integers macro_rules! int_impl { ($SelfT:ty, $ActualT:ident, $UnsignedT:ty, $BITS:expr, $Min:expr, $Max:expr, $Feature:expr, $EndFeature:expr, $rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr, - $reversed:expr, $le_bytes:expr, $be_bytes:expr) => { + $reversed:expr, $le_bytes:expr, $be_bytes:expr, + $to_xe_bytes_doc:expr, $from_xe_bytes_doc:expr) => { doc_comment! { concat!("Returns the smallest value that can be represented by this integer type. @@ -2023,7 +2043,9 @@ $EndFeature, " doc_comment! { concat!("Return the memory representation of this integer as a byte array in big-endian (network) byte order. - +", +$to_xe_bytes_doc, +" # Examples ``` @@ -2041,7 +2063,9 @@ assert_eq!(bytes, ", $be_bytes, "); doc_comment! { concat!("Return the memory representation of this integer as a byte array in little-endian byte order. - +", +$to_xe_bytes_doc, +" # Examples ``` @@ -2064,7 +2088,9 @@ native byte order. As the target platform's native endianness is used, portable code should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, instead. - +", +$to_xe_bytes_doc, +" [`to_be_bytes`]: #method.to_be_bytes [`to_le_bytes`]: #method.to_le_bytes @@ -2089,7 +2115,9 @@ assert_eq!(bytes, if cfg!(target_endian = \"big\") { doc_comment! { concat!("Create an integer value from its representation as a byte array in big endian. - +", +$from_xe_bytes_doc, +" # Examples ``` @@ -2120,7 +2148,9 @@ doc_comment! { concat!(" Create an integer value from its representation as a byte array in little endian. - +", +$from_xe_bytes_doc, +" # Examples ``` @@ -2157,7 +2187,9 @@ appropriate instead. [`from_be_bytes`]: #method.from_be_bytes [`from_le_bytes`]: #method.from_le_bytes - +", +$from_xe_bytes_doc, +" # Examples ``` @@ -2193,20 +2225,20 @@ fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), #[lang = "i8"] impl i8 { int_impl! { i8, i8, u8, 8, -128, 127, "", "", 2, "-0x7e", "0xa", "0x12", "0x12", "0x48", - "[0x12]", "[0x12]" } + "[0x12]", "[0x12]", "", "" } } #[lang = "i16"] impl i16 { int_impl! { i16, i16, u16, 16, -32768, 32767, "", "", 4, "-0x5ffd", "0x3a", "0x1234", "0x3412", - "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]" } + "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" } } #[lang = "i32"] impl i32 { int_impl! { i32, i32, u32, 32, -2147483648, 2147483647, "", "", 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78]" } + "[0x12, 0x34, 0x56, 0x78]", "", "" } } #[lang = "i64"] @@ -2214,7 +2246,7 @@ impl i64 { int_impl! { i64, i64, u64, 64, -9223372036854775808, 9223372036854775807, "", "", 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]" } + "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", "", "" } } #[lang = "i128"] @@ -2226,14 +2258,15 @@ impl i128 { "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \ 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \ - 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]" } + 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]", "", "" } } #[cfg(target_pointer_width = "16")] #[lang = "isize"] impl isize { int_impl! { isize, i16, u16, 16, -32768, 32767, "", "", 4, "-0x5ffd", "0x3a", "0x1234", - "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]" } + "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", + usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } } #[cfg(target_pointer_width = "32")] @@ -2241,7 +2274,8 @@ impl isize { impl isize { int_impl! { isize, i32, u32, 32, -2147483648, 2147483647, "", "", 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78]" } + "[0x12, 0x34, 0x56, 0x78]", + usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } } #[cfg(target_pointer_width = "64")] @@ -2250,14 +2284,16 @@ impl isize { int_impl! { isize, i64, u64, 64, -9223372036854775808, 9223372036854775807, "", "", 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]" } + "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", + usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } } // `Int` + `UnsignedInt` implemented for unsigned integers macro_rules! uint_impl { ($SelfT:ty, $ActualT:ty, $BITS:expr, $MaxV:expr, $Feature:expr, $EndFeature:expr, $rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr, - $reversed:expr, $le_bytes:expr, $be_bytes:expr) => { + $reversed:expr, $le_bytes:expr, $be_bytes:expr, + $to_xe_bytes_doc:expr, $from_xe_bytes_doc:expr) => { doc_comment! { concat!("Returns the smallest value that can be represented by this integer type. @@ -3817,7 +3853,9 @@ $EndFeature, " doc_comment! { concat!("Return the memory representation of this integer as a byte array in big-endian (network) byte order. - +", +$to_xe_bytes_doc, +" # Examples ``` @@ -3835,7 +3873,9 @@ assert_eq!(bytes, ", $be_bytes, "); doc_comment! { concat!("Return the memory representation of this integer as a byte array in little-endian byte order. - +", +$to_xe_bytes_doc, +" # Examples ``` @@ -3858,7 +3898,9 @@ native byte order. As the target platform's native endianness is used, portable code should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, instead. - +", +$to_xe_bytes_doc, +" [`to_be_bytes`]: #method.to_be_bytes [`to_le_bytes`]: #method.to_le_bytes @@ -3883,7 +3925,9 @@ assert_eq!(bytes, if cfg!(target_endian = \"big\") { doc_comment! { concat!("Create an integer value from its representation as a byte array in big endian. - +", +$from_xe_bytes_doc, +" # Examples ``` @@ -3914,7 +3958,9 @@ fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), concat!(" Create an integer value from its representation as a byte array in little endian. - +", +$from_xe_bytes_doc, +" # Examples ``` @@ -3951,7 +3997,9 @@ appropriate instead. [`from_be_bytes`]: #method.from_be_bytes [`from_le_bytes`]: #method.from_le_bytes - +", +$from_xe_bytes_doc, +" # Examples ``` @@ -3987,7 +4035,7 @@ fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), #[lang = "u8"] impl u8 { uint_impl! { u8, u8, 8, 255, "", "", 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]", - "[0x12]" } + "[0x12]", "", "" } /// Checks if the value is within the ASCII range. @@ -4506,13 +4554,13 @@ impl u8 { #[lang = "u16"] impl u16 { uint_impl! { u16, u16, 16, 65535, "", "", 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", - "[0x34, 0x12]", "[0x12, 0x34]" } + "[0x34, 0x12]", "[0x12, 0x34]", "", "" } } #[lang = "u32"] impl u32 { uint_impl! { u32, u32, 32, 4294967295, "", "", 8, "0x10000b3", "0xb301", "0x12345678", - "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]" } + "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" } } #[lang = "u64"] @@ -4520,7 +4568,8 @@ impl u64 { uint_impl! { u64, u64, 64, 18446744073709551615, "", "", 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]" } + "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", + "", ""} } #[lang = "u128"] @@ -4531,20 +4580,23 @@ impl u128 { "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \ 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \ - 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]" } + 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]", + "", ""} } #[cfg(target_pointer_width = "16")] #[lang = "usize"] impl usize { uint_impl! { usize, u16, 16, 65535, "", "", 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", - "[0x34, 0x12]", "[0x12, 0x34]" } + "[0x34, 0x12]", "[0x12, 0x34]", + usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } } #[cfg(target_pointer_width = "32")] #[lang = "usize"] impl usize { uint_impl! { usize, u32, 32, 4294967295, "", "", 8, "0x10000b3", "0xb301", "0x12345678", - "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]" } + "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", + usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } } #[cfg(target_pointer_width = "64")] @@ -4553,7 +4605,8 @@ impl usize { uint_impl! { usize, u64, 64, 18446744073709551615, "", "", 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]" } + "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", + usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } } /// A classification of floating point numbers. From 97d3ad066d08d98ba574f2da8d379dce07fc286f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Tue, 16 Apr 2019 09:59:55 +0200 Subject: [PATCH 088/212] Only hash dep node indices of deps of anon tasks --- src/librustc/dep_graph/graph.rs | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 1ecc580d8c5c4..a87c98a04a4ab 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -1021,25 +1021,22 @@ impl CurrentDepGraph { fn complete_anon_task(&mut self, kind: DepKind, task_deps: TaskDeps) -> DepNodeIndex { debug_assert!(!kind.is_eval_always()); - let mut fingerprint = self.anon_id_seed; let mut hasher = StableHasher::new(); - for &read in task_deps.reads.iter() { - let read_dep_node = self.data[read].node; + // The dep node indices are hashed here instead of hashing the dep nodes of the + // dependencies. These indices may refer to different nodes per session, but this isn't + // a problem here because we that ensure the final dep node hash is per session only by + // combining it with the per session random number `anon_id_seed`. This hash only need + // to map the dependencies to a single value on a per session basis. + task_deps.reads.hash(&mut hasher); - ::std::mem::discriminant(&read_dep_node.kind).hash(&mut hasher); + let target_dep_node = DepNode { + kind, // Fingerprint::combine() is faster than sending Fingerprint // through the StableHasher (at least as long as StableHasher // is so slow). - fingerprint = fingerprint.combine(read_dep_node.hash); - } - - fingerprint = fingerprint.combine(hasher.finish()); - - let target_dep_node = DepNode { - kind, - hash: fingerprint, + hash: self.anon_id_seed.combine(hasher.finish()), }; self.intern_node(target_dep_node, task_deps.reads, Fingerprint::ZERO).0 From c3694e5ee69247eb1ac10c6d3b187f567303dc8d Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 6 May 2019 13:12:04 +0100 Subject: [PATCH 089/212] Rename `ParamTy::idx` to `ParamTy::index` --- src/librustc/traits/error_reporting.rs | 2 +- src/librustc/traits/select.rs | 2 +- src/librustc/traits/util.rs | 2 +- src/librustc/ty/context.rs | 6 ++---- src/librustc/ty/mod.rs | 2 +- src/librustc/ty/relate.rs | 2 +- src/librustc/ty/structural_impls.rs | 2 +- src/librustc/ty/sty.rs | 12 ++++++------ src/librustc/ty/subst.rs | 6 +++--- src/librustc_typeck/check/method/probe.rs | 3 +-- src/librustc_typeck/check/mod.rs | 6 +++--- src/librustc_typeck/check/wfcheck.rs | 2 +- src/librustc_typeck/constrained_generic_params.rs | 2 +- src/librustc_typeck/variance/constraints.rs | 2 +- 14 files changed, 24 insertions(+), 27 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 007ff32f32776..d9ccbba69d5c0 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1453,7 +1453,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.infcx.tcx } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - if let ty::Param(ty::ParamTy {name, ..}) = ty.sty { + if let ty::Param(ty::ParamTy {name, .. }) = ty.sty { let infcx = self.infcx; self.var_map.entry(ty).or_insert_with(|| infcx.next_ty_var( diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index f0c402789c4cd..d68e2be9ea086 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -3424,7 +3424,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let mut found = false; for ty in field.walk() { if let ty::Param(p) = ty.sty { - ty_params.insert(p.idx as usize); + ty_params.insert(p.index as usize); found = true; } } diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 90f62a4d132c7..be29ea5701b2f 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -204,7 +204,7 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> { }, Component::Param(p) => { - let ty = tcx.mk_ty_param(p.idx, p.name); + let ty = tcx.mk_ty_param(p.index, p.name); Some(ty::Predicate::TypeOutlives( ty::Binder::dummy(ty::OutlivesPredicate(ty, r_min)))) }, diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 19440d0bc64ea..15524ca6e930c 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2715,10 +2715,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } #[inline] - pub fn mk_ty_param(self, - index: u32, - name: InternedString) -> Ty<'tcx> { - self.mk_ty(Param(ParamTy { idx: index, name: name })) + pub fn mk_ty_param(self, index: u32, name: InternedString) -> Ty<'tcx> { + self.mk_ty(Param(ParamTy { index, name: name })) } #[inline] diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index cb92e4b7470a5..7b749957c3ff5 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -979,7 +979,7 @@ impl<'a, 'gcx, 'tcx> Generics { param: &ParamTy, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx GenericParamDef { - if let Some(index) = param.idx.checked_sub(self.parent_count as u32) { + if let Some(index) = param.index.checked_sub(self.parent_count as u32) { let param = &self.params[index as usize]; match param.kind { GenericParamDefKind::Type { .. } => param, diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index d7b1907074195..2049341327495 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -390,7 +390,7 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, } (&ty::Param(ref a_p), &ty::Param(ref b_p)) - if a_p.idx == b_p.idx => + if a_p.index == b_p.index => { Ok(a) } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index bab9527dd07f6..6df8a21241f7b 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -240,7 +240,7 @@ impl fmt::Debug for Ty<'tcx> { impl fmt::Debug for ty::ParamTy { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}/#{}", self.name, self.idx) + write!(f, "{}/#{}", self.name, self.index) } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index cca40c379fc11..760f3d60d0571 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1111,13 +1111,13 @@ pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder>>; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable)] pub struct ParamTy { - pub idx: u32, + pub index: u32, pub name: InternedString, } impl<'a, 'gcx, 'tcx> ParamTy { pub fn new(index: u32, name: InternedString) -> ParamTy { - ParamTy { idx: index, name: name } + ParamTy { index, name: name } } pub fn for_self() -> ParamTy { @@ -1129,14 +1129,14 @@ impl<'a, 'gcx, 'tcx> ParamTy { } pub fn to_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> { - tcx.mk_ty_param(self.idx, self.name) + tcx.mk_ty_param(self.index, self.name) } pub fn is_self(&self) -> bool { - // FIXME(#50125): Ignoring `Self` with `idx != 0` might lead to weird behavior elsewhere, + // FIXME(#50125): Ignoring `Self` with `index != 0` might lead to weird behavior elsewhere, // but this should only be possible when using `-Z continue-parse-after-error` like // `compile-fail/issue-36638.rs`. - self.name == keywords::SelfUpper.name().as_str() && self.idx == 0 + self.name == keywords::SelfUpper.name().as_str() && self.index == 0 } } @@ -1763,7 +1763,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn is_param(&self, index: u32) -> bool { match self.sty { - ty::Param(ref data) => data.idx == index, + ty::Param(ref data) => data.index == index, _ => false, } } diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 8d51fbc174a04..33f0df836d0c1 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -547,7 +547,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for SubstFolder<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> { fn ty_for_param(&self, p: ty::ParamTy, source_ty: Ty<'tcx>) -> Ty<'tcx> { // Look up the type in the substitutions. It really should be in there. - let opt_ty = self.substs.get(p.idx as usize).map(|k| k.unpack()); + let opt_ty = self.substs.get(p.index as usize).map(|k| k.unpack()); let ty = match opt_ty { Some(UnpackedKind::Type(ty)) => ty, Some(kind) => { @@ -558,7 +558,7 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> { when substituting (root type={:?}) substs={:?}", p, source_ty, - p.idx, + p.index, kind, self.root_ty, self.substs, @@ -572,7 +572,7 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> { when substituting (root type={:?}) substs={:?}", p, source_ty, - p.idx, + p.index, self.root_ty, self.substs, ); diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 314f7e97cd28d..251400e65f383 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -757,8 +757,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { }); } - fn assemble_inherent_candidates_from_param(&mut self, - param_ty: ty::ParamTy) { + fn assemble_inherent_candidates_from_param(&mut self, param_ty: ty::ParamTy) { // FIXME -- Do we want to commit to this behavior for param bounds? let bounds = self.param_env diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index e404a8e6972c8..57cd2b4dab1be 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5795,9 +5795,9 @@ pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut types_used = vec![false; own_counts.types]; for leaf_ty in ty.walk() { - if let ty::Param(ty::ParamTy { idx, .. }) = leaf_ty.sty { - debug!("Found use of ty param num {}", idx); - types_used[idx as usize - own_counts.lifetimes] = true; + if let ty::Param(ty::ParamTy { index, .. }) = leaf_ty.sty { + debug!("Found use of ty param num {}", index); + types_used[index as usize - own_counts.lifetimes] = true; } else if let ty::Error = leaf_ty.sty { // If there is already another error, do not emit // an error for not using a type Parameter. diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 1420c66c73ea3..fd7d6fe694ccd 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -494,7 +494,7 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>( impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams { fn visit_ty(&mut self, t: Ty<'tcx>) -> bool { if let ty::Param(param) = t.sty { - self.params.insert(param.idx); + self.params.insert(param.index); } t.super_visit_with(self) } diff --git a/src/librustc_typeck/constrained_generic_params.rs b/src/librustc_typeck/constrained_generic_params.rs index 18bf66ceb3501..49910e39fed20 100644 --- a/src/librustc_typeck/constrained_generic_params.rs +++ b/src/librustc_typeck/constrained_generic_params.rs @@ -8,7 +8,7 @@ use syntax::source_map::Span; pub struct Parameter(pub u32); impl From for Parameter { - fn from(param: ty::ParamTy) -> Self { Parameter(param.idx) } + fn from(param: ty::ParamTy) -> Self { Parameter(param.index) } } impl From for Parameter { diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 5079a3bb55f89..4f82978f01a5d 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -324,7 +324,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } ty::Param(ref data) => { - self.add_constraint(current, data.idx, variance); + self.add_constraint(current, data.index, variance); } ty::FnPtr(sig) => { From 638d1d34ff89803b8558713fa6d5dff79019c854 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 6 May 2019 13:54:59 +0100 Subject: [PATCH 090/212] Remove duplicate comment Co-Authored-By: Gabriel Smith --- src/libsyntax/parse/parser.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d46feeab33599..084091f4c2a39 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -6045,10 +6045,6 @@ impl<'a> Parser<'a> { }); assoc_ty_bindings.push(span); } else if self.check_const_arg() { - // FIXME(const_generics): to distinguish between idents for types and consts, - // we should introduce a GenericArg::Ident in the AST and distinguish when - // lowering to the HIR. For now, idents for const args are not permitted. - // Parse const argument. let expr = if let token::OpenDelim(token::Brace) = self.token { self.parse_block_expr(None, self.span, BlockCheckMode::Default, ThinVec::new())? From 59ebd1b7c2b9558ab31c57878666f0707f33b689 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 6 May 2019 13:55:14 +0100 Subject: [PATCH 091/212] Shift const vars through binders Co-Authored-By: Gabriel Smith --- src/librustc/ty/subst.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 8d51fbc174a04..e5bd3f15efe95 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -618,8 +618,7 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> { } }; - // FIXME(const_generics): shift const through binders - ct + self.shift_vars_through_binders(ct) } /// It is sometimes necessary to adjust the De Bruijn indices during substitution. This occurs @@ -664,15 +663,15 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> { /// As indicated in the diagram, here the same type `&'a int` is substituted once, but in the /// first case we do not increase the De Bruijn index and in the second case we do. The reason /// is that only in the second case have we passed through a fn binder. - fn shift_vars_through_binders(&self, ty: Ty<'tcx>) -> Ty<'tcx> { - debug!("shift_vars(ty={:?}, binders_passed={:?}, has_escaping_bound_vars={:?})", - ty, self.binders_passed, ty.has_escaping_bound_vars()); + fn shift_vars_through_binders>(&self, val: T) -> T { + debug!("shift_vars(val={:?}, binders_passed={:?}, has_escaping_bound_vars={:?})", + val, self.binders_passed, val.has_escaping_bound_vars()); - if self.binders_passed == 0 || !ty.has_escaping_bound_vars() { - return ty; + if self.binders_passed == 0 || !val.has_escaping_bound_vars() { + return val; } - let result = ty::fold::shift_vars(self.tcx(), &ty, self.binders_passed); + let result = ty::fold::shift_vars(self.tcx(), &val, self.binders_passed); debug!("shift_vars: shifted result = {:?}", result); result From ad78fcf5246c9accb2a35ced91d85b710648abc9 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 6 May 2019 13:55:28 +0100 Subject: [PATCH 092/212] Ignore const parameters when constructing type bounds in rustdoc Co-Authored-By: Gabriel Smith --- src/librustdoc/clean/mod.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index de74a6a540055..3a260db806520 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1706,9 +1706,7 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, } Some(param.clean(cx)) } - ty::GenericParamDefKind::Const { .. } => { - unimplemented!() // FIXME(const_generics) - } + ty::GenericParamDefKind::Const { .. } => None, }).collect::>(); let mut where_predicates = preds.predicates.iter() From c6197541f73c570f5104c36920b387992c7658d2 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 6 May 2019 14:05:26 +0100 Subject: [PATCH 093/212] Implement TypeFoldable for InferConst Co-Authored-By: Gabriel Smith --- src/librustc/ty/structural_impls.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index bab9527dd07f6..f81394a878f5a 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -6,7 +6,7 @@ use crate::hir::def::Namespace; use crate::mir::ProjectionKind; use crate::mir::interpret::ConstValue; -use crate::ty::{self, Lift, Ty, TyCtxt, ConstVid}; +use crate::ty::{self, Lift, Ty, TyCtxt, ConstVid, InferConst}; use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use crate::ty::print::{FmtPrinter, Printer}; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; @@ -1352,8 +1352,7 @@ impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { match *self { ConstValue::ByRef(ptr, alloc) => ConstValue::ByRef(ptr, alloc), - // FIXME(const_generics): implement TypeFoldable for InferConst - ConstValue::Infer(ic) => ConstValue::Infer(ic), + ConstValue::Infer(ic) => ConstValue::Infer(ic.fold_with(folder)), ConstValue::Param(p) => ConstValue::Param(p.fold_with(folder)), ConstValue::Placeholder(p) => ConstValue::Placeholder(p), ConstValue::Scalar(a) => ConstValue::Scalar(a), @@ -1366,8 +1365,7 @@ impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> { fn super_visit_with>(&self, visitor: &mut V) -> bool { match *self { ConstValue::ByRef(..) => false, - // FIXME(const_generics): implement TypeFoldable for InferConst - ConstValue::Infer(_) => false, + ConstValue::Infer(ic) => ic.visit_with(visitor), ConstValue::Param(p) => p.visit_with(visitor), ConstValue::Placeholder(_) => false, ConstValue::Scalar(_) => false, @@ -1376,3 +1374,13 @@ impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> { } } } + +impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _folder: &mut F) -> Self { + *self + } + + fn super_visit_with>(&self, _visitor: &mut V) -> bool { + false + } +} From 670cf11de22583e1192636f0e6c36007ebcbb776 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 6 May 2019 14:16:07 +0100 Subject: [PATCH 094/212] Clean up `push_const_name` Co-Authored-By: Gabriel Smith --- src/librustc_mir/monomorphize/item.rs | 40 +++++++++++++++++---------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs index b001a09529e5b..999e7402afd93 100644 --- a/src/librustc_mir/monomorphize/item.rs +++ b/src/librustc_mir/monomorphize/item.rs @@ -3,7 +3,7 @@ use rustc::hir; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::mir::interpret::ConstValue; use rustc::session::config::OptLevel; -use rustc::ty::{self, Ty, TyCtxt, Const, ClosureSubsts, GeneratorSubsts, ParamConst}; +use rustc::ty::{self, Ty, TyCtxt, Const, ClosureSubsts, GeneratorSubsts}; use rustc::ty::subst::{SubstsRef, InternalSubsts}; use syntax::ast; use syntax::attr::InlineAttr; @@ -240,11 +240,11 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { } // Pushes the type name of the specified type to the provided string. - // If 'debug' is true, printing normally unprintable types is allowed - // (e.g. ty::GeneratorWitness). This parameter should only be set when - // this method is being used for logging purposes (e.g. with debug! or info!) - // When being used for codegen purposes, 'debug' should be set to 'false' - // in order to catch unexpected types that should never end up in a type name + // If `debug` is true, printing normally unprintable types is allowed + // (e.g. `ty::GeneratorWitness`). This parameter should only be set when + // this method is being used for logging purposes (e.g. with `debug!` or `info!`) + // When being used for codegen purposes, `debug` should be set to `false` + // in order to catch unexpected types that should never end up in a type name. pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String, debug: bool) { match t.sty { ty::Bool => output.push_str("bool"), @@ -387,22 +387,34 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { if debug { output.push_str(&format!("`{:?}`", t)); } else { - bug!("DefPathBasedNames: Trying to create type name for \ - unexpected type: {:?}", t); + bug!( + "DefPathBasedNames: trying to create type name for unexpected type: {:?}", + t, + ); } } } } - // FIXME(const_generics): handle debug printing. + // Pushes the the name of the specified const to the provided string. + // If `debug` is true, usually-unprintable consts (such as `Infer`) will be printed, + // as well as the unprintable types of constants (see `push_type_name` for more details). pub fn push_const_name(&self, c: &Const<'tcx>, output: &mut String, debug: bool) { match c.val { - ConstValue::Infer(..) | ConstValue::Placeholder(_) => output.push_str("_"), - ConstValue::Param(ParamConst { name, .. }) => { - write!(output, "{}", name).unwrap(); + ConstValue::Scalar(..) | ConstValue::Slice(..) | ConstValue::ByRef(..) => { + // FIXME(const_generics): we could probably do a better job here. + write!(output, "{:?}", c).unwrap() + } + _ => { + if debug { + write!(output, "{:?}", c).unwrap() + } else { + bug!( + "DefPathBasedNames: trying to create const name for unexpected const: {:?}", + c, + ); + } } - ConstValue::Unevaluated(..) => output.push_str("_: _"), - _ => write!(output, "{:?}", c).unwrap(), } output.push_str(": "); self.push_type_name(c.ty, output, debug); From c0454f0638f235dd7c8b4bb57ea5614e5e877746 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 6 May 2019 14:16:28 +0100 Subject: [PATCH 095/212] Remove incorrect FIXME Co-Authored-By: Gabriel Smith --- src/librustc_typeck/check/mod.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index e404a8e6972c8..82fcf8ff52f83 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5785,8 +5785,6 @@ pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty ); - // FIXME(const_generics): we probably want to check the bounds for const parameters too. - if own_counts.types == 0 { return; } From 5fc0395053c732c8becf0e1dca7000554c352ccd Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 6 May 2019 14:17:48 +0100 Subject: [PATCH 096/212] Resolve a couple of `unimplemented!()`s Co-Authored-By: Gabriel Smith --- src/librustc/infer/canonical/query_response.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs index 8225ed70c5827..413c1428ff954 100644 --- a/src/librustc/infer/canonical/query_response.rs +++ b/src/librustc/infer/canonical/query_response.rs @@ -318,8 +318,9 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { obligations.extend(ok.into_obligations()); } - (UnpackedKind::Const(..), UnpackedKind::Const(..)) => { - unimplemented!() // FIXME(const_generics) + (UnpackedKind::Const(v1), UnpackedKind::Const(v2)) => { + let ok = self.at(cause, param_env).eq(v1, v2)?; + obligations.extend(ok.into_obligations()); } _ => { @@ -626,8 +627,9 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { obligations .extend(self.at(cause, param_env).eq(v1, v2)?.into_obligations()); } - (UnpackedKind::Const(..), UnpackedKind::Const(..)) => { - unimplemented!() // FIXME(const_generics) + (UnpackedKind::Const(v1), UnpackedKind::Const(v2)) => { + let ok = self.at(cause, param_env).eq(v1, v2)?; + obligations.extend(ok.into_obligations()); } _ => { bug!("kind mismatch, cannot unify {:?} and {:?}", value1, value2,); From 9a2772aff0e6c2058fb52a844b4593eabd18fcbc Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 6 May 2019 15:07:46 +0100 Subject: [PATCH 097/212] Implement `ToTrace` for `ty::Const` --- src/librustc/infer/at.rs | 15 +++++++++++++++ src/librustc/infer/error_reporting/mod.rs | 1 + src/librustc/infer/mod.rs | 2 ++ 3 files changed, 18 insertions(+) diff --git a/src/librustc/infer/at.rs b/src/librustc/infer/at.rs index 34cd3ae5427e0..5772110889290 100644 --- a/src/librustc/infer/at.rs +++ b/src/librustc/infer/at.rs @@ -27,6 +27,7 @@ use super::*; +use crate::ty::Const; use crate::ty::relate::{Relate, TypeRelation}; pub struct At<'a, 'gcx: 'tcx, 'tcx: 'a> { @@ -308,6 +309,20 @@ impl<'tcx> ToTrace<'tcx> for ty::Region<'tcx> { } } +impl<'tcx> ToTrace<'tcx> for &'tcx Const<'tcx> { + fn to_trace(cause: &ObligationCause<'tcx>, + a_is_expected: bool, + a: Self, + b: Self) + -> TypeTrace<'tcx> + { + TypeTrace { + cause: cause.clone(), + values: Consts(ExpectedFound::new(a_is_expected, a, b)) + } + } +} + impl<'tcx> ToTrace<'tcx> for ty::TraitRef<'tcx> { fn to_trace(cause: &ObligationCause<'tcx>, a_is_expected: bool, diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 95b566d4a1b69..4b6e7da333081 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -1260,6 +1260,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { match *values { infer::Types(ref exp_found) => self.expected_found_str_ty(exp_found), infer::Regions(ref exp_found) => self.expected_found_str(exp_found), + infer::Consts(ref exp_found) => self.expected_found_str(exp_found), infer::TraitRefs(ref exp_found) => self.expected_found_str(exp_found), infer::PolyTraitRefs(ref exp_found) => self.expected_found_str(exp_found), } diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 5846e604cfc09..b5a9184079aa6 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -232,6 +232,7 @@ pub type PlaceholderMap<'tcx> = BTreeMap>; pub enum ValuePairs<'tcx> { Types(ExpectedFound>), Regions(ExpectedFound>), + Consts(ExpectedFound<&'tcx ty::Const<'tcx>>), TraitRefs(ExpectedFound>), PolyTraitRefs(ExpectedFound>), } @@ -1730,6 +1731,7 @@ EnumTypeFoldableImpl! { impl<'tcx> TypeFoldable<'tcx> for ValuePairs<'tcx> { (ValuePairs::Types)(a), (ValuePairs::Regions)(a), + (ValuePairs::Consts)(a), (ValuePairs::TraitRefs)(a), (ValuePairs::PolyTraitRefs)(a), } From 594685b5a2f35e2ff4fc01aca2ae91de92ed0993 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 6 May 2019 17:00:01 +0100 Subject: [PATCH 098/212] `token::LArrow` can begin arguments `<-` may indicate the start of a negative const argument. --- src/libsyntax/parse/parser.rs | 3 ++- src/test/ui/const-generics/const-expression-parameter.rs | 2 +- .../ui/const-generics/const-expression-parameter.stderr | 8 +------- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d46feeab33599..2f7b6f9fa664f 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2319,7 +2319,8 @@ impl<'a> Parser<'a> { let ident = self.parse_path_segment_ident()?; let is_args_start = |token: &token::Token| match *token { - token::Lt | token::BinOp(token::Shl) | token::OpenDelim(token::Paren) => true, + token::Lt | token::BinOp(token::Shl) | token::OpenDelim(token::Paren) + | token::LArrow => true, _ => false, }; let check_args_start = |this: &mut Self| { diff --git a/src/test/ui/const-generics/const-expression-parameter.rs b/src/test/ui/const-generics/const-expression-parameter.rs index 662c7b767bae0..22c6c35162281 100644 --- a/src/test/ui/const-generics/const-expression-parameter.rs +++ b/src/test/ui/const-generics/const-expression-parameter.rs @@ -6,7 +6,7 @@ fn i32_identity() -> i32 { } fn foo_a() { - i32_identity::<-1>(); //~ ERROR expected identifier, found `<-` + i32_identity::<-1>(); // ok } fn foo_b() { diff --git a/src/test/ui/const-generics/const-expression-parameter.stderr b/src/test/ui/const-generics/const-expression-parameter.stderr index 2f7a80f0c8fde..c255127c28079 100644 --- a/src/test/ui/const-generics/const-expression-parameter.stderr +++ b/src/test/ui/const-generics/const-expression-parameter.stderr @@ -1,9 +1,3 @@ -error: expected identifier, found `<-` - --> $DIR/const-expression-parameter.rs:9:19 - | -LL | i32_identity::<-1>(); - | ^^ expected identifier - error: expected one of `,` or `>`, found `+` --> $DIR/const-expression-parameter.rs:13:22 | @@ -16,5 +10,5 @@ warning: the feature `const_generics` is incomplete and may cause the compiler t LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to previous error From e570fe5b220c1c9064587f94a885587b7f910ab1 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 6 May 2019 17:00:34 +0100 Subject: [PATCH 099/212] Remove resolved FIXME --- src/libsyntax/parse/parser.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 2f7b6f9fa664f..67e3132b2fc18 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -6061,8 +6061,6 @@ impl<'a> Parser<'a> { self.fatal("identifiers may currently not be used for const generics") ); } else { - // FIXME(const_generics): this currently conflicts with emplacement syntax - // with negative integer literals. self.parse_literal_maybe_minus()? }; let value = AnonConst { From 6d26c5f73ca1c6d1615c141b181374e152cab61a Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Mon, 6 May 2019 13:42:15 -0500 Subject: [PATCH 100/212] rustfmt --- src/libsyntax/ext/tt/transcribe.rs | 100 ++++++++++++++--------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index bd2adb5ac13ba..5eb5475b2a948 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -1,10 +1,10 @@ use crate::ast::Ident; use crate::ext::base::ExtCtxt; use crate::ext::expand::Marker; -use crate::ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal}; +use crate::ext::tt::macro_parser::{MatchedNonterminal, MatchedSeq, NamedMatch}; use crate::ext::tt::quoted; use crate::mut_visit::noop_visit_tt; -use crate::parse::token::{self, Token, NtTT}; +use crate::parse::token::{self, NtTT, Token}; use crate::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint}; use smallvec::{smallvec, SmallVec}; @@ -16,18 +16,10 @@ use std::mem; use std::ops::Add; use std::rc::Rc; -// An iterator over the token trees in a delimited token tree (`{ ... }`) or a sequence (`$(...)`). +/// An iterator over the token trees in a delimited token tree (`{ ... }`) or a sequence (`$(...)`). enum Frame { - Delimited { - forest: Lrc, - idx: usize, - span: DelimSpan, - }, - Sequence { - forest: Lrc, - idx: usize, - sep: Option, - }, + Delimited { forest: Lrc, idx: usize, span: DelimSpan }, + Sequence { forest: Lrc, idx: usize, sep: Option }, } impl Frame { @@ -54,13 +46,13 @@ impl Iterator for Frame { } } -/// This can do Macro-By-Example transcription. On the other hand, if -/// `src` contains no `TokenTree::{Sequence, MetaVar, MetaVarDecl}`s, `interp` can -/// (and should) be None. -pub fn transcribe(cx: &ExtCtxt<'_>, - interp: Option>>, - src: Vec) - -> TokenStream { +/// This can do Macro-By-Example transcription. On the other hand, if `src` contains no +/// `TokenTree::{Sequence, MetaVar, MetaVarDecl}`s, `interp` can (and should) be `None`. +pub fn transcribe( + cx: &ExtCtxt<'_>, + interp: Option>>, + src: Vec, +) -> TokenStream { let mut stack: SmallVec<[Frame; 1]> = smallvec![Frame::new(src)]; let interpolations = interp.unwrap_or_else(FxHashMap::default); /* just a convenience */ let mut repeats = Vec::new(); @@ -84,7 +76,7 @@ pub fn transcribe(cx: &ExtCtxt<'_>, }; result.push(TokenTree::Token(prev_span, sep).into()); } - continue + continue; } } @@ -96,29 +88,30 @@ pub fn transcribe(cx: &ExtCtxt<'_>, if result_stack.is_empty() { return TokenStream::new(result); } - let tree = TokenTree::Delimited( - span, - forest.delim, - TokenStream::new(result).into(), - ); + let tree = + TokenTree::Delimited(span, forest.delim, TokenStream::new(result).into()); result = result_stack.pop().unwrap(); result.push(tree.into()); } } - continue + continue; }; match tree { quoted::TokenTree::Sequence(sp, seq) => { // FIXME(pcwalton): Bad copy. - match lockstep_iter_size("ed::TokenTree::Sequence(sp, seq.clone()), - &interpolations, - &repeats) { + match lockstep_iter_size( + "ed::TokenTree::Sequence(sp, seq.clone()), + &interpolations, + &repeats, + ) { LockstepIterSize::Unconstrained => { - cx.span_fatal(sp.entire(), /* blame macro writer */ + cx.span_fatal( + sp.entire(), /* blame macro writer */ "attempted to repeat an expression \ containing no syntax \ - variables matched as repeating at this depth"); + variables matched as repeating at this depth", + ); } LockstepIterSize::Contradiction(ref msg) => { // FIXME #2887 blame macro invoker instead @@ -153,8 +146,10 @@ pub fn transcribe(cx: &ExtCtxt<'_>, result.push(token.into()); } } else { - cx.span_fatal(sp, /* blame the macro writer */ - &format!("variable '{}' is still repeating at this depth", ident)); + cx.span_fatal( + sp, /* blame the macro writer */ + &format!("variable '{}' is still repeating at this depth", ident), + ); } } else { let ident = @@ -180,10 +175,11 @@ pub fn transcribe(cx: &ExtCtxt<'_>, } } -fn lookup_cur_matched(ident: Ident, - interpolations: &FxHashMap>, - repeats: &[(usize, usize)]) - -> Option> { +fn lookup_cur_matched( + ident: Ident, + interpolations: &FxHashMap>, + repeats: &[(usize, usize)], +) -> Option> { interpolations.get(&ident).map(|matched| { let mut matched = matched.clone(); for &(idx, _) in repeats { @@ -217,9 +213,11 @@ impl Add for LockstepIterSize { LockstepIterSize::Contradiction(_) => other, LockstepIterSize::Constraint(r_len, _) if l_len == r_len => self, LockstepIterSize::Constraint(r_len, r_id) => { - let msg = format!("inconsistent lockstep iteration: \ - '{}' has {} items, but '{}' has {}", - l_id, l_len, r_id, r_len); + let msg = format!( + "inconsistent lockstep iteration: \ + '{}' has {} items, but '{}' has {}", + l_id, l_len, r_id, r_len + ); LockstepIterSize::Contradiction(msg) } }, @@ -227,30 +225,32 @@ impl Add for LockstepIterSize { } } -fn lockstep_iter_size(tree: "ed::TokenTree, - interpolations: &FxHashMap>, - repeats: &[(usize, usize)]) - -> LockstepIterSize { +fn lockstep_iter_size( + tree: "ed::TokenTree, + interpolations: &FxHashMap>, + repeats: &[(usize, usize)], +) -> LockstepIterSize { use quoted::TokenTree; match *tree { TokenTree::Delimited(_, ref delimed) => { delimed.tts.iter().fold(LockstepIterSize::Unconstrained, |size, tt| { size + lockstep_iter_size(tt, interpolations, repeats) }) - }, + } TokenTree::Sequence(_, ref seq) => { seq.tts.iter().fold(LockstepIterSize::Unconstrained, |size, tt| { size + lockstep_iter_size(tt, interpolations, repeats) }) - }, - TokenTree::MetaVar(_, name) | TokenTree::MetaVarDecl(_, name, _) => + } + TokenTree::MetaVar(_, name) | TokenTree::MetaVarDecl(_, name, _) => { match lookup_cur_matched(name, interpolations, repeats) { Some(matched) => match *matched { MatchedNonterminal(_) => LockstepIterSize::Unconstrained, MatchedSeq(ref ads, _) => LockstepIterSize::Constraint(ads.len(), name), }, - _ => LockstepIterSize::Unconstrained - }, + _ => LockstepIterSize::Unconstrained, + } + } TokenTree::Token(..) => LockstepIterSize::Unconstrained, } } From 9a0a87a654303c69856d55dac419a2c440efc3d4 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 6 May 2019 13:02:12 -0700 Subject: [PATCH 101/212] Revert "Disable big-endian simd in swap_nonoverlapping_bytes" This reverts commit 77bd4dc65406ba3cedbc779e6f6280868231912e. Issue #42778 was formerly easy to reproduce on two big-endian targets, `powerpc64` and `s390x`, so we disabled SIMD on this function for all big-endian targets as a workaround. I have re-tested this code on `powerpc64` and `s390x`, each with the bundled LLVM 8 and with external LLVM 7 and LLVM 6, and the problems no longer appear. So it seems safe to remove this workaround, although I'm still a little uncomfortable that we never found a root-cause... --- src/libcore/ptr.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index a41be4269d504..c3f6d7daf2342 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -374,10 +374,7 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) { // #[repr(simd)], even if we don't actually use this struct directly. // // FIXME repr(simd) broken on emscripten and redox - // It's also broken on big-endian powerpc64 and s390x. #42778 - #[cfg_attr(not(any(target_os = "emscripten", target_os = "redox", - target_endian = "big")), - repr(simd))] + #[cfg_attr(not(any(target_os = "emscripten", target_os = "redox")), repr(simd))] struct Block(u64, u64, u64, u64); struct UnalignedBlock(u64, u64, u64, u64); From a416a19153e799dae6679d8672703dbeb48730d5 Mon Sep 17 00:00:00 2001 From: David Wood Date: Mon, 6 May 2019 20:45:47 +0100 Subject: [PATCH 102/212] Add test for current behaviour. This commit adds a test for the current behaviour of signature deduction of generators when there is a type mismatch between the return type of the function body and the signature. --- .../type-mismatch-signature-deduction.rs | 17 ++++++++++++++ .../type-mismatch-signature-deduction.stderr | 23 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 src/test/ui/generator/type-mismatch-signature-deduction.rs create mode 100644 src/test/ui/generator/type-mismatch-signature-deduction.stderr diff --git a/src/test/ui/generator/type-mismatch-signature-deduction.rs b/src/test/ui/generator/type-mismatch-signature-deduction.rs new file mode 100644 index 0000000000000..7774ff48f56b7 --- /dev/null +++ b/src/test/ui/generator/type-mismatch-signature-deduction.rs @@ -0,0 +1,17 @@ +#![feature(generators, generator_trait)] + +use std::ops::Generator; + +fn foo() -> impl Generator { //~ ERROR type mismatch + || { + if false { + return Ok(6); + } + + yield (); + + 5 //~ ERROR mismatched types [E0308] + } +} + +fn main() {} diff --git a/src/test/ui/generator/type-mismatch-signature-deduction.stderr b/src/test/ui/generator/type-mismatch-signature-deduction.stderr new file mode 100644 index 0000000000000..9ebf77a02f5ca --- /dev/null +++ b/src/test/ui/generator/type-mismatch-signature-deduction.stderr @@ -0,0 +1,23 @@ +error[E0308]: mismatched types + --> $DIR/type-mismatch-signature-deduction.rs:13:9 + | +LL | 5 + | ^ expected enum `std::result::Result`, found integer + | + = note: expected type `std::result::Result<{integer}, _>` + found type `{integer}` + +error[E0271]: type mismatch resolving `<[generator@$DIR/type-mismatch-signature-deduction.rs:6:5: 14:6 _] as std::ops::Generator>::Return == i32` + --> $DIR/type-mismatch-signature-deduction.rs:5:13 + | +LL | fn foo() -> impl Generator { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found i32 + | + = note: expected type `std::result::Result<{integer}, _>` + found type `i32` + = note: the return type of a function must have a statically known size + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0271, E0308. +For more information about an error, try `rustc --explain E0271`. From 54430ad53ab00bf86090a8d11844db1c40b2ca24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 6 May 2019 16:00:21 -0700 Subject: [PATCH 103/212] review comments: fix typo and add comments --- src/librustc_typeck/check/mod.rs | 2 +- src/libsyntax/parse/lexer/mod.rs | 2 +- src/libsyntax/parse/mod.rs | 4 ++-- src/libsyntax/parse/parser.rs | 11 +++++++---- src/libsyntax/util/parser.rs | 5 ++++- 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 763d6b898a484..cc73e1753d470 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4174,7 +4174,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { oprnd_t, ); let sp = tcx.sess.source_map().start_point(expr.span); - if let Some(sp) = tcx.sess.parse_sess.abiguous_block_expr_parse + if let Some(sp) = tcx.sess.parse_sess.ambiguous_block_expr_parse .borrow().get(&sp) { tcx.sess.parse_sess.expr_parentheses_needed( diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index e7d79a647d360..4e5a51bdd9afa 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -1918,7 +1918,7 @@ mod tests { raw_identifier_spans: Lock::new(Vec::new()), registered_diagnostics: Lock::new(ErrorMap::new()), buffered_lints: Lock::new(vec![]), - abiguous_block_expr_parse: Lock::new(FxHashMap::default()), + ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), } } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 0d41a1ff84904..0ad6036942280 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -50,7 +50,7 @@ pub struct ParseSess { /// Contains the spans of block expressions that could have been incomplete based on the /// operation token that followed it, but that the parser cannot identify without further /// analysis. - pub abiguous_block_expr_parse: Lock>, + pub ambiguous_block_expr_parse: Lock>, } impl ParseSess { @@ -74,7 +74,7 @@ impl ParseSess { included_mod_stack: Lock::new(vec![]), source_map, buffered_lints: Lock::new(vec![]), - abiguous_block_expr_parse: Lock::new(FxHashMap::default()), + ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 66d45f799d97d..460d829fc0676 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2928,7 +2928,7 @@ impl<'a> Parser<'a> { self.this_token_descr()); let mut err = self.fatal(&msg); let sp = self.sess.source_map().start_point(self.span); - if let Some(sp) = self.sess.abiguous_block_expr_parse.borrow() + if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow() .get(&sp) { self.sess.expr_parentheses_needed(&mut err, *sp, None); @@ -3630,12 +3630,15 @@ impl<'a> Parser<'a> { return Ok(lhs); } (false, _) => {} // continue parsing the expression - (true, Some(AssocOp::Multiply)) | // `{ 42 } *foo = bar;` + // An exhaustive check is done in the following block, but these are checked first + // because they *are* ambiguous but also reasonable looking incorrect syntax, so we + // want to keep their span info to improve diagnostics in these cases in a later stage. + (true, Some(AssocOp::Multiply)) | // `{ 42 } *foo = bar;` or `{ 42 } * 3` (true, Some(AssocOp::Subtract)) | // `{ 42 } -5` (true, Some(AssocOp::Add)) => { // `{ 42 } + 42 // These cases are ambiguous and can't be identified in the parser alone let sp = self.sess.source_map().start_point(self.span); - self.sess.abiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span); + self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span); return Ok(lhs); } (true, Some(ref op)) if !op.can_continue_expr_unambiguously() => { @@ -4968,7 +4971,7 @@ impl<'a> Parser<'a> { let mut err = self.fatal(&msg); err.span_label(self.span, format!("expected {}", expected)); let sp = self.sess.source_map().start_point(self.span); - if let Some(sp) = self.sess.abiguous_block_expr_parse.borrow().get(&sp) { + if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) { self.sess.expr_parentheses_needed(&mut err, *sp, None); } return Err(err); diff --git a/src/libsyntax/util/parser.rs b/src/libsyntax/util/parser.rs index d76dede8155a0..828fbaef98540 100644 --- a/src/libsyntax/util/parser.rs +++ b/src/libsyntax/util/parser.rs @@ -208,6 +208,10 @@ impl AssocOp { } } + /// This operator could be used to follow a block unambiguously. + /// + /// This is used for error recovery at the moment, providing a suggestion to wrap blocks with + /// parentheses while having a high degree of confidence on the correctness of the suggestion. pub fn can_continue_expr_unambiguously(&self) -> bool { use AssocOp::*; match self { @@ -227,7 +231,6 @@ impl AssocOp { Colon => true, // `{ 42 }: usize` _ => false, } - } } From 9a2ee0aaef1dfe835c65359b2b07721953ea7040 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 2 May 2019 05:05:58 +0300 Subject: [PATCH 104/212] serialize: add missing Encodable impl for Path. --- src/libserialize/serialize.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs index 8ef8c2b4c0a22..36a1628014ddb 100644 --- a/src/libserialize/serialize.rs +++ b/src/libserialize/serialize.rs @@ -764,12 +764,18 @@ macro_rules! tuple { tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, } -impl Encodable for path::PathBuf { +impl Encodable for path::Path { fn encode(&self, e: &mut S) -> Result<(), S::Error> { self.to_str().unwrap().encode(e) } } +impl Encodable for path::PathBuf { + fn encode(&self, e: &mut S) -> Result<(), S::Error> { + path::Path::encode(self, e) + } +} + impl Decodable for path::PathBuf { fn decode(d: &mut D) -> Result { let bytes: String = Decodable::decode(d)?; From fc72e56e78742ed2dd93dd7e94f8eb08d7c28bb4 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 6 May 2019 18:19:21 -0700 Subject: [PATCH 105/212] Update cargo --- Cargo.lock | 9 ++++----- src/tools/cargo | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c930b628f4b37..ff66b4a0372ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -271,9 +271,10 @@ dependencies = [ "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "libgit2-sys 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "opener 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opener 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "proptest 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1688,11 +1689,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "opener" -version = "0.3.2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4202,7 +4201,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c281318d992e4432cfa799969467003d05921582a7489a8325e37f8a450d5113" -"checksum opener 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "04b1d6b086d9b3009550f9b6f81b10ad9428cf14f404b8e1a3a06f6f012c8ec9" +"checksum opener 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "998c59e83d9474c01127a96e023b7a04bb061dd286bf8bb939d31dc8d31a7448" "checksum openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ec7bd7ca4cce6dbdc77e7c1230682740d307d1218a87fb0349a571272be749f9" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" "checksum openssl-src 111.1.0+1.1.1a (registry+https://github.com/rust-lang/crates.io-index)" = "26bb632127731bf4ac49bf86a5dde12d2ca0918c2234fc39d79d4da2ccbc6da7" diff --git a/src/tools/cargo b/src/tools/cargo index beb8fcb5248dc..759b6161a328d 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit beb8fcb5248dc2e6aa488af9613216d5ccb31c6a +Subproject commit 759b6161a328db1d4863139e90875308ecd25a75 From f0e43fc98671f76f7cdcc07cfa17fb2362c132ea Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 2 May 2019 05:06:08 +0300 Subject: [PATCH 106/212] compiletest: only use `make_exe_name` for tests that end up being executed. --- .../const-eval/unused-broken-const.stderr | 2 -- src/test/ui/emit-directives.rs | 6 ----- src/test/ui/emit-directives.stderr | 2 +- ...n-projection-output-repeated-supertrait.rs | 3 +++ src/tools/compiletest/src/runtest.rs | 26 +++++++++++++++---- 5 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/test/ui/consts/const-eval/unused-broken-const.stderr b/src/test/ui/consts/const-eval/unused-broken-const.stderr index 603efe449f143..e45ce65d8bb35 100644 --- a/src/test/ui/consts/const-eval/unused-broken-const.stderr +++ b/src/test/ui/consts/const-eval/unused-broken-const.stderr @@ -1,5 +1,3 @@ -warning: due to multiple output types requested, the explicitly specified output file name will be adapted for each output type - error: any use of this value will cause an error --> $DIR/unused-broken-const.rs:5:18 | diff --git a/src/test/ui/emit-directives.rs b/src/test/ui/emit-directives.rs index 088280e358ae7..924569d3e232d 100644 --- a/src/test/ui/emit-directives.rs +++ b/src/test/ui/emit-directives.rs @@ -1,11 +1,5 @@ -// ignore-tidy-linelength // compile-flags:--emit=metadata --error-format=json -Z emit-directives // compile-pass -// -// Normalization is required to eliminated minor path and filename differences -// across platforms. -// normalize-stderr-test: "metadata file written: .*/emit-directives" -> "metadata file written: .../emit-directives" -// normalize-stderr-test: "emit-directives(\.\w*)?/a(\.\w*)?" -> "emit-directives/a" // A very basic test for the emission of build directives in JSON output. diff --git a/src/test/ui/emit-directives.stderr b/src/test/ui/emit-directives.stderr index b8a4b96f4bf25..068745edb8dc0 100644 --- a/src/test/ui/emit-directives.stderr +++ b/src/test/ui/emit-directives.stderr @@ -1 +1 @@ -{"directive":"metadata file written: .../emit-directives/a"} +{"directive":"metadata file written: $TEST_BUILD_DIR/emit-directives/libemit_directives.rmeta"} diff --git a/src/test/ui/traits/trait-object-with-self-in-projection-output-repeated-supertrait.rs b/src/test/ui/traits/trait-object-with-self-in-projection-output-repeated-supertrait.rs index 46c083f930591..3e9f612a2afee 100644 --- a/src/test/ui/traits/trait-object-with-self-in-projection-output-repeated-supertrait.rs +++ b/src/test/ui/traits/trait-object-with-self-in-projection-output-repeated-supertrait.rs @@ -1,5 +1,8 @@ // compile-pass +// FIXME(eddyb) shorten the name so windows doesn't choke on it. +#![crate_name = "trait_test"] + // Regression test related to #56288. Check that a supertrait projection (of // `Output`) that references `Self` is ok if there is another occurence of // the same supertrait that specifies the projection explicitly, even if diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 42f9cdb7886fd..649679e9b3cc0 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1422,10 +1422,21 @@ impl<'test> TestCx<'test> { } fn compile_test(&self) -> ProcRes { - let mut rustc = self.make_compile_args( - &self.testpaths.file, - TargetLocation::ThisFile(self.make_exe_name()), - ); + // Only use `make_exe_name` when the test ends up being executed. + let will_execute = match self.config.mode { + RunPass | Ui => self.should_run_successfully(), + Incremental => self.revision.unwrap().starts_with("r"), + RunFail | RunPassValgrind | MirOpt | + DebugInfoBoth | DebugInfoGdb | DebugInfoLldb => true, + _ => false, + }; + let output_file = if will_execute { + TargetLocation::ThisFile(self.make_exe_name()) + } else { + TargetLocation::ThisDirectory(self.output_base_dir()) + }; + + let mut rustc = self.make_compile_args(&self.testpaths.file, output_file); rustc.arg("-L").arg(&self.aux_output_dir_name()); @@ -1882,7 +1893,12 @@ impl<'test> TestCx<'test> { rustc.arg("-o").arg(path); } TargetLocation::ThisDirectory(path) => { - rustc.arg("--out-dir").arg(path); + if is_rustdoc { + // `rustdoc` uses `-o` for the output directory. + rustc.arg("-o").arg(path); + } else { + rustc.arg("--out-dir").arg(path); + } } } From 1618c079abc7cb97afe3cbcf5a7ff1f9412775bc Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 2 May 2019 05:06:33 +0300 Subject: [PATCH 107/212] rustc: rename -Z emit-directives to -Z emit-artifact-notifications and simplify the output. --- src/librustc/session/config.rs | 4 ++-- src/librustc_errors/emitter.rs | 8 +++++--- src/librustc_errors/lib.rs | 18 ++++++------------ src/librustc_interface/passes.rs | 13 +++++-------- src/libsyntax/json.rs | 13 +++++++------ .../ui/emit-artifact-notifications.nll.stderr | 1 + src/test/ui/emit-artifact-notifications.rs | 6 ++++++ src/test/ui/emit-artifact-notifications.stderr | 1 + src/test/ui/emit-directives.rs | 6 ------ src/test/ui/emit-directives.stderr | 1 - src/tools/compiletest/src/json.rs | 10 +++++----- 11 files changed, 38 insertions(+), 43 deletions(-) create mode 100644 src/test/ui/emit-artifact-notifications.nll.stderr create mode 100644 src/test/ui/emit-artifact-notifications.rs create mode 100644 src/test/ui/emit-artifact-notifications.stderr delete mode 100644 src/test/ui/emit-directives.rs delete mode 100644 src/test/ui/emit-directives.stderr diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 084a5429f26fa..12427daa38381 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1462,8 +1462,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, the same values as the target option of the same name"), allow_features: Option> = (None, parse_opt_comma_list, [TRACKED], "only allow the listed language features to be enabled in code (space separated)"), - emit_directives: bool = (false, parse_bool, [UNTRACKED], - "emit build directives if producing JSON output"), + emit_artifact_notifications: bool = (false, parse_bool, [UNTRACKED], + "emit notifications after each artifact has been output (only in the JSON format)"), } pub fn default_lib_output() -> CrateType { diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index bfc9113c2d41e..59cbd65f05c68 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -16,6 +16,7 @@ use std::borrow::Cow; use std::io::prelude::*; use std::io; use std::cmp::{min, Reverse}; +use std::path::Path; use termcolor::{StandardStream, ColorChoice, ColorSpec, BufferWriter, Ansi}; use termcolor::{WriteColor, Color, Buffer}; @@ -52,9 +53,10 @@ pub trait Emitter { /// Emit a structured diagnostic. fn emit_diagnostic(&mut self, db: &DiagnosticBuilder<'_>); - /// Emit a JSON directive. The default is to do nothing; this should only - /// be emitted with --error-format=json. - fn maybe_emit_json_directive(&mut self, _directive: String) {} + /// Emit a notification that an artifact has been output. + /// This is currently only supported for the JSON format, + /// other formats can, and will, simply ignore it. + fn emit_artifact_notification(&mut self, _path: &Path) {} /// Checks if should show explanations about "rustc --explain" fn should_show_explain(&self) -> bool { diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index e173e1060cc10..3aa87fad07174 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -26,6 +26,7 @@ use std::borrow::Cow; use std::cell::Cell; use std::{error, fmt}; use std::panic; +use std::path::Path; use termcolor::{ColorSpec, Color}; @@ -294,16 +295,9 @@ impl error::Error for ExplicitBug { pub use diagnostic::{Diagnostic, SubDiagnostic, DiagnosticStyledString, DiagnosticId}; pub use diagnostic_builder::DiagnosticBuilder; -/// A handler deals with two kinds of compiler output. -/// - Errors: certain errors (fatal, bug, unimpl) may cause immediate exit, -/// others log errors for later reporting. -/// - Directives: with --error-format=json, the compiler produces directives -/// that indicate when certain actions have completed, which are useful for -/// Cargo. They may change at any time and should not be considered a public -/// API. -/// -/// This crate's name (rustc_errors) doesn't encompass the directives, because -/// directives were added much later. +/// A handler deals with errors and other compiler output. +/// Certain errors (fatal, bug, unimpl) may cause immediate exit, +/// others log errors for later reporting. pub struct Handler { pub flags: HandlerFlags, @@ -775,8 +769,8 @@ impl Handler { } } - pub fn maybe_emit_json_directive(&self, directive: String) { - self.emitter.borrow_mut().maybe_emit_json_directive(directive); + pub fn emit_artifact_notification(&self, path: &Path) { + self.emitter.borrow_mut().emit_artifact_notification(path); } } diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 8543cca1dd545..54b3e73420560 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -1048,14 +1048,11 @@ fn encode_and_write_metadata<'tcx>( tcx.sess.fatal(&format!("couldn't create a temp dir: {}", err)) }); let metadata_filename = emit_metadata(tcx.sess, &metadata, &metadata_tmpdir); - match std::fs::rename(&metadata_filename, &out_filename) { - Ok(_) => { - if tcx.sess.opts.debugging_opts.emit_directives { - tcx.sess.parse_sess.span_diagnostic.maybe_emit_json_directive( - format!("metadata file written: {}", out_filename.display())); - } - } - Err(e) => tcx.sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e)), + if let Err(e) = fs::rename(&metadata_filename, &out_filename) { + tcx.sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e)); + } + if tcx.sess.opts.debugging_opts.emit_artifact_notifications { + tcx.sess.parse_sess.span_diagnostic.emit_artifact_notification(&out_filename); } } diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs index 65f8d0e77d7be..2dd2ecb749300 100644 --- a/src/libsyntax/json.rs +++ b/src/libsyntax/json.rs @@ -19,6 +19,7 @@ use errors::emitter::{Emitter, HumanReadableErrorType}; use syntax_pos::{MacroBacktrace, Span, SpanLabel, MultiSpan}; use rustc_data_structures::sync::{self, Lrc}; use std::io::{self, Write}; +use std::path::Path; use std::vec; use std::sync::{Arc, Mutex}; @@ -91,15 +92,15 @@ impl Emitter for JsonEmitter { } } - fn maybe_emit_json_directive(&mut self, directive: String) { - let data = Directive { directive }; + fn emit_artifact_notification(&mut self, path: &Path) { + let data = ArtifactNotification { artifact: path }; let result = if self.pretty { writeln!(&mut self.dst, "{}", as_pretty_json(&data)) } else { writeln!(&mut self.dst, "{}", as_json(&data)) }; if let Err(e) = result { - panic!("failed to print message: {:?}", e); + panic!("failed to print notification: {:?}", e); } } } @@ -181,9 +182,9 @@ struct DiagnosticCode { } #[derive(RustcEncodable)] -struct Directive { - /// The directive itself. - directive: String, +struct ArtifactNotification<'a> { + /// The path of the artifact. + artifact: &'a Path, } impl Diagnostic { diff --git a/src/test/ui/emit-artifact-notifications.nll.stderr b/src/test/ui/emit-artifact-notifications.nll.stderr new file mode 100644 index 0000000000000..347d9aeac2307 --- /dev/null +++ b/src/test/ui/emit-artifact-notifications.nll.stderr @@ -0,0 +1 @@ +{"artifact":"$TEST_BUILD_DIR/emit-artifact-notifications.nll/libemit_artifact_notifications.rmeta"} diff --git a/src/test/ui/emit-artifact-notifications.rs b/src/test/ui/emit-artifact-notifications.rs new file mode 100644 index 0000000000000..c2c930c8b1bae --- /dev/null +++ b/src/test/ui/emit-artifact-notifications.rs @@ -0,0 +1,6 @@ +// compile-flags:--emit=metadata --error-format=json -Z emit-artifact-notifications +// compile-pass + +// A very basic test for the emission of artifact notifications in JSON output. + +fn main() {} diff --git a/src/test/ui/emit-artifact-notifications.stderr b/src/test/ui/emit-artifact-notifications.stderr new file mode 100644 index 0000000000000..56c977181ff51 --- /dev/null +++ b/src/test/ui/emit-artifact-notifications.stderr @@ -0,0 +1 @@ +{"artifact":"$TEST_BUILD_DIR/emit-artifact-notifications/libemit_artifact_notifications.rmeta"} diff --git a/src/test/ui/emit-directives.rs b/src/test/ui/emit-directives.rs deleted file mode 100644 index 924569d3e232d..0000000000000 --- a/src/test/ui/emit-directives.rs +++ /dev/null @@ -1,6 +0,0 @@ -// compile-flags:--emit=metadata --error-format=json -Z emit-directives -// compile-pass - -// A very basic test for the emission of build directives in JSON output. - -fn main() {} diff --git a/src/test/ui/emit-directives.stderr b/src/test/ui/emit-directives.stderr deleted file mode 100644 index 068745edb8dc0..0000000000000 --- a/src/test/ui/emit-directives.stderr +++ /dev/null @@ -1 +0,0 @@ -{"directive":"metadata file written: $TEST_BUILD_DIR/emit-directives/libemit_directives.rmeta"} diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs index 26a3c4dee40aa..d651b9a92b649 100644 --- a/src/tools/compiletest/src/json.rs +++ b/src/tools/compiletest/src/json.rs @@ -4,7 +4,7 @@ use crate::errors::{Error, ErrorKind}; use crate::runtest::ProcRes; use serde_json; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::str::FromStr; #[derive(Deserialize)] @@ -18,9 +18,9 @@ struct Diagnostic { } #[derive(Deserialize)] -struct Directive { +struct ArtifactNotification { #[allow(dead_code)] - directive: String, + artifact: PathBuf, } #[derive(Deserialize, Clone)] @@ -75,8 +75,8 @@ pub fn extract_rendered(output: &str) -> String { if line.starts_with('{') { if let Ok(diagnostic) = serde_json::from_str::(line) { diagnostic.rendered - } else if let Ok(_directive) = serde_json::from_str::(line) { - // Swallow the directive. + } else if let Ok(_) = serde_json::from_str::(line) { + // Ignore the notification. None } else { print!( From bb1c67dde4ef2936b4f9b39cf4963584608d3c12 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 2 May 2019 05:49:57 +0300 Subject: [PATCH 108/212] rustc_codegen_ssa: emit artifact notifications for the main link product too. --- src/librustc_codegen_ssa/back/link.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index f25891d77ce53..8a751b02b78dd 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -95,6 +95,9 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(sess: &'a Session, ); } } + if sess.opts.debugging_opts.emit_artifact_notifications { + sess.parse_sess.span_diagnostic.emit_artifact_notification(&out_filename); + } } if sess.opts.cg.save_temps { From 2e789b9f0dd4d288e09881c1152f30a9fb456f75 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Sun, 5 May 2019 17:23:47 -0700 Subject: [PATCH 109/212] Add test for #59972 --- src/test/run-pass/generator/issue-59972.rs | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/test/run-pass/generator/issue-59972.rs diff --git a/src/test/run-pass/generator/issue-59972.rs b/src/test/run-pass/generator/issue-59972.rs new file mode 100644 index 0000000000000..995da4fb3ff3c --- /dev/null +++ b/src/test/run-pass/generator/issue-59972.rs @@ -0,0 +1,23 @@ +// compile-flags: --edition=2018 + +#![feature(async_await, await_macro)] + +pub enum Uninhabited { } + +fn uninhabited_async() -> Uninhabited { + unreachable!() +} + +async fn noop() { } + +#[allow(unused)] +async fn contains_never() { + let error = uninhabited_async(); + await!(noop()); + let error2 = error; +} + +#[allow(unused_must_use)] +fn main() { + contains_never(); +} From c89a13179ea1d8431868508d79d57ab3c6ce0ac7 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 7 May 2019 04:49:26 +0300 Subject: [PATCH 110/212] compiletest: uniformly normalize paths, so they all work on all platforms. --- src/tools/compiletest/src/runtest.rs | 32 +++++++++++++--------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 649679e9b3cc0..0e4946736fb7c 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -3154,42 +3154,40 @@ impl<'test> TestCx<'test> { } fn normalize_output(&self, output: &str, custom_rules: &[(String, String)]) -> String { - let parent_dir = self.testpaths.file.parent().unwrap(); let cflags = self.props.compile_flags.join(" "); let json = cflags.contains("--error-format json") || cflags.contains("--error-format pretty-json") || cflags.contains("--error-format=json") || cflags.contains("--error-format=pretty-json"); - let parent_dir_str = if json { - parent_dir.display().to_string().replace("\\", "\\\\") - } else { - parent_dir.display().to_string() + + let mut normalized = output.to_string(); + + let mut normalize_path = |from: &Path, to: &str| { + let mut from = from.display().to_string(); + if json { + from = from.replace("\\", "\\\\"); + } + normalized = normalized.replace(&from, to); }; - let mut normalized = output.replace(&parent_dir_str, "$DIR"); + let parent_dir = self.testpaths.file.parent().unwrap(); + normalize_path(parent_dir, "$DIR"); // Paths into the libstd/libcore let src_dir = self.config.src_base.parent().unwrap().parent().unwrap(); - let src_dir_str = if json { - src_dir.display().to_string().replace("\\", "\\\\") - } else { - src_dir.display().to_string() - }; - normalized = normalized.replace(&src_dir_str, "$SRC_DIR"); + normalize_path(src_dir, "$SRC_DIR"); // Paths into the build directory let test_build_dir = &self.config.build_base; let parent_build_dir = test_build_dir.parent().unwrap().parent().unwrap().parent().unwrap(); // eg. /home/user/rust/build/x86_64-unknown-linux-gnu/test/ui - normalized = normalized.replace(test_build_dir.to_str().unwrap(), "$TEST_BUILD_DIR"); + normalize_path(test_build_dir, "$TEST_BUILD_DIR"); // eg. /home/user/rust/build - normalized = normalized.replace(&parent_build_dir.to_str().unwrap(), "$BUILD_DIR"); + normalize_path(parent_build_dir, "$BUILD_DIR"); // Paths into lib directory. - let mut lib_dir = parent_build_dir.parent().unwrap().to_path_buf(); - lib_dir.push("lib"); - normalized = normalized.replace(&lib_dir.to_str().unwrap(), "$LIB_DIR"); + normalize_path(&parent_build_dir.parent().unwrap().join("lib"), "$LIB_DIR"); if json { // escaped newlines in json strings should be readable From f2919a31c8101da2dd773ea5ffca4195e96d3d50 Mon Sep 17 00:00:00 2001 From: David Wood Date: Mon, 6 May 2019 22:56:47 +0100 Subject: [PATCH 111/212] Trust signature over return expr for generators. This commit extends the logic used to determine what the expected signature of a closure is so that it can also determine the expected signature of a generator. This improves a diagnostic where the fn signature was blamed instead of the generator body. It doesn't fix fix the diagnostic for `async fn`. --- src/librustc_typeck/check/closure.rs | 49 ++++++++++++------- .../generator-yielding-or-returning-itself.rs | 2 +- ...erator-yielding-or-returning-itself.stderr | 24 +++++---- .../type-mismatch-signature-deduction.rs | 6 +-- .../type-mismatch-signature-deduction.stderr | 25 +++------- 5 files changed, 53 insertions(+), 53 deletions(-) diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 838874cc2bf07..3fa192f16f32e 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -246,7 +246,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } /// Given a projection like "::Result == Y", we can deduce - /// everything we need to know about a closure. + /// everything we need to know about a closure or generator. /// /// The `cause_span` should be the span that caused us to /// have this expected signature, or `None` if we can't readily @@ -262,37 +262,50 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let trait_ref = projection.to_poly_trait_ref(tcx); - if tcx.lang_items().fn_trait_kind(trait_ref.def_id()).is_none() { + let is_fn = tcx.lang_items().fn_trait_kind(trait_ref.def_id()).is_some(); + let gen_trait = tcx.lang_items().gen_trait().unwrap(); + let is_gen = gen_trait == trait_ref.def_id(); + if !is_fn && !is_gen { + debug!("deduce_sig_from_projection: not fn or generator"); return None; } - let arg_param_ty = trait_ref.skip_binder().substs.type_at(1); - let arg_param_ty = self.resolve_type_vars_if_possible(&arg_param_ty); - debug!( - "deduce_sig_from_projection: arg_param_ty {:?}", - arg_param_ty - ); + if is_gen { + // Check that we deduce the signature from the `<_ as std::ops::Generator>::Return` + // associated item and not yield. + let return_assoc_item = self.tcx.associated_items(gen_trait).nth(1).unwrap().def_id; + if return_assoc_item != projection.projection_def_id() { + debug!("deduce_sig_from_projection: not return assoc item of generator"); + return None; + } + } + + let input_tys = if is_fn { + let arg_param_ty = trait_ref.skip_binder().substs.type_at(1); + let arg_param_ty = self.resolve_type_vars_if_possible(&arg_param_ty); + debug!("deduce_sig_from_projection: arg_param_ty={:?}", arg_param_ty); - let input_tys = match arg_param_ty.sty { - ty::Tuple(tys) => tys.into_iter().map(|k| k.expect_ty()), - _ => return None, + match arg_param_ty.sty { + ty::Tuple(tys) => tys.into_iter().map(|k| k.expect_ty()).collect::>(), + _ => return None, + } + } else { + // Generators cannot have explicit arguments. + vec![] }; let ret_param_ty = projection.skip_binder().ty; let ret_param_ty = self.resolve_type_vars_if_possible(&ret_param_ty); - debug!( - "deduce_sig_from_projection: ret_param_ty {:?}", - ret_param_ty - ); + debug!("deduce_sig_from_projection: ret_param_ty={:?}", ret_param_ty); let sig = self.tcx.mk_fn_sig( - input_tys, - ret_param_ty, + input_tys.iter(), + &ret_param_ty, false, hir::Unsafety::Normal, Abi::Rust, ); - debug!("deduce_sig_from_projection: sig {:?}", sig); + debug!("deduce_sig_from_projection: sig={:?}", sig); Some(ExpectedSig { cause_span, sig }) } diff --git a/src/test/ui/generator-yielding-or-returning-itself.rs b/src/test/ui/generator-yielding-or-returning-itself.rs index 30788e3c1864b..fd52667981873 100644 --- a/src/test/ui/generator-yielding-or-returning-itself.rs +++ b/src/test/ui/generator-yielding-or-returning-itself.rs @@ -13,7 +13,7 @@ pub fn want_cyclic_generator_return(_: T) fn supply_cyclic_generator_return() { want_cyclic_generator_return(|| { - //~^ ERROR type mismatch + //~^ ERROR closure/generator type that references itself if false { yield None.unwrap(); } None.unwrap() }) diff --git a/src/test/ui/generator-yielding-or-returning-itself.stderr b/src/test/ui/generator-yielding-or-returning-itself.stderr index 5834aed2450b1..42591683fe4e3 100644 --- a/src/test/ui/generator-yielding-or-returning-itself.stderr +++ b/src/test/ui/generator-yielding-or-returning-itself.stderr @@ -1,20 +1,17 @@ -error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 19:6 _] as std::ops::Generator>::Return == [generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 19:6 _]` - --> $DIR/generator-yielding-or-returning-itself.rs:15:5 +error[E0644]: closure/generator type that references itself + --> $DIR/generator-yielding-or-returning-itself.rs:15:34 | -LL | want_cyclic_generator_return(|| { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size +LL | want_cyclic_generator_return(|| { + | __________________________________^ +LL | | +LL | | if false { yield None.unwrap(); } +LL | | None.unwrap() +LL | | }) + | |_____^ cyclic type of infinite size | = note: closures cannot capture themselves or take themselves as argument; this error may be the result of a recent compiler bug-fix, see https://github.com/rust-lang/rust/issues/46062 for more details -note: required by `want_cyclic_generator_return` - --> $DIR/generator-yielding-or-returning-itself.rs:9:1 - | -LL | / pub fn want_cyclic_generator_return(_: T) -LL | | where T: Generator -LL | | { -LL | | } - | |_^ error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 32:6 _] as std::ops::Generator>::Yield == [generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 32:6 _]` --> $DIR/generator-yielding-or-returning-itself.rs:28:5 @@ -36,4 +33,5 @@ LL | | } error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0271`. +Some errors have detailed explanations: E0271, E0644. +For more information about an error, try `rustc --explain E0271`. diff --git a/src/test/ui/generator/type-mismatch-signature-deduction.rs b/src/test/ui/generator/type-mismatch-signature-deduction.rs index 7774ff48f56b7..b9c6bc5d0796e 100644 --- a/src/test/ui/generator/type-mismatch-signature-deduction.rs +++ b/src/test/ui/generator/type-mismatch-signature-deduction.rs @@ -2,15 +2,15 @@ use std::ops::Generator; -fn foo() -> impl Generator { //~ ERROR type mismatch +fn foo() -> impl Generator { || { if false { - return Ok(6); + return Ok(6); //~ ERROR mismatched types [E0308] } yield (); - 5 //~ ERROR mismatched types [E0308] + 5 } } diff --git a/src/test/ui/generator/type-mismatch-signature-deduction.stderr b/src/test/ui/generator/type-mismatch-signature-deduction.stderr index 9ebf77a02f5ca..35d3f95c3e9e4 100644 --- a/src/test/ui/generator/type-mismatch-signature-deduction.stderr +++ b/src/test/ui/generator/type-mismatch-signature-deduction.stderr @@ -1,23 +1,12 @@ error[E0308]: mismatched types - --> $DIR/type-mismatch-signature-deduction.rs:13:9 + --> $DIR/type-mismatch-signature-deduction.rs:8:20 | -LL | 5 - | ^ expected enum `std::result::Result`, found integer +LL | return Ok(6); + | ^^^^^ expected i32, found enum `std::result::Result` | - = note: expected type `std::result::Result<{integer}, _>` - found type `{integer}` + = note: expected type `i32` + found type `std::result::Result<{integer}, _>` -error[E0271]: type mismatch resolving `<[generator@$DIR/type-mismatch-signature-deduction.rs:6:5: 14:6 _] as std::ops::Generator>::Return == i32` - --> $DIR/type-mismatch-signature-deduction.rs:5:13 - | -LL | fn foo() -> impl Generator { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found i32 - | - = note: expected type `std::result::Result<{integer}, _>` - found type `i32` - = note: the return type of a function must have a statically known size - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0271, E0308. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0308`. From d5e819015f550bedb27bc287f96f3937bb831cd5 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 7 May 2019 13:32:07 +0200 Subject: [PATCH 112/212] Add a `cast` method to raw pointers. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is similar to `NonNull::cast`. Compared to the `as` operator (which has a wide range of meanings depending on the input and output types), a call to this method: * Can only go from a raw pointer to a raw pointer * Cannot change the pointer’s `const`ness … even when the pointed types are inferred based on context. --- src/libcore/ptr.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index a41be4269d504..6355bcdcab2fa 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -974,6 +974,13 @@ impl *const T { (self as *const u8) == null() } + /// Cast to a pointer to a different type + #[unstable(feature = "ptr_cast", issue = "60602")] + #[inline] + pub const fn cast(self) -> *const U { + self as _ + } + /// Returns `None` if the pointer is null, or else returns a reference to /// the value wrapped in `Some`. /// @@ -1593,6 +1600,13 @@ impl *mut T { (self as *mut u8) == null_mut() } + /// Cast to a pointer to a different type + #[unstable(feature = "ptr_cast", issue = "60602")] + #[inline] + pub const fn cast(self) -> *mut U { + self as _ + } + /// Returns `None` if the pointer is null, or else returns a reference to /// the value wrapped in `Some`. /// From 1516087ca91f0aa8c9f4f8cb0aa6ff48862043c4 Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Mon, 29 Apr 2019 16:57:29 -0400 Subject: [PATCH 113/212] add negative tests for OS X LLVM target changes --- .../i686-no-macosx-deployment-target.rs | 26 +++++++++++++++++++ .../x86_64-no-macosx-deployment-target.rs | 26 +++++++++++++++++++ src/tools/compiletest/src/header.rs | 8 ++++++ src/tools/compiletest/src/runtest.rs | 3 +++ 4 files changed, 63 insertions(+) create mode 100644 src/test/codegen/i686-no-macosx-deployment-target.rs create mode 100644 src/test/codegen/x86_64-no-macosx-deployment-target.rs diff --git a/src/test/codegen/i686-no-macosx-deployment-target.rs b/src/test/codegen/i686-no-macosx-deployment-target.rs new file mode 100644 index 0000000000000..eb826590523b7 --- /dev/null +++ b/src/test/codegen/i686-no-macosx-deployment-target.rs @@ -0,0 +1,26 @@ +// +// Checks that we leave the target alone MACOSX_DEPLOYMENT_TARGET is unset. +// See issue #60235. + +// compile-flags: -O --target=i686-apple-darwin --crate-type=rlib +// unset-rustc-env:MACOSX_DEPLOYMENT_TARGET +#![feature(no_core, lang_items)] +#![no_core] + +#[lang="sized"] +trait Sized { } +#[lang="freeze"] +trait Freeze { } +#[lang="copy"] +trait Copy { } + +#[repr(C)] +pub struct Bool { + b: bool, +} + +// CHECK: target triple = "i686-apple-darwin" +#[no_mangle] +pub extern "C" fn structbool() -> Bool { + Bool { b: true } +} diff --git a/src/test/codegen/x86_64-no-macosx-deployment-target.rs b/src/test/codegen/x86_64-no-macosx-deployment-target.rs new file mode 100644 index 0000000000000..58a11d1095bbe --- /dev/null +++ b/src/test/codegen/x86_64-no-macosx-deployment-target.rs @@ -0,0 +1,26 @@ +// +// Checks that we leave the target alone when MACOSX_DEPLOYMENT_TARGET is unset. +// See issue #60235. + +// compile-flags: -O --target=x86_64-apple-darwin --crate-type=rlib +// unset-rustc-env:MACOSX_DEPLOYMENT_TARGET +#![feature(no_core, lang_items)] +#![no_core] + +#[lang="sized"] +trait Sized { } +#[lang="freeze"] +trait Freeze { } +#[lang="copy"] +trait Copy { } + +#[repr(C)] +pub struct Bool { + b: bool, +} + +// CHECK: target triple = "x86_64-apple-darwin" +#[no_mangle] +pub extern "C" fn structbool() -> Bool { + Bool { b: true } +} diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index fb6ada89171ab..54e9b76a21ee0 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -305,6 +305,9 @@ pub struct TestProps { pub extern_private: Vec, // Environment settings to use for compiling pub rustc_env: Vec<(String, String)>, + // Environment variables to unset prior to compiling. + // Variables are unset before applying 'rustc_env'. + pub unset_rustc_env: Vec, // Environment settings to use during execution pub exec_env: Vec<(String, String)>, // Lines to check if they appear in the expected debugger output @@ -373,6 +376,7 @@ impl TestProps { extern_private: vec![], revisions: vec![], rustc_env: vec![], + unset_rustc_env: vec![], exec_env: vec![], check_lines: vec![], build_aux_docs: false, @@ -499,6 +503,10 @@ impl TestProps { self.rustc_env.push(ee); } + if let Some(ev) = config.parse_name_value_directive(ln, "unset-rustc-env") { + self.unset_rustc_env.push(ev); + } + if let Some(cl) = config.parse_check_line(ln) { self.check_lines.push(cl); } diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 42f9cdb7886fd..d3e39867a311f 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1692,6 +1692,9 @@ impl<'test> TestCx<'test> { add_extern_priv(&private_lib, true); } + self.props.unset_rustc_env.clone() + .iter() + .fold(&mut rustc, |rustc, v| rustc.env_remove(v)); rustc.envs(self.props.rustc_env.clone()); self.compose_and_run( rustc, From 97ba4c95d00108ac79c86d2bbc6834b1fef008a2 Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Thu, 25 Apr 2019 16:04:37 -0400 Subject: [PATCH 114/212] choose a more specific LLVM target on OS X when necessary This behavior matches clang's behavior, and makes cross-language LTO possible. Fixes #60235. --- src/librustc_metadata/creader.rs | 4 +-- src/librustc_target/spec/apple_base.rs | 32 +++++++++++++++---- src/librustc_target/spec/i686_apple_darwin.rs | 8 ++++- .../spec/x86_64_apple_darwin.rs | 10 ++++-- .../codegen/i686-macosx-deployment-target.rs | 26 +++++++++++++++ .../x86_64-macosx-deployment-target.rs | 26 +++++++++++++++ 6 files changed, 94 insertions(+), 12 deletions(-) create mode 100644 src/test/codegen/i686-macosx-deployment-target.rs create mode 100644 src/test/codegen/x86_64-macosx-deployment-target.rs diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 160d4c30c0bad..c47d7d85a3769 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -783,7 +783,7 @@ impl<'a> CrateLoader<'a> { Sanitizer::Leak => LSAN_SUPPORTED_TARGETS, Sanitizer::Memory => MSAN_SUPPORTED_TARGETS, }; - if !supported_targets.contains(&&*self.sess.target.target.llvm_target) { + if !supported_targets.contains(&&*self.sess.opts.target_triple.triple()) { self.sess.err(&format!("{:?}Sanitizer only works with the `{}` target", sanitizer, supported_targets.join("` or `") @@ -794,7 +794,7 @@ impl<'a> CrateLoader<'a> { // firstyear 2017 - during testing I was unable to access an OSX machine // to make this work on different crate types. As a result, today I have // only been able to test and support linux as a target. - if self.sess.target.target.llvm_target == "x86_64-unknown-linux-gnu" { + if self.sess.opts.target_triple.triple() == "x86_64-unknown-linux-gnu" { if !self.sess.crate_types.borrow().iter().all(|ct| { match *ct { // Link the runtime diff --git a/src/librustc_target/spec/apple_base.rs b/src/librustc_target/spec/apple_base.rs index c21f7f38ca5a3..9dd343b6c8de8 100644 --- a/src/librustc_target/spec/apple_base.rs +++ b/src/librustc_target/spec/apple_base.rs @@ -14,13 +14,7 @@ pub fn opts() -> TargetOptions { // // Here we detect what version is being requested, defaulting to 10.7. ELF // TLS is flagged as enabled if it looks to be supported. - let deployment_target = env::var("MACOSX_DEPLOYMENT_TARGET").ok(); - let version = deployment_target.as_ref().and_then(|s| { - let mut i = s.splitn(2, '.'); - i.next().and_then(|a| i.next().map(|b| (a, b))) - }).and_then(|(a, b)| { - a.parse::().and_then(|a| b.parse::().map(|b| (a, b))).ok() - }).unwrap_or((10, 7)); + let version = macos_deployment_target().unwrap_or((10, 7)); TargetOptions { // macOS has -dead_strip, which doesn't rely on function_sections @@ -40,3 +34,27 @@ pub fn opts() -> TargetOptions { .. Default::default() } } + +fn macos_deployment_target() -> Option<(u32, u32)> { + let deployment_target = env::var("MACOSX_DEPLOYMENT_TARGET").ok(); + let version = deployment_target.as_ref().and_then(|s| { + let mut i = s.splitn(2, '.'); + i.next().and_then(|a| i.next().map(|b| (a, b))) + }).and_then(|(a, b)| { + a.parse::().and_then(|a| b.parse::().map(|b| (a, b))).ok() + }); + + version +} + +pub fn macos_llvm_target(arch: &str) -> String { + let version = macos_deployment_target(); + let llvm_target = match version { + Some((major, minor)) => { + format!("{}-apple-macosx{}.{}.0", arch, major, minor) + }, + None => format!("{}-apple-darwin", arch) + }; + + llvm_target +} diff --git a/src/librustc_target/spec/i686_apple_darwin.rs b/src/librustc_target/spec/i686_apple_darwin.rs index 58c59cc872846..7d804ea53fb31 100644 --- a/src/librustc_target/spec/i686_apple_darwin.rs +++ b/src/librustc_target/spec/i686_apple_darwin.rs @@ -8,8 +8,14 @@ pub fn target() -> TargetResult { base.stack_probes = true; base.eliminate_frame_pointer = false; + // Clang automatically chooses a more specific target based on + // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work + // correctly, we do too. + let arch = "i686"; + let llvm_target = super::apple_base::macos_llvm_target(&arch); + Ok(Target { - llvm_target: "i686-apple-darwin".to_string(), + llvm_target: llvm_target, target_endian: "little".to_string(), target_pointer_width: "32".to_string(), target_c_int_width: "32".to_string(), diff --git a/src/librustc_target/spec/x86_64_apple_darwin.rs b/src/librustc_target/spec/x86_64_apple_darwin.rs index c54181741b3cc..182103440f035 100644 --- a/src/librustc_target/spec/x86_64_apple_darwin.rs +++ b/src/librustc_target/spec/x86_64_apple_darwin.rs @@ -8,13 +8,19 @@ pub fn target() -> TargetResult { base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]); base.stack_probes = true; + // Clang automatically chooses a more specific target based on + // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work + // correctly, we do too. + let arch = "x86_64"; + let llvm_target = super::apple_base::macos_llvm_target(&arch); + Ok(Target { - llvm_target: "x86_64-apple-darwin".to_string(), + llvm_target: llvm_target, target_endian: "little".to_string(), target_pointer_width: "64".to_string(), target_c_int_width: "32".to_string(), data_layout: "e-m:o-i64:64-f80:128-n8:16:32:64-S128".to_string(), - arch: "x86_64".to_string(), + arch: arch.to_string(), target_os: "macos".to_string(), target_env: String::new(), target_vendor: "apple".to_string(), diff --git a/src/test/codegen/i686-macosx-deployment-target.rs b/src/test/codegen/i686-macosx-deployment-target.rs new file mode 100644 index 0000000000000..dad376d6677f7 --- /dev/null +++ b/src/test/codegen/i686-macosx-deployment-target.rs @@ -0,0 +1,26 @@ +// +// Checks that we correctly modify the target when MACOSX_DEPLOYMENT_TARGET is set. +// See issue #60235. + +// compile-flags: -O --target=i686-apple-darwin --crate-type=rlib +// rustc-env:MACOSX_DEPLOYMENT_TARGET=10.9 +#![feature(no_core, lang_items)] +#![no_core] + +#[lang="sized"] +trait Sized { } +#[lang="freeze"] +trait Freeze { } +#[lang="copy"] +trait Copy { } + +#[repr(C)] +pub struct Bool { + b: bool, +} + +// CHECK: target triple = "i686-apple-macosx10.9.0" +#[no_mangle] +pub extern "C" fn structbool() -> Bool { + Bool { b: true } +} diff --git a/src/test/codegen/x86_64-macosx-deployment-target.rs b/src/test/codegen/x86_64-macosx-deployment-target.rs new file mode 100644 index 0000000000000..8e291b7b298d5 --- /dev/null +++ b/src/test/codegen/x86_64-macosx-deployment-target.rs @@ -0,0 +1,26 @@ +// +// Checks that we correctly modify the target when MACOSX_DEPLOYMENT_TARGET is set. +// See issue #60235. + +// compile-flags: -O --target=x86_64-apple-darwin --crate-type=rlib +// rustc-env:MACOSX_DEPLOYMENT_TARGET=10.9 +#![feature(no_core, lang_items)] +#![no_core] + +#[lang="sized"] +trait Sized { } +#[lang="freeze"] +trait Freeze { } +#[lang="copy"] +trait Copy { } + +#[repr(C)] +pub struct Bool { + b: bool, +} + +// CHECK: target triple = "x86_64-apple-macosx10.9.0" +#[no_mangle] +pub extern "C" fn structbool() -> Bool { + Bool { b: true } +} From b98bf88d3244cc5518b6ad9302f179c1e6d11a9e Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 7 May 2019 13:31:12 -0300 Subject: [PATCH 115/212] Be a bit more explicit asserting over the vec rather than the len --- src/libcore/mem.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 95480c6bf048d..ae43a7f5ffa1e 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -666,8 +666,8 @@ pub fn swap(x: &mut T, y: &mut T) { /// let mut v: Vec = vec![1, 2]; /// /// let old_v = mem::replace(&mut v, vec![3, 4, 5]); -/// assert_eq!(2, old_v.len()); -/// assert_eq!(3, v.len()); +/// assert_eq!(vec![1, 2], old_v); +/// assert_eq!(vec![3, 4, 5], v); /// ``` /// /// `replace` allows consumption of a struct field by replacing it with another value. From fe8760cb848d45f5c83b41e689878b893b74e45d Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Thu, 18 Apr 2019 12:55:23 -0700 Subject: [PATCH 116/212] Implement built-in await syntax Adds support for .await under the existing async_await feature gate. Moves macro-like await! syntax to the await_macro feature gate. Removes support for `await` as a non-keyword under the `async_await` feature. --- src/librustc/error_codes.rs | 2 + src/librustc/hir/lowering.rs | 306 ++++++++++++++++-- src/librustc/hir/mod.rs | 4 + src/librustc/ich/impls_syntax.rs | 1 + src/librustc_lint/builtin.rs | 43 +-- src/librustc_mir/hair/pattern/check_match.rs | 6 +- src/libsyntax/ast.rs | 13 + src/libsyntax/feature_gate.rs | 18 ++ src/libsyntax/mut_visit.rs | 1 + src/libsyntax/parse/parser.rs | 17 + src/libsyntax/parse/token.rs | 5 + src/libsyntax/print/pprust.rs | 12 + src/libsyntax/util/parser.rs | 3 + src/libsyntax/visit.rs | 1 + src/libsyntax_pos/hygiene.rs | 2 + src/libsyntax_pos/symbol.rs | 1 + src/test/run-pass/async-await.rs | 36 +-- src/test/run-pass/await-macro.rs | 199 ++++++++++++ src/test/run-pass/issue-55809.rs | 10 +- ...015-edition-error-in-non-macro-position.rs | 36 +++ ...edition-error-in-non-macro-position.stderr | 88 +++++ ...5-edition-no-warnings-with-feature-gate.rs | 16 - ...018-edition-error-in-non-macro-position.rs | 27 ++ ...edition-error-in-non-macro-position.stderr | 80 +++++ .../ui/await-keyword/2018-edition-error.rs | 11 +- .../await-keyword/2018-edition-error.stderr | 46 ++- ...2018-edition-no-error-with-feature-gate.rs | 16 - .../ui/await-keyword/post_expansion_error.rs | 2 +- .../await-keyword/post_expansion_error.stderr | 6 +- src/test/ui/feature-gate/await-macro.rs | 12 + src/test/ui/feature-gate/await-macro.stderr | 12 + .../ui/generator/unresolved_type_param.rs | 11 +- .../ui/generator/unresolved_type_param.stderr | 13 +- src/test/ui/issues/issue-51719.rs | 11 + src/test/ui/issues/issue-51719.stderr | 8 + src/test/ui/issues/issue-51751.rs | 13 + src/test/ui/issues/issue-51751.stderr | 8 + 37 files changed, 931 insertions(+), 165 deletions(-) create mode 100644 src/test/run-pass/await-macro.rs create mode 100644 src/test/ui/await-keyword/2015-edition-error-in-non-macro-position.rs create mode 100644 src/test/ui/await-keyword/2015-edition-error-in-non-macro-position.stderr delete mode 100644 src/test/ui/await-keyword/2015-edition-no-warnings-with-feature-gate.rs create mode 100644 src/test/ui/await-keyword/2018-edition-error-in-non-macro-position.rs create mode 100644 src/test/ui/await-keyword/2018-edition-error-in-non-macro-position.stderr delete mode 100644 src/test/ui/await-keyword/2018-edition-no-error-with-feature-gate.rs create mode 100644 src/test/ui/feature-gate/await-macro.rs create mode 100644 src/test/ui/feature-gate/await-macro.stderr create mode 100644 src/test/ui/issues/issue-51719.rs create mode 100644 src/test/ui/issues/issue-51719.stderr create mode 100644 src/test/ui/issues/issue-51751.rs create mode 100644 src/test/ui/issues/issue-51751.stderr diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index fd089fc688e32..a1bfd417566ad 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -2205,4 +2205,6 @@ register_diagnostics! { E0711, // a feature has been declared with conflicting stability attributes // E0702, // replaced with a generic attribute input check E0726, // non-explicit (not `'_`) elided lifetime in unsupported position + E0727, // `async` generators are not yet supported + E0728, // `await` must be in an `async` function or block } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 36e4195c989c0..20e016b8b5b1e 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -95,6 +95,7 @@ pub struct LoweringContext<'a> { modules: BTreeMap, is_generator: bool, + is_async_body: bool, catch_scopes: Vec, loop_scopes: Vec, @@ -248,6 +249,7 @@ pub fn lower_crate( item_local_id_counters: Default::default(), node_id_to_hir_id: IndexVec::new(), is_generator: false, + is_async_body: false, is_in_trait_impl: false, lifetimes_to_define: Vec::new(), is_collecting_in_band_lifetimes: false, @@ -801,8 +803,17 @@ impl<'a> LoweringContext<'a> { } fn record_body(&mut self, value: hir::Expr, arguments: HirVec) -> hir::BodyId { + if self.is_generator && self.is_async_body { + span_err!( + self.sess, + value.span, + E0727, + "`async` generators are not yet supported", + ); + self.sess.abort_if_errors(); + } let body = hir::Body { - is_generator: self.is_generator, + is_generator: self.is_generator || self.is_async_body, arguments, value, }; @@ -1124,7 +1135,8 @@ impl<'a> LoweringContext<'a> { span: Span, body: impl FnOnce(&mut LoweringContext<'_>) -> hir::Expr, ) -> hir::ExprKind { - let prev_is_generator = mem::replace(&mut self.is_generator, true); + let prev_is_generator = mem::replace(&mut self.is_generator, false); + let prev_is_async_body = mem::replace(&mut self.is_async_body, true); let output = match ret_ty { Some(ty) => FunctionRetTy::Ty(P(ty.clone())), None => FunctionRetTy::Default(span), @@ -1140,6 +1152,7 @@ impl<'a> LoweringContext<'a> { let body_expr = body(self); let body_id = self.record_body(body_expr, arguments); self.is_generator = prev_is_generator; + self.is_async_body = prev_is_async_body; let capture_clause = self.lower_capture_clause(capture_clause); let decl = self.lower_fn_decl(&decl, None, /* impl trait allowed */ false, None); @@ -1167,11 +1180,13 @@ impl<'a> LoweringContext<'a> { where F: FnOnce(&mut LoweringContext<'_>) -> hir::Expr, { - let prev = mem::replace(&mut self.is_generator, false); + let prev_generator = mem::replace(&mut self.is_generator, false); + let prev_async = mem::replace(&mut self.is_async_body, false); let arguments = self.lower_args(decl); let result = f(self); let r = self.record_body(result, arguments); - self.is_generator = prev; + self.is_generator = prev_generator; + self.is_async_body = prev_async; return r; } @@ -4205,6 +4220,7 @@ impl<'a> LoweringContext<'a> { }) }) } + ExprKind::Await(_origin, ref expr) => self.lower_await(e.span, expr), ExprKind::Closure( capture_clause, ref asyncness, movability, ref decl, ref body, fn_decl_span ) => { @@ -4326,12 +4342,13 @@ impl<'a> LoweringContext<'a> { let id = self.next_id(); let e1 = self.lower_expr(e1); let e2 = self.lower_expr(e2); - let ty_path = P(self.std_path(e.span, &["ops", "RangeInclusive"], None, false)); - let ty = P(self.ty_path(id, e.span, hir::QPath::Resolved(None, ty_path))); - let new_seg = P(hir::PathSegment::from_ident(Ident::from_str("new"))); - let new_path = hir::QPath::TypeRelative(ty, new_seg); - let new = P(self.expr(e.span, hir::ExprKind::Path(new_path), ThinVec::new())); - hir::ExprKind::Call(new, hir_vec![e1, e2]) + self.expr_call_std_assoc_fn( + id, + e.span, + &["ops", "RangeInclusive"], + "new", + hir_vec![e1, e2], + ) } ExprKind::Range(ref e1, ref e2, lims) => { use syntax::ast::RangeLimits::*; @@ -4468,9 +4485,7 @@ impl<'a> LoweringContext<'a> { let expr = opt_expr .as_ref() .map(|x| self.lower_expr(x)) - .unwrap_or_else(|| - self.expr(e.span, hir::ExprKind::Tup(hir_vec![]), ThinVec::new()) - ); + .unwrap_or_else(|| self.expr_unit(e.span)); hir::ExprKind::Yield(P(expr)) } @@ -4503,7 +4518,7 @@ impl<'a> LoweringContext<'a> { let body = if let Some(else_expr) = wildcard_arm { P(self.lower_expr(else_expr)) } else { - self.expr_tuple(e.span, hir_vec![]) + P(self.expr_tuple(e.span, hir_vec![])) }; arms.push(self.arm(hir_vec![wildcard_pattern], body)); } @@ -4651,8 +4666,11 @@ impl<'a> LoweringContext<'a> { let iter = P(self.expr_ident(head_sp, iter, iter_pat_nid)); let ref_mut_iter = self.expr_mut_addr_of(head_sp, iter); let next_path = &["iter", "Iterator", "next"]; - let next_path = P(self.expr_std_path(head_sp, next_path, None, ThinVec::new())); - let next_expr = P(self.expr_call(head_sp, next_path, hir_vec![ref_mut_iter])); + let next_expr = P(self.expr_call_std_path( + head_sp, + next_path, + hir_vec![ref_mut_iter], + )); let arms = hir_vec![pat_arm, break_arm]; P(self.expr( @@ -4723,9 +4741,11 @@ impl<'a> LoweringContext<'a> { // `match ::std::iter::IntoIterator::into_iter() { ... }` let into_iter_expr = { let into_iter_path = &["iter", "IntoIterator", "into_iter"]; - let into_iter = P(self.expr_std_path( - head_sp, into_iter_path, None, ThinVec::new())); - P(self.expr_call(head_sp, into_iter, hir_vec![head])) + P(self.expr_call_std_path( + head_sp, + into_iter_path, + hir_vec![head], + )) }; let match_expr = P(self.expr_match( @@ -4778,9 +4798,11 @@ impl<'a> LoweringContext<'a> { let sub_expr = self.lower_expr(sub_expr); let path = &["ops", "Try", "into_result"]; - let path = P(self.expr_std_path( - unstable_span, path, None, ThinVec::new())); - P(self.expr_call(e.span, path, hir_vec![sub_expr])) + P(self.expr_call_std_path( + unstable_span, + path, + hir_vec![sub_expr], + )) }; // `#[allow(unreachable_code)]` @@ -4817,12 +4839,9 @@ impl<'a> LoweringContext<'a> { let err_ident = self.str_to_ident("err"); let (err_local, err_local_nid) = self.pat_ident(try_span, err_ident); let from_expr = { - let path = &["convert", "From", "from"]; - let from = P(self.expr_std_path( - try_span, path, None, ThinVec::new())); + let from_path = &["convert", "From", "from"]; let err_expr = self.expr_ident(try_span, err_ident, err_local_nid); - - self.expr_call(try_span, from, hir_vec![err_expr]) + self.expr_call_std_path(try_span, from_path, hir_vec![err_expr]) }; let from_err_expr = self.wrap_in_try_constructor("from_error", from_expr, unstable_span); @@ -5056,6 +5075,42 @@ impl<'a> LoweringContext<'a> { self.expr(span, hir::ExprKind::Call(e, args), ThinVec::new()) } + // Note: associated functions must use `expr_call_std_path`. + fn expr_call_std_path( + &mut self, + span: Span, + path_components: &[&str], + args: hir::HirVec, + ) -> hir::Expr { + let path = P(self.expr_std_path(span, path_components, None, ThinVec::new())); + self.expr_call(span, path, args) + } + + // Create an expression calling an associated function of an std type. + // + // Associated functions cannot be resolved through the normal `std_path` function, + // as they are resolved differently and so cannot use `expr_call_std_path`. + // + // This function accepts the path component (`ty_path_components`) separately from + // the name of the associated function (`assoc_fn_name`) in order to facilitate + // separate resolution of the type and creation of a path referring to its associated + // function. + fn expr_call_std_assoc_fn( + &mut self, + ty_path_id: hir::HirId, + span: Span, + ty_path_components: &[&str], + assoc_fn_name: &str, + args: hir::HirVec, + ) -> hir::ExprKind { + let ty_path = P(self.std_path(span, ty_path_components, None, false)); + let ty = P(self.ty_path(ty_path_id, span, hir::QPath::Resolved(None, ty_path))); + let fn_seg = P(hir::PathSegment::from_ident(Ident::from_str(assoc_fn_name))); + let fn_path = hir::QPath::TypeRelative(ty, fn_seg); + let fn_expr = P(self.expr(span, hir::ExprKind::Path(fn_path), ThinVec::new())); + hir::ExprKind::Call(fn_expr, args) + } + fn expr_ident(&mut self, span: Span, ident: Ident, binding: hir::HirId) -> hir::Expr { self.expr_ident_with_attrs(span, ident, binding, ThinVec::new()) } @@ -5127,8 +5182,12 @@ impl<'a> LoweringContext<'a> { self.expr(b.span, hir::ExprKind::Block(b, None), attrs) } - fn expr_tuple(&mut self, sp: Span, exprs: hir::HirVec) -> P { - P(self.expr(sp, hir::ExprKind::Tup(exprs), ThinVec::new())) + fn expr_unit(&mut self, sp: Span) -> hir::Expr { + self.expr_tuple(sp, hir_vec![]) + } + + fn expr_tuple(&mut self, sp: Span, exprs: hir::HirVec) -> hir::Expr { + self.expr(sp, hir::ExprKind::Tup(exprs), ThinVec::new()) } fn expr(&mut self, span: Span, node: hir::ExprKind, attrs: ThinVec) -> hir::Expr { @@ -5184,6 +5243,23 @@ impl<'a> LoweringContext<'a> { } } + fn expr_unsafe(&mut self, expr: P) -> hir::Expr { + let hir_id = self.next_id(); + let span = expr.span; + self.expr( + span, + hir::ExprKind::Block(P(hir::Block { + stmts: hir_vec![], + expr: Some(expr), + hir_id, + rules: hir::UnsafeBlock(hir::CompilerGenerated), + span, + targeted_by_break: false, + }), None), + ThinVec::new(), + ) + } + fn pat_ok(&mut self, span: Span, pat: P) -> P { self.pat_std_enum(span, &["result", "Result", "Ok"], hir_vec![pat]) } @@ -5258,13 +5334,12 @@ impl<'a> LoweringContext<'a> { span: Span, components: &[&str], params: Option>, - is_value: bool + is_value: bool, ) -> hir::Path { let mut path = self.resolver .resolve_str_path(span, self.crate_root, components, is_value); path.segments.last_mut().unwrap().args = params; - for seg in path.segments.iter_mut() { if seg.hir_id.is_some() { seg.hir_id = Some(self.next_id()); @@ -5465,6 +5540,175 @@ impl<'a> LoweringContext<'a> { ThinVec::new())); P(self.expr_call(e.span, from_err, hir_vec![e])) } + + fn lower_await( + &mut self, + await_span: Span, + expr: &ast::Expr, + ) -> hir::ExprKind { + // to: + // + // { + // let mut pinned = ; + // loop { + // match ::std::future::poll_with_tls_context(unsafe { + // ::std::pin::Pin::new_unchecked(&mut pinned) + // }) { + // ::std::task::Poll::Ready(x) => break x, + // ::std::task::Poll::Pending => {}, + // } + // yield (); + // } + // } + if !self.is_async_body { + span_err!( + self.sess, + await_span, + E0728, + "`await` is only allowed inside `async` functions and blocks" + ); + self.sess.abort_if_errors(); + } + let span = self.mark_span_with_reason( + CompilerDesugaringKind::Await, + await_span, + None, + ); + let gen_future_span = self.mark_span_with_reason( + CompilerDesugaringKind::Await, + await_span, + Some(vec![Symbol::intern("gen_future")].into()), + ); + + // let mut pinned = ; + let expr = P(self.lower_expr(expr)); + let pinned_ident = self.str_to_ident("pinned"); + let (pinned_pat, pinned_pat_hid) = self.pat_ident_binding_mode( + span, + pinned_ident, + hir::BindingAnnotation::Mutable, + ); + let pinned_let = self.stmt_let_pat( + span, + Some(expr), + pinned_pat, + hir::LocalSource::AwaitDesugar, + ); + + // ::std::future::poll_with_tls_context(unsafe { + // ::std::pin::Pin::new_unchecked(&mut pinned) + // })` + let poll_expr = { + let pinned = P(self.expr_ident(span, pinned_ident, pinned_pat_hid)); + let ref_mut_pinned = self.expr_mut_addr_of(span, pinned); + let pin_ty_id = self.next_id(); + let new_unchecked_expr_kind = self.expr_call_std_assoc_fn( + pin_ty_id, + span, + &["pin", "Pin"], + "new_unchecked", + hir_vec![ref_mut_pinned], + ); + let new_unchecked = P(self.expr(span, new_unchecked_expr_kind, ThinVec::new())); + let unsafe_expr = self.expr_unsafe(new_unchecked); + P(self.expr_call_std_path( + gen_future_span, + &["future", "poll_with_tls_context"], + hir_vec![unsafe_expr], + )) + }; + + // `::std::task::Poll::Ready(x) => break x` + let loop_node_id = self.sess.next_node_id(); + let loop_hir_id = self.lower_node_id(loop_node_id); + let ready_arm = { + let x_ident = self.str_to_ident("x"); + let (x_pat, x_pat_hid) = self.pat_ident(span, x_ident); + let x_expr = P(self.expr_ident(span, x_ident, x_pat_hid)); + let ready_pat = self.pat_std_enum( + span, + &["task", "Poll", "Ready"], + hir_vec![x_pat], + ); + let break_x = self.with_loop_scope(loop_node_id, |this| { + let expr_break = hir::ExprKind::Break( + this.lower_loop_destination(None), + Some(x_expr), + ); + P(this.expr(await_span, expr_break, ThinVec::new())) + }); + self.arm(hir_vec![ready_pat], break_x) + }; + + // `::std::task::Poll::Pending => {}` + let pending_arm = { + let pending_pat = self.pat_std_enum( + span, + &["task", "Poll", "Pending"], + hir_vec![], + ); + let empty_block = P(hir::Block { + stmts: hir_vec![], + expr: None, + hir_id: self.next_id(), + rules: hir::DefaultBlock, + span, + targeted_by_break: false, + }); + let empty_block = P(self.expr_block(empty_block, ThinVec::new())); + self.arm(hir_vec![pending_pat], empty_block) + }; + + let match_stmt = { + let match_expr = P(self.expr_match( + span, + poll_expr, + hir_vec![ready_arm, pending_arm], + hir::MatchSource::AwaitDesugar, + )); + hir::Stmt { + hir_id: self.next_id(), + node: hir::StmtKind::Expr(match_expr), + span, + } + }; + + let yield_stmt = { + let unit = self.expr_unit(span); + let yield_expr = P(self.expr( + span, + hir::ExprKind::Yield(P(unit)), + ThinVec::new(), + )); + hir::Stmt { + hir_id: self.next_id(), + node: hir::StmtKind::Expr(yield_expr), + span, + } + }; + + let loop_block = P(self.block_all( + span, + hir_vec![match_stmt, yield_stmt], + None, + )); + + let loop_expr = P(hir::Expr { + hir_id: loop_hir_id, + node: hir::ExprKind::Loop( + loop_block, + None, + hir::LoopSource::Loop, + ), + span, + attrs: ThinVec::new(), + }); + + hir::ExprKind::Block( + P(self.block_all(span, hir_vec![pinned_let], Some(loop_expr))), + None, + ) + } } fn body_ids(bodies: &BTreeMap) -> Vec { diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 1e357e1341710..01de7917e6e23 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1606,6 +1606,8 @@ pub enum LocalSource { /// } /// ``` AsyncFn, + /// A desugared `.await`. + AwaitDesugar, } /// Hints at the original code for a `match _ { .. }`. @@ -1624,6 +1626,8 @@ pub enum MatchSource { ForLoopDesugar, /// A desugared `?` operator. TryDesugar, + /// A desugared `.await`. + AwaitDesugar, } /// The loop type that yielded an `ExprKind::Loop`. diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index 40cce8e77c0e0..90dd5099cbfd6 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -396,6 +396,7 @@ impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnFormat { impl_stable_hash_for!(enum ::syntax_pos::hygiene::CompilerDesugaringKind { Async, + Await, QuestionMark, ExistentialReturnType, ForLoop, diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index f70429c22b68c..f7a89271ec55f 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -46,7 +46,6 @@ use syntax::symbol::{Symbol, keywords}; use syntax::errors::{Applicability, DiagnosticBuilder}; use syntax::print::pprust::expr_to_string; use syntax::visit::FnKind; -use syntax::struct_span_err; use rustc::hir::{self, GenericParamKind, PatKind}; @@ -1438,15 +1437,10 @@ impl KeywordIdents { UnderMacro(under_macro): UnderMacro, ident: ast::Ident) { - let ident_str = &ident.as_str()[..]; - let cur_edition = cx.sess.edition(); - let is_raw_ident = |ident: ast::Ident| { - cx.sess.parse_sess.raw_identifier_spans.borrow().contains(&ident.span) - }; - let next_edition = match cur_edition { + let next_edition = match cx.sess.edition() { Edition::Edition2015 => { - match ident_str { - "async" | "try" => Edition::Edition2018, + match &ident.as_str()[..] { + "async" | "await" | "try" => Edition::Edition2018, // rust-lang/rust#56327: Conservatively do not // attempt to report occurrences of `dyn` within @@ -1462,43 +1456,16 @@ impl KeywordIdents { // an identifier. "dyn" if !under_macro => Edition::Edition2018, - // Only issue warnings for `await` if the `async_await` - // feature isn't being used. Otherwise, users need - // to keep using `await` for the macro exposed by std. - "await" if !cx.sess.features_untracked().async_await => Edition::Edition2018, _ => return, } } // There are no new keywords yet for the 2018 edition and beyond. - // However, `await` is a "false" keyword in the 2018 edition, - // and can only be used if the `async_await` feature is enabled. - // Otherwise, we emit an error. - _ => { - if "await" == ident_str - && !cx.sess.features_untracked().async_await - && !is_raw_ident(ident) - { - let mut err = struct_span_err!( - cx.sess, - ident.span, - E0721, - "`await` is a keyword in the {} edition", cur_edition, - ); - err.span_suggestion( - ident.span, - "you can use a raw identifier to stay compatible", - "r#await".to_string(), - Applicability::MachineApplicable, - ); - err.emit(); - } - return - }, + _ => return, }; // don't lint `r#foo` - if is_raw_ident(ident) { + if cx.sess.parse_sess.raw_identifier_spans.borrow().contains(&ident.span) { return; } diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index ed183acc93b74..1a7266859ad9f 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -77,6 +77,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> { hir::LocalSource::Normal => "local binding", hir::LocalSource::ForLoopDesugar => "`for` loop binding", hir::LocalSource::AsyncFn => "async fn binding", + hir::LocalSource::AwaitDesugar => "`await` future binding", }); // Check legality of move bindings and `@` patterns. @@ -412,8 +413,9 @@ fn check_arms<'a, 'tcx>( err.emit(); } - // Unreachable patterns in try expressions occur when one of the arms - // are an uninhabited type. Which is OK. + // Unreachable patterns in try and await expressions occur when one of + // the arms are an uninhabited type. Which is OK. + hir::MatchSource::AwaitDesugar | hir::MatchSource::TryDesugar => {} } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 33b8c76bb531a..af2302d24f521 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1065,6 +1065,7 @@ impl Expr { ExprKind::Block(..) => ExprPrecedence::Block, ExprKind::TryBlock(..) => ExprPrecedence::TryBlock, ExprKind::Async(..) => ExprPrecedence::Async, + ExprKind::Await(..) => ExprPrecedence::Await, ExprKind::Assign(..) => ExprPrecedence::Assign, ExprKind::AssignOp(..) => ExprPrecedence::AssignOp, ExprKind::Field(..) => ExprPrecedence::Field, @@ -1186,6 +1187,9 @@ pub enum ExprKind { /// created during lowering cannot be made the parent of any other /// preexisting defs. Async(CaptureBy, NodeId, P), + /// An await expression (`my_future.await`). + Await(AwaitOrigin, P), + /// A try block (`try { ... }`). TryBlock(P), @@ -1287,6 +1291,15 @@ pub enum Movability { Movable, } +/// Whether an `await` comes from `await!` or `.await` syntax. +/// FIXME: this should be removed when support for legacy `await!` is removed. +/// https://github.com/rust-lang/rust/issues/60610 +#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] +pub enum AwaitOrigin { + FieldLike, + MacroLike, +} + pub type Mac = Spanned; /// Represents a macro invocation. The `Path` indicates which macro diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 2a1f3c4801406..dda5ac1f4e16e 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -485,6 +485,10 @@ declare_features! ( // Allows async and await syntax. (active, async_await, "1.28.0", Some(50547), None), + // Allows await! macro-like syntax. + // This will likely be removed prior to stabilization of async/await. + (active, await_macro, "1.28.0", Some(50547), None), + // Allows reinterpretation of the bits of a value of one type as another type during const eval. (active, const_transmute, "1.29.0", Some(53605), None), @@ -2104,6 +2108,20 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::ExprKind::Async(..) => { gate_feature_post!(&self, async_await, e.span, "async blocks are unstable"); } + ast::ExprKind::Await(origin, _) => { + match origin { + ast::AwaitOrigin::FieldLike => + gate_feature_post!(&self, async_await, e.span, "async/await is unstable"), + ast::AwaitOrigin::MacroLike => + gate_feature_post!( + &self, + await_macro, + e.span, + "`await!()` macro syntax is unstable, and will soon be removed \ + in favor of `.await` syntax." + ), + } + } _ => {} } visit::walk_expr(self, e); diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 2e09235ca77b0..6eb8b1b5004c9 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -1185,6 +1185,7 @@ pub fn noop_visit_expr(Expr { node, id, span, attrs }: &mut Expr, vis.visit_id(node_id); vis.visit_block(body); } + ExprKind::Await(_origin, expr) => vis.visit_expr(expr), ExprKind::Assign(el, er) => { vis.visit_expr(el); vis.visit_expr(er); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d46feeab33599..c5d761885657d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2751,6 +2751,14 @@ impl<'a> Parser<'a> { db.span_label(self.span, "expected expression"); db.note("variable declaration using `let` is a statement"); return Err(db); + } else if self.span.rust_2018() && self.eat_keyword(keywords::Await) { + // FIXME: remove this branch when `await!` is no longer supported + // https://github.com/rust-lang/rust/issues/60610 + self.expect(&token::Not)?; + self.expect(&token::OpenDelim(token::Paren))?; + let expr = self.parse_expr()?; + self.expect(&token::CloseDelim(token::Paren))?; + ex = ExprKind::Await(ast::AwaitOrigin::MacroLike, expr); } else if self.token.is_path_start() { let path = self.parse_path(PathStyle::Expr)?; @@ -3014,6 +3022,15 @@ impl<'a> Parser<'a> { // Assuming we have just parsed `.`, continue parsing into an expression. fn parse_dot_suffix(&mut self, self_arg: P, lo: Span) -> PResult<'a, P> { + if self.span.rust_2018() && self.eat_keyword(keywords::Await) { + let span = lo.to(self.prev_span); + let await_expr = self.mk_expr( + span, + ExprKind::Await(ast::AwaitOrigin::FieldLike, self_arg), + ThinVec::new(), + ); + return Ok(await_expr); + } let segment = self.parse_path_segment(PathStyle::Expr)?; self.check_trailing_angle_brackets(&segment, token::OpenDelim(token::Paren)); diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 2fa4f5263fbc5..fd7a39c576daa 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -99,6 +99,11 @@ pub(crate) fn ident_can_begin_expr(ident: ast::Ident, is_raw: bool) -> bool { ident_token.is_path_segment_keyword() || [ keywords::Async.name(), + + // FIXME: remove when `await!(..)` syntax is removed + // https://github.com/rust-lang/rust/issues/60610 + keywords::Await.name(), + keywords::Do.name(), keywords::Box.name(), keywords::Break.name(), diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 6c0fdfaa776f9..682621d40ab65 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2250,6 +2250,18 @@ impl<'a> State<'a> { self.ibox(0)?; self.print_block_with_attrs(blk, attrs)?; } + ast::ExprKind::Await(origin, ref expr) => { + match origin { + ast::AwaitOrigin::MacroLike => { + self.s.word("await!")?; + self.print_expr_maybe_paren(expr, parser::PREC_FORCE_PAREN)?; + } + ast::AwaitOrigin::FieldLike => { + self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX)?; + self.s.word(".await")?; + } + } + } ast::ExprKind::Assign(ref lhs, ref rhs) => { let prec = AssocOp::Assign.precedence() as i8; self.print_expr_maybe_paren(lhs, prec + 1)?; diff --git a/src/libsyntax/util/parser.rs b/src/libsyntax/util/parser.rs index 5f15ede7b0b6a..80dabffaba9f4 100644 --- a/src/libsyntax/util/parser.rs +++ b/src/libsyntax/util/parser.rs @@ -267,6 +267,7 @@ pub enum ExprPrecedence { TryBlock, Struct, Async, + Await, Err, } @@ -301,6 +302,7 @@ impl ExprPrecedence { ExprPrecedence::Unary => PREC_PREFIX, // Unary, postfix + ExprPrecedence::Await | ExprPrecedence::Call | ExprPrecedence::MethodCall | ExprPrecedence::Field | @@ -346,6 +348,7 @@ pub fn contains_exterior_struct_lit(value: &ast::Expr) -> bool { // X { y: 1 } + X { y: 2 } contains_exterior_struct_lit(&lhs) || contains_exterior_struct_lit(&rhs) } + ast::ExprKind::Await(_, ref x) | ast::ExprKind::Unary(_, ref x) | ast::ExprKind::Cast(ref x, _) | ast::ExprKind::Type(ref x, _) | diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index fc99d10b0b6c6..0503e5644dbc5 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -768,6 +768,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { ExprKind::Async(_, _, ref body) => { visitor.visit_block(body); } + ExprKind::Await(_, ref expr) => visitor.visit_expr(expr), ExprKind::Assign(ref left_hand_expression, ref right_hand_expression) => { visitor.visit_expr(left_hand_expression); visitor.visit_expr(right_hand_expression); diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index c806020039d26..a901afdff43e6 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -598,6 +598,7 @@ pub enum CompilerDesugaringKind { /// `impl Trait` with `Foo`. ExistentialReturnType, Async, + Await, ForLoop, } @@ -605,6 +606,7 @@ impl CompilerDesugaringKind { pub fn name(self) -> Symbol { Symbol::intern(match self { CompilerDesugaringKind::Async => "async", + CompilerDesugaringKind::Await => "await", CompilerDesugaringKind::QuestionMark => "?", CompilerDesugaringKind::TryBlock => "try block", CompilerDesugaringKind::ExistentialReturnType => "existential type", diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index cdbfabae7ce1f..20759217b54a0 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -84,6 +84,7 @@ symbols! { // Edition-specific keywords that are used in unstable Rust or reserved for future use. Async: "async", // >= 2018 Edition only + Await: "await", // >= 2018 Edition only Try: "try", // >= 2018 Edition only // Special lifetime names diff --git a/src/test/run-pass/async-await.rs b/src/test/run-pass/async-await.rs index e1b4328debd9a..49fd8b8b1ce27 100644 --- a/src/test/run-pass/async-await.rs +++ b/src/test/run-pass/async-await.rs @@ -1,7 +1,7 @@ // edition:2018 // aux-build:arc_wake.rs -#![feature(async_await, await_macro)] +#![feature(async_await)] extern crate arc_wake; @@ -46,14 +46,14 @@ impl Future for WakeOnceThenComplete { fn async_block(x: u8) -> impl Future { async move { - await!(wake_and_yield_once()); + wake_and_yield_once().await; x } } fn async_block_with_borrow_named_lifetime<'a>(x: &'a u8) -> impl Future + 'a { async move { - await!(wake_and_yield_once()); + wake_and_yield_once().await; *x } } @@ -61,43 +61,43 @@ fn async_block_with_borrow_named_lifetime<'a>(x: &'a u8) -> impl Future impl Future { async move { let future = async { - await!(wake_and_yield_once()); + wake_and_yield_once().await; x }; - await!(future) + future.await } } fn async_closure(x: u8) -> impl Future { (async move |x: u8| -> u8 { - await!(wake_and_yield_once()); + wake_and_yield_once().await; x })(x) } async fn async_fn(x: u8) -> u8 { - await!(wake_and_yield_once()); + wake_and_yield_once().await; x } async fn generic_async_fn(x: T) -> T { - await!(wake_and_yield_once()); + wake_and_yield_once().await; x } async fn async_fn_with_borrow(x: &u8) -> u8 { - await!(wake_and_yield_once()); + wake_and_yield_once().await; *x } async fn async_fn_with_borrow_named_lifetime<'a>(x: &'a u8) -> u8 { - await!(wake_and_yield_once()); + wake_and_yield_once().await; *x } fn async_fn_with_impl_future_named_lifetime<'a>(x: &'a u8) -> impl Future + 'a { async move { - await!(wake_and_yield_once()); + wake_and_yield_once().await; *x } } @@ -110,18 +110,18 @@ async fn async_fn_multiple_args(x: &u8, _y: &u8) -> u8 { */ async fn async_fn_multiple_args_named_lifetime<'a>(x: &'a u8, _y: &'a u8) -> u8 { - await!(wake_and_yield_once()); + wake_and_yield_once().await; *x } fn async_fn_with_internal_borrow(y: u8) -> impl Future { async move { - await!(async_fn_with_borrow_named_lifetime(&y)) + async_fn_with_borrow_named_lifetime(&y).await } } unsafe async fn unsafe_async_fn(x: u8) -> u8 { - await!(wake_and_yield_once()); + wake_and_yield_once().await; x } @@ -134,7 +134,7 @@ trait Bar { impl Foo { async fn async_method(x: u8) -> u8 { unsafe { - await!(unsafe_async_fn(x)) + unsafe_async_fn(x).await } } } @@ -165,7 +165,7 @@ fn main() { ($($fn_name:expr,)*) => { $( test_future_yields_once_then_returns(|x| { async move { - await!($fn_name(&x)) + $fn_name(&x).await } }); )* } @@ -181,7 +181,7 @@ fn main() { Foo::async_method, |x| { async move { - unsafe { await!(unsafe_async_fn(x)) } + unsafe { unsafe_async_fn(x).await } } }, } @@ -192,7 +192,7 @@ fn main() { async_fn_with_impl_future_named_lifetime, |x| { async move { - await!(async_fn_multiple_args_named_lifetime(x, x)) + async_fn_multiple_args_named_lifetime(x, x).await } }, } diff --git a/src/test/run-pass/await-macro.rs b/src/test/run-pass/await-macro.rs new file mode 100644 index 0000000000000..e1b4328debd9a --- /dev/null +++ b/src/test/run-pass/await-macro.rs @@ -0,0 +1,199 @@ +// edition:2018 +// aux-build:arc_wake.rs + +#![feature(async_await, await_macro)] + +extern crate arc_wake; + +use std::pin::Pin; +use std::future::Future; +use std::sync::{ + Arc, + atomic::{self, AtomicUsize}, +}; +use std::task::{Context, Poll}; +use arc_wake::ArcWake; + +struct Counter { + wakes: AtomicUsize, +} + +impl ArcWake for Counter { + fn wake(self: Arc) { + Self::wake_by_ref(&self) + } + fn wake_by_ref(arc_self: &Arc) { + arc_self.wakes.fetch_add(1, atomic::Ordering::SeqCst); + } +} + +struct WakeOnceThenComplete(bool); + +fn wake_and_yield_once() -> WakeOnceThenComplete { WakeOnceThenComplete(false) } + +impl Future for WakeOnceThenComplete { + type Output = (); + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { + if self.0 { + Poll::Ready(()) + } else { + cx.waker().wake_by_ref(); + self.0 = true; + Poll::Pending + } + } +} + +fn async_block(x: u8) -> impl Future { + async move { + await!(wake_and_yield_once()); + x + } +} + +fn async_block_with_borrow_named_lifetime<'a>(x: &'a u8) -> impl Future + 'a { + async move { + await!(wake_and_yield_once()); + *x + } +} + +fn async_nonmove_block(x: u8) -> impl Future { + async move { + let future = async { + await!(wake_and_yield_once()); + x + }; + await!(future) + } +} + +fn async_closure(x: u8) -> impl Future { + (async move |x: u8| -> u8 { + await!(wake_and_yield_once()); + x + })(x) +} + +async fn async_fn(x: u8) -> u8 { + await!(wake_and_yield_once()); + x +} + +async fn generic_async_fn(x: T) -> T { + await!(wake_and_yield_once()); + x +} + +async fn async_fn_with_borrow(x: &u8) -> u8 { + await!(wake_and_yield_once()); + *x +} + +async fn async_fn_with_borrow_named_lifetime<'a>(x: &'a u8) -> u8 { + await!(wake_and_yield_once()); + *x +} + +fn async_fn_with_impl_future_named_lifetime<'a>(x: &'a u8) -> impl Future + 'a { + async move { + await!(wake_and_yield_once()); + *x + } +} + +/* FIXME(cramertj) support when `existential type T<'a, 'b>:;` works +async fn async_fn_multiple_args(x: &u8, _y: &u8) -> u8 { + await!(wake_and_yield_once()); + *x +} +*/ + +async fn async_fn_multiple_args_named_lifetime<'a>(x: &'a u8, _y: &'a u8) -> u8 { + await!(wake_and_yield_once()); + *x +} + +fn async_fn_with_internal_borrow(y: u8) -> impl Future { + async move { + await!(async_fn_with_borrow_named_lifetime(&y)) + } +} + +unsafe async fn unsafe_async_fn(x: u8) -> u8 { + await!(wake_and_yield_once()); + x +} + +struct Foo; + +trait Bar { + fn foo() {} +} + +impl Foo { + async fn async_method(x: u8) -> u8 { + unsafe { + await!(unsafe_async_fn(x)) + } + } +} + +fn test_future_yields_once_then_returns(f: F) +where + F: FnOnce(u8) -> Fut, + Fut: Future, +{ + let mut fut = Box::pin(f(9)); + let counter = Arc::new(Counter { wakes: AtomicUsize::new(0) }); + let waker = ArcWake::into_waker(counter.clone()); + let mut cx = Context::from_waker(&waker); + assert_eq!(0, counter.wakes.load(atomic::Ordering::SeqCst)); + assert_eq!(Poll::Pending, fut.as_mut().poll(&mut cx)); + assert_eq!(1, counter.wakes.load(atomic::Ordering::SeqCst)); + assert_eq!(Poll::Ready(9), fut.as_mut().poll(&mut cx)); +} + +fn main() { + macro_rules! test { + ($($fn_name:expr,)*) => { $( + test_future_yields_once_then_returns($fn_name); + )* } + } + + macro_rules! test_with_borrow { + ($($fn_name:expr,)*) => { $( + test_future_yields_once_then_returns(|x| { + async move { + await!($fn_name(&x)) + } + }); + )* } + } + + test! { + async_block, + async_nonmove_block, + async_closure, + async_fn, + generic_async_fn, + async_fn_with_internal_borrow, + Foo::async_method, + |x| { + async move { + unsafe { await!(unsafe_async_fn(x)) } + } + }, + } + test_with_borrow! { + async_block_with_borrow_named_lifetime, + async_fn_with_borrow, + async_fn_with_borrow_named_lifetime, + async_fn_with_impl_future_named_lifetime, + |x| { + async move { + await!(async_fn_multiple_args_named_lifetime(x, x)) + } + }, + } +} diff --git a/src/test/run-pass/issue-55809.rs b/src/test/run-pass/issue-55809.rs index 12be6582a21e8..b7e60b773b416 100644 --- a/src/test/run-pass/issue-55809.rs +++ b/src/test/run-pass/issue-55809.rs @@ -1,7 +1,7 @@ // edition:2018 // run-pass -#![feature(async_await, await_macro)] +#![feature(async_await)] trait Foo { } @@ -14,15 +14,15 @@ async fn foo_async(_v: T) -> u8 where T: Foo { } async fn bad(v: T) -> u8 where T: Foo { - await!(foo_async(v)) + foo_async(v).await } async fn async_main() { let mut v = (); - let _ = await!(bad(&mut v)); - let _ = await!(foo_async(&mut v)); - let _ = await!(bad(v)); + let _ = bad(&mut v).await; + let _ = foo_async(&mut v).await; + let _ = bad(v).await; } fn main() { diff --git a/src/test/ui/await-keyword/2015-edition-error-in-non-macro-position.rs b/src/test/ui/await-keyword/2015-edition-error-in-non-macro-position.rs new file mode 100644 index 0000000000000..c4f3f3edc486e --- /dev/null +++ b/src/test/ui/await-keyword/2015-edition-error-in-non-macro-position.rs @@ -0,0 +1,36 @@ +#![feature(async_await, await_macro)] +#![allow(non_camel_case_types)] +#![deny(keyword_idents)] + +mod outer_mod { + pub mod await { //~ ERROR `await` is a keyword in the 2018 edition + //~^ WARN this was previously accepted by the compiler + pub struct await; //~ ERROR `await` is a keyword in the 2018 edition + //~^ WARN this was previously accepted by the compiler + } +} +use outer_mod::await::await; //~ ERROR `await` is a keyword in the 2018 edition +//~^ ERROR `await` is a keyword in the 2018 edition +//~^^ WARN this was previously accepted by the compiler +//~^^^ WARN this was previously accepted by the compiler + +struct Foo { await: () } +//~^ ERROR `await` is a keyword in the 2018 edition +//~^^ WARN this was previously accepted by the compiler + +impl Foo { fn await() {} } +//~^ ERROR `await` is a keyword in the 2018 edition +//~^^ WARN this was previously accepted by the compiler + +macro_rules! await { +//~^ ERROR `await` is a keyword in the 2018 edition +//~^^ WARN this was previously accepted by the compiler + () => {} +} + +fn main() { + match await { await => {} } //~ ERROR `await` is a keyword in the 2018 edition + //~^ ERROR `await` is a keyword in the 2018 edition + //~^^ WARN this was previously accepted by the compiler + //~^^^ WARN this was previously accepted by the compiler +} diff --git a/src/test/ui/await-keyword/2015-edition-error-in-non-macro-position.stderr b/src/test/ui/await-keyword/2015-edition-error-in-non-macro-position.stderr new file mode 100644 index 0000000000000..067ecd6a5138d --- /dev/null +++ b/src/test/ui/await-keyword/2015-edition-error-in-non-macro-position.stderr @@ -0,0 +1,88 @@ +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-error-in-non-macro-position.rs:6:13 + | +LL | pub mod await { + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | +note: lint level defined here + --> $DIR/2015-edition-error-in-non-macro-position.rs:3:9 + | +LL | #![deny(keyword_idents)] + | ^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = note: for more information, see issue #49716 + +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-error-in-non-macro-position.rs:8:20 + | +LL | pub struct await; + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = note: for more information, see issue #49716 + +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-error-in-non-macro-position.rs:12:16 + | +LL | use outer_mod::await::await; + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = note: for more information, see issue #49716 + +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-error-in-non-macro-position.rs:12:23 + | +LL | use outer_mod::await::await; + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = note: for more information, see issue #49716 + +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-error-in-non-macro-position.rs:17:14 + | +LL | struct Foo { await: () } + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = note: for more information, see issue #49716 + +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-error-in-non-macro-position.rs:21:15 + | +LL | impl Foo { fn await() {} } + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = note: for more information, see issue #49716 + +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-error-in-non-macro-position.rs:25:14 + | +LL | macro_rules! await { + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = note: for more information, see issue #49716 + +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-error-in-non-macro-position.rs:32:11 + | +LL | match await { await => {} } + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = note: for more information, see issue #49716 + +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-error-in-non-macro-position.rs:32:19 + | +LL | match await { await => {} } + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = note: for more information, see issue #49716 + +error: aborting due to 9 previous errors + diff --git a/src/test/ui/await-keyword/2015-edition-no-warnings-with-feature-gate.rs b/src/test/ui/await-keyword/2015-edition-no-warnings-with-feature-gate.rs deleted file mode 100644 index 92c60e7d6eed0..0000000000000 --- a/src/test/ui/await-keyword/2015-edition-no-warnings-with-feature-gate.rs +++ /dev/null @@ -1,16 +0,0 @@ -// compile-pass - -#![feature(async_await)] -#![allow(non_camel_case_types)] -#![deny(keyword_idents)] - -mod outer_mod { - pub mod await { - pub struct await; - } -} -use outer_mod::await::await; - -fn main() { - match await { await => {} } -} diff --git a/src/test/ui/await-keyword/2018-edition-error-in-non-macro-position.rs b/src/test/ui/await-keyword/2018-edition-error-in-non-macro-position.rs new file mode 100644 index 0000000000000..b2e8e4be17244 --- /dev/null +++ b/src/test/ui/await-keyword/2018-edition-error-in-non-macro-position.rs @@ -0,0 +1,27 @@ +// edition:2018 + +#![allow(non_camel_case_types)] +#![feature(async_await, await_macro)] + +mod outer_mod { + pub mod await { //~ ERROR expected identifier, found reserved keyword `await` + pub struct await; //~ ERROR expected identifier, found reserved keyword `await` + } +} +use self::outer_mod::await::await; //~ ERROR expected identifier, found reserved keyword `await` +//~^ ERROR expected identifier, found reserved keyword `await` + +struct Foo { await: () } +//~^ ERROR expected identifier, found reserved keyword `await` + +impl Foo { fn await() {} } +//~^ ERROR expected identifier, found reserved keyword `await` + +macro_rules! await { +//~^ ERROR expected identifier, found reserved keyword `await` + () => {} +} + +fn main() { + match await { await => () } //~ ERROR expected `!`, found `{` +} diff --git a/src/test/ui/await-keyword/2018-edition-error-in-non-macro-position.stderr b/src/test/ui/await-keyword/2018-edition-error-in-non-macro-position.stderr new file mode 100644 index 0000000000000..076a31bd9ced6 --- /dev/null +++ b/src/test/ui/await-keyword/2018-edition-error-in-non-macro-position.stderr @@ -0,0 +1,80 @@ +error: expected identifier, found reserved keyword `await` + --> $DIR/2018-edition-error-in-non-macro-position.rs:7:13 + | +LL | pub mod await { + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | pub mod r#await { + | ^^^^^^^ + +error: expected identifier, found reserved keyword `await` + --> $DIR/2018-edition-error-in-non-macro-position.rs:8:20 + | +LL | pub struct await; + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | pub struct r#await; + | ^^^^^^^ + +error: expected identifier, found reserved keyword `await` + --> $DIR/2018-edition-error-in-non-macro-position.rs:11:22 + | +LL | use self::outer_mod::await::await; + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | use self::outer_mod::r#await::await; + | ^^^^^^^ + +error: expected identifier, found reserved keyword `await` + --> $DIR/2018-edition-error-in-non-macro-position.rs:11:29 + | +LL | use self::outer_mod::await::await; + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | use self::outer_mod::await::r#await; + | ^^^^^^^ + +error: expected identifier, found reserved keyword `await` + --> $DIR/2018-edition-error-in-non-macro-position.rs:14:14 + | +LL | struct Foo { await: () } + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | struct Foo { r#await: () } + | ^^^^^^^ + +error: expected identifier, found reserved keyword `await` + --> $DIR/2018-edition-error-in-non-macro-position.rs:17:15 + | +LL | impl Foo { fn await() {} } + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | impl Foo { fn r#await() {} } + | ^^^^^^^ + +error: expected identifier, found reserved keyword `await` + --> $DIR/2018-edition-error-in-non-macro-position.rs:20:14 + | +LL | macro_rules! await { + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | macro_rules! r#await { + | ^^^^^^^ + +error: expected `!`, found `{` + --> $DIR/2018-edition-error-in-non-macro-position.rs:26:17 + | +LL | match await { await => () } + | ----- ^ expected `!` + | | + | while parsing this match expression + +error: aborting due to 8 previous errors + diff --git a/src/test/ui/await-keyword/2018-edition-error.rs b/src/test/ui/await-keyword/2018-edition-error.rs index 7ba3382ddf129..e0b2962ce9791 100644 --- a/src/test/ui/await-keyword/2018-edition-error.rs +++ b/src/test/ui/await-keyword/2018-edition-error.rs @@ -2,14 +2,13 @@ #![allow(non_camel_case_types)] mod outer_mod { - pub mod await { //~ ERROR `await` is a keyword - pub struct await; //~ ERROR `await` is a keyword + pub mod await { //~ ERROR expected identifier + pub struct await; //~ ERROR expected identifier } } -use self::outer_mod::await::await; //~ ERROR `await` is a keyword - //~^ ERROR `await` is a keyword +use self::outer_mod::await::await; //~ ERROR expected identifier + //~^ ERROR expected identifier, found reserved keyword `await` fn main() { - match await { await => () } //~ ERROR `await` is a keyword - //~^ ERROR `await` is a keyword + match await { await => () } //~ ERROR expected `!`, found `{` } diff --git a/src/test/ui/await-keyword/2018-edition-error.stderr b/src/test/ui/await-keyword/2018-edition-error.stderr index 67ff6c5675abf..c8bf9b42ca545 100644 --- a/src/test/ui/await-keyword/2018-edition-error.stderr +++ b/src/test/ui/await-keyword/2018-edition-error.stderr @@ -1,38 +1,50 @@ -error[E0721]: `await` is a keyword in the 2018 edition +error: expected identifier, found reserved keyword `await` --> $DIR/2018-edition-error.rs:5:13 | LL | pub mod await { - | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | pub mod r#await { + | ^^^^^^^ -error[E0721]: `await` is a keyword in the 2018 edition +error: expected identifier, found reserved keyword `await` --> $DIR/2018-edition-error.rs:6:20 | LL | pub struct await; - | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | pub struct r#await; + | ^^^^^^^ -error[E0721]: `await` is a keyword in the 2018 edition +error: expected identifier, found reserved keyword `await` --> $DIR/2018-edition-error.rs:9:22 | LL | use self::outer_mod::await::await; - | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | use self::outer_mod::r#await::await; + | ^^^^^^^ -error[E0721]: `await` is a keyword in the 2018 edition +error: expected identifier, found reserved keyword `await` --> $DIR/2018-edition-error.rs:9:29 | LL | use self::outer_mod::await::await; - | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` - -error[E0721]: `await` is a keyword in the 2018 edition - --> $DIR/2018-edition-error.rs:13:11 + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers | -LL | match await { await => () } - | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` +LL | use self::outer_mod::await::r#await; + | ^^^^^^^ -error[E0721]: `await` is a keyword in the 2018 edition - --> $DIR/2018-edition-error.rs:13:19 +error: expected `!`, found `{` + --> $DIR/2018-edition-error.rs:13:17 | LL | match await { await => () } - | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | ----- ^ expected `!` + | | + | while parsing this match expression -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors diff --git a/src/test/ui/await-keyword/2018-edition-no-error-with-feature-gate.rs b/src/test/ui/await-keyword/2018-edition-no-error-with-feature-gate.rs deleted file mode 100644 index 52d32c8351080..0000000000000 --- a/src/test/ui/await-keyword/2018-edition-no-error-with-feature-gate.rs +++ /dev/null @@ -1,16 +0,0 @@ -// compile-pass -// edition:2018 - -#![allow(non_camel_case_types)] -#![feature(async_await)] - -mod outer_mod { - pub mod await { - pub struct await; - } -} -use self::outer_mod::await::await; - -fn main() { - match await { await => () } -} diff --git a/src/test/ui/await-keyword/post_expansion_error.rs b/src/test/ui/await-keyword/post_expansion_error.rs index 96dd48052def8..b4c899b0d0295 100644 --- a/src/test/ui/await-keyword/post_expansion_error.rs +++ b/src/test/ui/await-keyword/post_expansion_error.rs @@ -6,5 +6,5 @@ macro_rules! r#await { fn main() { await!() - //~^ ERROR `await` is a keyword + //~^ ERROR expected expression, found `)` } diff --git a/src/test/ui/await-keyword/post_expansion_error.stderr b/src/test/ui/await-keyword/post_expansion_error.stderr index 9483f77422759..0996c38b3b6c6 100644 --- a/src/test/ui/await-keyword/post_expansion_error.stderr +++ b/src/test/ui/await-keyword/post_expansion_error.stderr @@ -1,8 +1,8 @@ -error[E0721]: `await` is a keyword in the 2018 edition - --> $DIR/post_expansion_error.rs:8:5 +error: expected expression, found `)` + --> $DIR/post_expansion_error.rs:8:12 | LL | await!() - | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | ^ expected expression error: aborting due to previous error diff --git a/src/test/ui/feature-gate/await-macro.rs b/src/test/ui/feature-gate/await-macro.rs new file mode 100644 index 0000000000000..291db9ba41370 --- /dev/null +++ b/src/test/ui/feature-gate/await-macro.rs @@ -0,0 +1,12 @@ +// gate-test-await_macro +// edition:2018 + +#![feature(async_await)] + +async fn bar() {} + +async fn foo() { + await!(bar()); //~ ERROR `await!()` macro syntax is unstable, and will soon be removed +} + +fn main() {} diff --git a/src/test/ui/feature-gate/await-macro.stderr b/src/test/ui/feature-gate/await-macro.stderr new file mode 100644 index 0000000000000..b6833655f6d8a --- /dev/null +++ b/src/test/ui/feature-gate/await-macro.stderr @@ -0,0 +1,12 @@ +error[E0658]: `await!()` macro syntax is unstable, and will soon be removed in favor of `.await` syntax. + --> $DIR/await-macro.rs:9:5 + | +LL | await!(bar()); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/50547 + = help: add #![feature(await_macro)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/generator/unresolved_type_param.rs b/src/test/ui/generator/unresolved_type_param.rs index f49369b125f6f..77174b0321782 100644 --- a/src/test/ui/generator/unresolved_type_param.rs +++ b/src/test/ui/generator/unresolved_type_param.rs @@ -2,13 +2,14 @@ // Error message should pinpoint the type parameter T as needing to be bound // (rather than give a general error message) // edition:2018 -#![feature(futures_api, async_await, await_macro)] +#![feature(async_await)] async fn bar() -> () {} async fn foo() { - await!(bar()); - //~^ ERROR type inside generator must be known in this context - //~| NOTE cannot infer type for `T` - //~| NOTE the type is part of the generator because of this `yield` + bar().await; + //~^ ERROR type inside generator must be known in this context + //~| NOTE cannot infer type for `T` + //~| NOTE the type is part of the generator because of this `yield` + //~| NOTE in this expansion of desugaring of `await` } fn main() {} diff --git a/src/test/ui/generator/unresolved_type_param.stderr b/src/test/ui/generator/unresolved_type_param.stderr index 57ccdda3f43a1..afb9adf4c77cc 100644 --- a/src/test/ui/generator/unresolved_type_param.stderr +++ b/src/test/ui/generator/unresolved_type_param.stderr @@ -1,15 +1,14 @@ error[E0698]: type inside generator must be known in this context - --> $DIR/unresolved_type_param.rs:9:16 + --> $DIR/unresolved_type_param.rs:9:5 | -LL | await!(bar()); - | ^^^ cannot infer type for `T` +LL | bar().await; + | ^^^ cannot infer type for `T` | note: the type is part of the generator because of this `yield` - --> $DIR/unresolved_type_param.rs:9:9 + --> $DIR/unresolved_type_param.rs:9:5 | -LL | await!(bar()); - | ^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) +LL | bar().await; + | ^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-51719.rs b/src/test/ui/issues/issue-51719.rs new file mode 100644 index 0000000000000..2c02ac01142bb --- /dev/null +++ b/src/test/ui/issues/issue-51719.rs @@ -0,0 +1,11 @@ +// edition:2018 +// +// Tests that the .await syntax can't be used to make a generator + +#![feature(async_await)] + +async fn foo() {} + +fn make_generator() { + let _gen = || foo.await; //~ ERROR `await` is only allowed inside `async` functions and blocks +} diff --git a/src/test/ui/issues/issue-51719.stderr b/src/test/ui/issues/issue-51719.stderr new file mode 100644 index 0000000000000..768909b66ec77 --- /dev/null +++ b/src/test/ui/issues/issue-51719.stderr @@ -0,0 +1,8 @@ +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/issue-51719.rs:10:19 + | +LL | let _gen = || foo.await; + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/issues/issue-51751.rs b/src/test/ui/issues/issue-51751.rs new file mode 100644 index 0000000000000..7afd7ecc82649 --- /dev/null +++ b/src/test/ui/issues/issue-51751.rs @@ -0,0 +1,13 @@ +// edition:2018 + +#![feature(async_await)] + +async fn inc(limit: i64) -> i64 { + limit + 1 +} + +fn main() { + let result = inc(10000); + let finished = result.await; + //~^ ERROR `await` is only allowed inside `async` functions and blocks +} diff --git a/src/test/ui/issues/issue-51751.stderr b/src/test/ui/issues/issue-51751.stderr new file mode 100644 index 0000000000000..0c4cb034a9381 --- /dev/null +++ b/src/test/ui/issues/issue-51751.stderr @@ -0,0 +1,8 @@ +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/issue-51751.rs:11:20 + | +LL | let finished = result.await; + | ^^^^^^^^^^^^ + +error: aborting due to previous error + From 606bb6f6fe4cfb6e3054e90cc400553f280ad94a Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Mon, 6 May 2019 16:31:59 -0500 Subject: [PATCH 117/212] avoid extra copy --- src/libsyntax/ext/tt/transcribe.rs | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 5eb5475b2a948..424b94173a7f8 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -98,16 +98,11 @@ pub fn transcribe( }; match tree { - quoted::TokenTree::Sequence(sp, seq) => { - // FIXME(pcwalton): Bad copy. - match lockstep_iter_size( - "ed::TokenTree::Sequence(sp, seq.clone()), - &interpolations, - &repeats, - ) { + seq @ quoted::TokenTree::Sequence(..) => { + match lockstep_iter_size(&seq, interp, &repeats) { LockstepIterSize::Unconstrained => { cx.span_fatal( - sp.entire(), /* blame macro writer */ + seq.span(), /* blame macro writer */ "attempted to repeat an expression \ containing no syntax \ variables matched as repeating at this depth", @@ -115,9 +110,15 @@ pub fn transcribe( } LockstepIterSize::Contradiction(ref msg) => { // FIXME #2887 blame macro invoker instead - cx.span_fatal(sp.entire(), &msg[..]); + cx.span_fatal(seq.span(), &msg[..]); } LockstepIterSize::Constraint(len, _) => { + let (sp, seq) = if let quoted::TokenTree::Sequence(sp, seq) = seq { + (sp, seq) + } else { + unreachable!() + }; + if len == 0 { if seq.op == quoted::KleeneOp::OneOrMore { // FIXME #2887 blame invoker @@ -201,10 +202,8 @@ enum LockstepIterSize { Contradiction(String), } -impl Add for LockstepIterSize { - type Output = LockstepIterSize; - - fn add(self, other: LockstepIterSize) -> LockstepIterSize { +impl LockstepIterSize { + fn with(self, other: LockstepIterSize) -> LockstepIterSize { match self { LockstepIterSize::Unconstrained => other, LockstepIterSize::Contradiction(_) => self, From 5db665b972f7c9578fe0fd2bdb9c7aef6f6db3db Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Mon, 6 May 2019 16:16:23 -0500 Subject: [PATCH 118/212] lots of comments + minor cleanup --- src/libsyntax/ext/tt/macro_parser.rs | 5 +- src/libsyntax/ext/tt/macro_rules.rs | 2 +- src/libsyntax/ext/tt/quoted.rs | 1 + src/libsyntax/ext/tt/transcribe.rs | 147 ++++++++++++++++++++++++--- 4 files changed, 139 insertions(+), 16 deletions(-) diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index ab5823eaca52a..084a69f4cda0f 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -554,7 +554,10 @@ fn inner_parse_loop<'root, 'tt>( match item.top_elts.get_tt(idx) { // Need to descend into a sequence TokenTree::Sequence(sp, seq) => { - // Examine the case where there are 0 matches of this sequence + // Examine the case where there are 0 matches of this sequence. We are + // implicitly disallowing OneOrMore from having 0 matches here. Thus, that will + // result in a "no rules expected token" error by virtue of this matcher not + // working. if seq.op == quoted::KleeneOp::ZeroOrMore || seq.op == quoted::KleeneOp::ZeroOrOne { diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index b1b9d25b3d56b..a53cc2fe66173 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -151,7 +151,7 @@ fn generic_extension<'cx>(cx: &'cx mut ExtCtxt<'_>, let rhs_spans = rhs.iter().map(|t| t.span()).collect::>(); // rhs has holes ( `$id` and `$(...)` that need filled) - let mut tts = transcribe(cx, Some(named_matches), rhs); + let mut tts = transcribe(cx, &named_matches, rhs); // Replace all the tokens for the corresponding positions in the macro, to maintain // proper positions in error reporting, while maintaining the macro_backtrace. diff --git a/src/libsyntax/ext/tt/quoted.rs b/src/libsyntax/ext/tt/quoted.rs index b24edb57e527e..ed8395f11ad50 100644 --- a/src/libsyntax/ext/tt/quoted.rs +++ b/src/libsyntax/ext/tt/quoted.rs @@ -73,6 +73,7 @@ pub enum KleeneOp { ZeroOrMore, /// Kleene plus (`+`) for one or more repetitions OneOrMore, + /// Kleene optional (`?`) for zero or one reptitions ZeroOrOne, } diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 424b94173a7f8..3a40e8403ccff 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -13,7 +13,6 @@ use syntax_pos::DUMMY_SP; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; use std::mem; -use std::ops::Add; use std::rc::Rc; /// An iterator over the token trees in a delimited token tree (`{ ... }`) or a sequence (`$(...)`). @@ -23,6 +22,7 @@ enum Frame { } impl Frame { + /// Construct a new frame around the delimited set of tokens. fn new(tts: Vec) -> Frame { let forest = Lrc::new(quoted::Delimited { delim: token::NoDelim, tts: tts }); Frame::Delimited { forest: forest, idx: 0, span: DelimSpan::dummy() } @@ -46,30 +46,72 @@ impl Iterator for Frame { } } -/// This can do Macro-By-Example transcription. On the other hand, if `src` contains no -/// `TokenTree::{Sequence, MetaVar, MetaVarDecl}`s, `interp` can (and should) be `None`. +/// This can do Macro-By-Example transcription. +/// - `interp` is a map of meta-variables to the tokens (non-terminals) they matched in the +/// invocation. We are assuming we already know there is a match. +/// - `src` is the RHS of the MBE, that is, the "example" we are filling in. +/// +/// For example, +/// +/// ```rust +/// macro_rules! foo { +/// ($id:ident) => { println!("{}", stringify!($id)); } +/// } +/// +/// foo!(bar); +/// ``` +/// +/// `interp` would contain `$id => bar` and `src` would contain `println!("{}", stringify!($id));`. +/// +/// `transcribe` would return a `TokenStream` containing `println!("{}", stringify!(bar));`. +/// +/// Along the way, we do some additional error checking. pub fn transcribe( cx: &ExtCtxt<'_>, - interp: Option>>, + interp: &FxHashMap>, src: Vec, ) -> TokenStream { + assert!(src.len() > 0); + + // We descend into the RHS (`src`), expanding things as we go. This stack contains the things + // we have yet to expand/are still expanding. We start the stack off with the whole RHS. let mut stack: SmallVec<[Frame; 1]> = smallvec![Frame::new(src)]; - let interpolations = interp.unwrap_or_else(FxHashMap::default); /* just a convenience */ + + // As we descend in the RHS, we will need to be able to match nested sequences of matchers. + // `repeats` keeps track of where we are in matching at each level, with the last element being + // the most deeply nested sequence. This is used as a stack. let mut repeats = Vec::new(); + + // `result` contains resulting token stream from the TokenTree we just finished processing. At + // the end, this will contain the full result of transcription, but at arbitrary points during + // `transcribe`, `result` will contain subsets of the final result. + // + // Specifically, as we descend into each TokenTree, we will push the existing results onto the + // `result_stack` and clear `results`. We will then produce the results of transcribing the + // TokenTree into `results`. Then, as we unwind back out of the `TokenTree`, we will pop the + // `result_stack` and append `results` too it to produce the new `results` up to that point. + // + // Thus, if we try to pop the `result_stack` and it is empty, we have reached the top-level + // again, and we are done transcribing. let mut result: Vec = Vec::new(); let mut result_stack = Vec::new(); loop { + // Look at the last frame on the stack. let tree = if let Some(tree) = stack.last_mut().unwrap().next() { + // If it still has a TokenTree we have not looked at yet, use that tree. tree - } else { + } + // The else-case never produces a value for `tree` (it `continue`s or `return`s). + else { + // Otherwise, if we have just reached the end of a sequence and we can keep repeating, + // go back to the beginning of the sequence. if let Frame::Sequence { ref mut idx, ref sep, .. } = *stack.last_mut().unwrap() { let (ref mut repeat_idx, repeat_len) = *repeats.last_mut().unwrap(); *repeat_idx += 1; if *repeat_idx < repeat_len { *idx = 0; if let Some(sep) = sep.clone() { - // repeat same span, I guess let prev_span = match result.last() { Some((tt, _)) => tt.span(), None => DUMMY_SP, @@ -80,14 +122,25 @@ pub fn transcribe( } } + // We are done with the top of the stack. Pop it. Depending on what it was, we do + // different things. Note that the outermost item must be the delimited, wrapped RHS + // that was passed in originally to `transcribe`. match stack.pop().unwrap() { + // Done with a sequence. Pop from repeats. Frame::Sequence { .. } => { repeats.pop(); } + + // We are done processing a Delimited. If this is the top-level delimited, we are + // done. Otherwise, we unwind the result_stack to append what we have produced to + // any previous results. Frame::Delimited { forest, span, .. } => { if result_stack.is_empty() { + // No results left to compute! We are back at the top-level. return TokenStream::new(result); } + + // Step back into the parent Delimited. let tree = TokenTree::Delimited(span, forest.delim, TokenStream::new(result).into()); result = result_stack.pop().unwrap(); @@ -97,35 +150,54 @@ pub fn transcribe( continue; }; + // At this point, we know we are in the middle of a TokenTree (the last one on `stack`). + // `tree` contains the next `TokenTree` to be processed. match tree { + // We are descending into a sequence. We first make sure that the matchers in the RHS + // and the matches in `interp` have the same shape. Otherwise, either the caller or the + // macro writer has made a mistake. seq @ quoted::TokenTree::Sequence(..) => { match lockstep_iter_size(&seq, interp, &repeats) { LockstepIterSize::Unconstrained => { cx.span_fatal( seq.span(), /* blame macro writer */ - "attempted to repeat an expression \ - containing no syntax \ - variables matched as repeating at this depth", + "attempted to repeat an expression containing no syntax variables \ + matched as repeating at this depth", ); } + LockstepIterSize::Contradiction(ref msg) => { + // FIXME: this should be impossible. I (mark-i-m) believe it would + // represent a bug in the macro_parser. // FIXME #2887 blame macro invoker instead cx.span_fatal(seq.span(), &msg[..]); } + LockstepIterSize::Constraint(len, _) => { + // We do this to avoid an extra clone above. We know that this is a + // sequence already. let (sp, seq) = if let quoted::TokenTree::Sequence(sp, seq) = seq { (sp, seq) } else { unreachable!() }; + // Is the repetition empty? if len == 0 { if seq.op == quoted::KleeneOp::OneOrMore { + // FIXME: this should be impossible because we check for this in + // macro_parser.rs // FIXME #2887 blame invoker cx.span_fatal(sp.entire(), "this must repeat at least once"); } } else { + // 0 is the initial counter (we have done 0 repretitions so far). `len` + // is the total number of reptitions we should generate. repeats.push((0, len)); + + // The first time we encounter the sequence we push it to the stack. It + // then gets reused (see the beginning of the loop) until we are done + // repeating. stack.push(Frame::Sequence { idx: 0, sep: seq.separator.clone(), @@ -135,10 +207,16 @@ pub fn transcribe( } } } - // FIXME #2887: think about span stuff here + + // Replace the meta-var with the matched token tree from the invocation. quoted::TokenTree::MetaVar(mut sp, ident) => { - if let Some(cur_matched) = lookup_cur_matched(ident, &interpolations, &repeats) { + // Find the matched nonterminal from the macro invocation, and use it to replace + // the meta-var. + if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) { if let MatchedNonterminal(ref nt) = *cur_matched { + // FIXME #2887: why do we apply a mark when matching a token tree meta-var + // (e.g. `$x:tt`), but not when we are matching any other type of token + // tree? if let NtTT(ref tt) = **nt { result.push(tt.clone().into()); } else { @@ -147,12 +225,15 @@ pub fn transcribe( result.push(token.into()); } } else { + // We were unable to descend far enough. This is an error. cx.span_fatal( sp, /* blame the macro writer */ &format!("variable '{}' is still repeating at this depth", ident), ); } } else { + // If we aren't able to match the meta-var, we push it back into the result but + // with modified syntax context. (I believe this supports nested macros). let ident = Ident::new(ident.name, ident.span.apply_mark(cx.current_expansion.mark)); sp = sp.apply_mark(cx.current_expansion.mark); @@ -160,22 +241,39 @@ pub fn transcribe( result.push(TokenTree::Token(sp, token::Token::from_ast_ident(ident)).into()); } } + + // If we are entering a new delimiter, we push its contents to the `stack` to be + // processed, and we push all of the currently produced results to the `result_stack`. + // We will produce all of the results of the inside of the `Delimited` and then we will + // jump back out of the Delimited, pop the result_stack and add the new results back to + // the previous results (from outside the Delimited). quoted::TokenTree::Delimited(mut span, delimited) => { span = span.apply_mark(cx.current_expansion.mark); stack.push(Frame::Delimited { forest: delimited, idx: 0, span: span }); result_stack.push(mem::replace(&mut result, Vec::new())); } + + // Nothing much to do here. Just push the token to the result, being careful to + // preserve syntax context. quoted::TokenTree::Token(sp, tok) => { let mut marker = Marker(cx.current_expansion.mark); let mut tt = TokenTree::Token(sp, tok); noop_visit_tt(&mut tt, &mut marker); result.push(tt.into()); } + + // There should be no meta-var declarations in the invocation of a macro. quoted::TokenTree::MetaVarDecl(..) => panic!("unexpected `TokenTree::MetaVarDecl"), } } } +/// Lookup the meta-var named `ident` and return the matched token tree from the invocation using +/// the set of matches `interpolations`. +/// +/// See the definition of `repeats` in the `transcribe` function. `repeats` is used to descend +/// into the right place in nested matchers. If we attempt to descend too far, the macro writer has +/// made a mistake, and we return `None`. fn lookup_cur_matched( ident: Ident, interpolations: &FxHashMap>, @@ -195,14 +293,29 @@ fn lookup_cur_matched( }) } +/// An accumulator over a TokenTree to be used with `fold`. During transcription, we need to make +/// sure that the size of each sequence and all of its nested sequences are the same as the sizes +/// of all the matched (nested) sequences in the macro invocation. If they don't match, somebody +/// has made a mistake (either the macro writer or caller). #[derive(Clone)] enum LockstepIterSize { + /// No constraints on length of matcher. This is true for any TokenTree variants except a + /// `MetaVar` with an actual `MatchedSeq` (as opposed to a `MatchedNonterminal`). Unconstrained, + + /// A `MetaVar` with an actual `MatchedSeq`. The length of the match and the name of the + /// meta-var are returned. Constraint(usize, Ident), + + /// Two `Constraint`s on the same sequence had different lengths. This is an error. Contradiction(String), } impl LockstepIterSize { + /// Find incompatibilities in matcher/invocation sizes. + /// - `Unconstrained` is compatible with everything. + /// - `Contradiction` is incompatible with everything. + /// - `Constraint(len)` is only compatible with other constraints of the same length. fn with(self, other: LockstepIterSize) -> LockstepIterSize { match self { LockstepIterSize::Unconstrained => other, @@ -224,6 +337,12 @@ impl LockstepIterSize { } } +/// Given a `tree`, make sure that all sequences have the same length as the matches for the +/// appropriate meta-vars in `interpolations`. +/// +/// Note that if `repeats` does not match the exact correct depth of a meta-var, +/// `lookup_cur_matched` will return `None`, which is why this still works even in the presnece of +/// multiple nested matcher sequences. fn lockstep_iter_size( tree: "ed::TokenTree, interpolations: &FxHashMap>, @@ -233,12 +352,12 @@ fn lockstep_iter_size( match *tree { TokenTree::Delimited(_, ref delimed) => { delimed.tts.iter().fold(LockstepIterSize::Unconstrained, |size, tt| { - size + lockstep_iter_size(tt, interpolations, repeats) + size.with(lockstep_iter_size(tt, interpolations, repeats)) }) } TokenTree::Sequence(_, ref seq) => { seq.tts.iter().fold(LockstepIterSize::Unconstrained, |size, tt| { - size + lockstep_iter_size(tt, interpolations, repeats) + size.with(lockstep_iter_size(tt, interpolations, repeats)) }) } TokenTree::MetaVar(_, name) | TokenTree::MetaVarDecl(_, name, _) => { From 152b26afc900c7d6c2291dd88a681705af0b7a0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 8 May 2019 08:19:29 +0200 Subject: [PATCH 119/212] submodules: update clippy from fc96aa03 to 341c96af Changes: ```` rustup https://github.com/rust-lang/rust/pull/60586 Add test for #771. Clean up while_loop tests ```` --- src/tools/clippy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/clippy b/src/tools/clippy index fc96aa0368841..341c96afd3311 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit fc96aa036884183ddc68d2659f4633e6f138b4e0 +Subproject commit 341c96afd331195beeb001436535c1feb479ff9d From bfa15f39888a514f1eb164e210cf5d85b33146e1 Mon Sep 17 00:00:00 2001 From: ben Date: Sun, 5 May 2019 08:41:39 +1200 Subject: [PATCH 120/212] Add tests for concrete const types --- .../concrete-const-as-fn-arg.rs | 14 +++++++++++ .../concrete-const-as-fn-arg.stderr | 6 +++++ .../concrete-const-impl-method.rs | 24 +++++++++++++++++++ .../concrete-const-impl-method.stderr | 6 +++++ 4 files changed, 50 insertions(+) create mode 100644 src/test/ui/const-generics/concrete-const-as-fn-arg.rs create mode 100644 src/test/ui/const-generics/concrete-const-as-fn-arg.stderr create mode 100644 src/test/ui/const-generics/concrete-const-impl-method.rs create mode 100644 src/test/ui/const-generics/concrete-const-impl-method.stderr diff --git a/src/test/ui/const-generics/concrete-const-as-fn-arg.rs b/src/test/ui/const-generics/concrete-const-as-fn-arg.rs new file mode 100644 index 0000000000000..54981b77a2b84 --- /dev/null +++ b/src/test/ui/const-generics/concrete-const-as-fn-arg.rs @@ -0,0 +1,14 @@ +// Test that a concrete const type i.e. A<2>, can be used as an argument type in a function +// run-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +struct A; // ok + +fn with_concrete_const_arg(_: A<2>) -> u32 { 17 } + +fn main() { + let val: A<2> = A; + assert_eq!(with_concrete_const_arg(val), 17); +} diff --git a/src/test/ui/const-generics/concrete-const-as-fn-arg.stderr b/src/test/ui/const-generics/concrete-const-as-fn-arg.stderr new file mode 100644 index 0000000000000..955b319d70044 --- /dev/null +++ b/src/test/ui/const-generics/concrete-const-as-fn-arg.stderr @@ -0,0 +1,6 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/concrete-const-as-fn-arg.rs:4:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + diff --git a/src/test/ui/const-generics/concrete-const-impl-method.rs b/src/test/ui/const-generics/concrete-const-impl-method.rs new file mode 100644 index 0000000000000..226ea4151806e --- /dev/null +++ b/src/test/ui/const-generics/concrete-const-impl-method.rs @@ -0,0 +1,24 @@ +// Test that a method/associated non-method within an impl block of a concrete const type i.e. A<2>, +// is callable. +// run-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +pub struct A; + +impl A<2> { + fn impl_method(&self) -> u32 { + 17 + } + + fn associated_non_method() -> u32 { + 17 + } +} + +fn main() { + let val: A<2> = A; + assert_eq!(val.impl_method(), 17); + assert_eq!(A::<2>::associated_non_method(), 17); +} diff --git a/src/test/ui/const-generics/concrete-const-impl-method.stderr b/src/test/ui/const-generics/concrete-const-impl-method.stderr new file mode 100644 index 0000000000000..3ce488c62755a --- /dev/null +++ b/src/test/ui/const-generics/concrete-const-impl-method.stderr @@ -0,0 +1,6 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/concrete-const-impl-method.rs:5:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + From df5a0111be33f8abdd649bbce896dd7dafd76f44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 24 Apr 2019 21:02:17 +0200 Subject: [PATCH 121/212] Optimize HIR map --- src/librustc/hir/map/collector.rs | 27 ++++++-- src/librustc/hir/map/mod.rs | 105 +++++++++++++++++------------- src/librustc/session/mod.rs | 3 - src/librustc_driver/pretty.rs | 12 ++-- 4 files changed, 87 insertions(+), 60 deletions(-) diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 50bd89a158964..24eaeb45ba5ec 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -1,9 +1,11 @@ use super::*; use crate::dep_graph::{DepGraph, DepKind, DepNodeIndex}; use crate::hir; +use crate::hir::map::HirMap; use crate::hir::def_id::{LOCAL_CRATE, CrateNum}; use crate::hir::intravisit::{Visitor, NestedVisitorMap}; use rustc_data_structures::svh::Svh; +use rustc_data_structures::indexed_vec::IndexVec; use crate::ich::Fingerprint; use crate::middle::cstore::CrateStore; use crate::session::CrateDisambiguator; @@ -12,6 +14,7 @@ use crate::util::nodemap::FxHashMap; use syntax::ast::NodeId; use syntax::source_map::SourceMap; use syntax_pos::Span; +use std::iter::repeat; use crate::ich::StableHashingContext; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; @@ -25,7 +28,7 @@ pub(super) struct NodeCollector<'a, 'hir> { source_map: &'a SourceMap, /// The node map - map: FxHashMap>, + map: HirMap<'hir>, /// The parent of this node parent_node: hir::HirId, @@ -142,11 +145,15 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { ); } + let (lo, hi) = definitions.def_index_counts_lo_hi(); + let mut collector = NodeCollector { krate, source_map: sess.source_map(), - map: FxHashMap::with_capacity_and_hasher(sess.current_node_id_count(), - Default::default()), + map: [ + repeat(None).take(lo).collect(), + repeat(None).take(hi).collect(), + ], parent_node: hir::CRATE_HIR_ID, current_signature_dep_index: root_mod_sig_dep_index, current_full_dep_index: root_mod_full_dep_index, @@ -171,7 +178,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { crate_disambiguator: CrateDisambiguator, cstore: &dyn CrateStore, commandline_args_hash: u64) - -> (FxHashMap>, Svh) + -> (HirMap<'hir>, Svh) { self.hir_body_nodes.sort_unstable_by_key(|bn| bn.0); @@ -224,7 +231,17 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { fn insert_entry(&mut self, id: HirId, entry: Entry<'hir>) { debug!("hir_map: {:?} => {:?}", id, entry); - self.map.insert(id, entry); + let local_map = &mut self.map[id.owner.address_space().index()][id.owner.as_array_index()]; + let i = id.local_id.as_u32() as usize; + if local_map.is_none() { + *local_map = Some(IndexVec::with_capacity(i + 1)); + } + let local_map = local_map.as_mut().unwrap(); + let len = local_map.len(); + if i >= len { + local_map.extend(repeat(None).take(i - len + 1)); + } + local_map[id.local_id] = Some(entry); } fn insert(&mut self, span: Span, hir_id: HirId, node: Node<'hir>) { diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index a59170e96669c..e6bc4beb450fc 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -11,6 +11,7 @@ use crate::middle::cstore::CrateStoreDyn; use rustc_target::spec::abi::Abi; use rustc_data_structures::svh::Svh; +use rustc_data_structures::indexed_vec::IndexVec; use syntax::ast::{self, Name, NodeId}; use syntax::source_map::Spanned; use syntax::ext::base::MacroKind; @@ -161,6 +162,8 @@ impl Forest { } } +pub(super) type HirMap<'hir> = [Vec>>>>; 2]; + /// Represents a mapping from `NodeId`s to AST elements and their parent `NodeId`s. #[derive(Clone)] pub struct Map<'hir> { @@ -174,7 +177,7 @@ pub struct Map<'hir> { /// The SVH of the local crate. pub crate_hash: Svh, - map: FxHashMap>, + map: HirMap<'hir>, definitions: &'hir Definitions, @@ -183,6 +186,12 @@ pub struct Map<'hir> { } impl<'hir> Map<'hir> { + #[inline] + fn lookup(&self, id: HirId) -> Option<&Entry<'hir>> { + let local_map = self.map[id.owner.address_space().index()].get(id.owner.as_array_index())?; + local_map.as_ref()?.get(id.local_id)?.as_ref() + } + /// Registers a read in the dependency graph of the AST node with /// the given `id`. This needs to be called each time a public /// function returns the HIR for a node -- in other words, when it @@ -191,7 +200,7 @@ impl<'hir> Map<'hir> { /// read recorded). If the function just returns a DefId or /// NodeId, no actual content was returned, so no read is needed. pub fn read(&self, hir_id: HirId) { - if let Some(entry) = self.map.get(&hir_id) { + if let Some(entry) = self.lookup(hir_id) { self.dep_graph.read_index(entry.dep_node); } else { bug!("called `HirMap::read()` with invalid `HirId`: {:?}", hir_id) @@ -378,12 +387,8 @@ impl<'hir> Map<'hir> { }) } - fn entry_count(&self) -> usize { - self.map.len() - } - fn find_entry(&self, id: HirId) -> Option> { - self.map.get(&id).cloned() + self.lookup(id).cloned() } pub fn krate(&self) -> &'hir Crate { @@ -433,7 +438,7 @@ impl<'hir> Map<'hir> { /// item (possibly associated), a closure, or a `hir::AnonConst`. pub fn body_owner(&self, BodyId { hir_id }: BodyId) -> NodeId { let parent = self.get_parent_node_by_hir_id(hir_id); - assert!(self.map.get(&parent).map_or(false, |e| e.is_body_owner(hir_id))); + assert!(self.lookup(parent).map_or(false, |e| e.is_body_owner(hir_id))); self.hir_to_node_id(parent) } @@ -1004,6 +1009,24 @@ impl<'hir> Map<'hir> { attrs.unwrap_or(&[]) } + /// Returns an iterator that yields all the hir ids in the map. + fn all_ids<'a>(&'a self) -> impl Iterator + 'a { + let map = &self.map; + let spaces = [DefIndexAddressSpace::Low, DefIndexAddressSpace::High].iter().cloned(); + spaces.flat_map(move |space| { + map[space.index()].iter().enumerate().filter_map(|(i, local_map)| { + local_map.as_ref().map(|m| (i, m)) + }).flat_map(move |(def_index, local_map)| { + local_map.iter_enumerated().filter_map(move |(i, entry)| entry.map(move |_| { + HirId { + owner: DefIndex::from_array_index(def_index, space), + local_id: i, + } + })) + }) + }) + } + /// Returns an iterator that yields the node id's with paths that /// match `parts`. (Requires `parts` is non-empty.) /// @@ -1012,13 +1035,16 @@ impl<'hir> Map<'hir> { /// such as `foo::bar::quux`, `bar::quux`, `other::bar::quux`, and /// any other such items it can find in the map. pub fn nodes_matching_suffix<'a>(&'a self, parts: &'a [String]) - -> NodesMatchingSuffix<'a, 'hir> { - NodesMatchingSuffix { + -> impl Iterator + 'a { + let nodes = NodesMatchingSuffix { map: self, item_name: parts.last().unwrap(), in_which: &parts[..parts.len() - 1], - idx: ast::CRATE_NODE_ID, - } + }; + + self.all_ids().filter(move |hir| nodes.matces_suffix(*hir)).map(move |hir| { + self.hir_to_node_id(hir) + }) } pub fn span(&self, id: NodeId) -> Span { @@ -1097,21 +1123,20 @@ impl<'hir> Map<'hir> { } } -pub struct NodesMatchingSuffix<'a, 'hir:'a> { - map: &'a Map<'hir>, +pub struct NodesMatchingSuffix<'a> { + map: &'a Map<'a>, item_name: &'a String, in_which: &'a [String], - idx: NodeId, } -impl<'a, 'hir> NodesMatchingSuffix<'a, 'hir> { +impl<'a> NodesMatchingSuffix<'a> { /// Returns `true` only if some suffix of the module path for parent /// matches `self.in_which`. /// /// In other words: let `[x_0,x_1,...,x_k]` be `self.in_which`; /// returns true if parent's path ends with the suffix /// `x_0::x_1::...::x_k`. - fn suffix_matches(&self, parent: NodeId) -> bool { + fn suffix_matches(&self, parent: HirId) -> bool { let mut cursor = parent; for part in self.in_which.iter().rev() { let (mod_id, mod_name) = match find_first_mod_parent(self.map, cursor) { @@ -1121,7 +1146,7 @@ impl<'a, 'hir> NodesMatchingSuffix<'a, 'hir> { if mod_name != &**part { return false; } - cursor = self.map.get_parent(mod_id); + cursor = self.map.get_parent_item(mod_id); } return true; @@ -1131,14 +1156,14 @@ impl<'a, 'hir> NodesMatchingSuffix<'a, 'hir> { // If `id` itself is a mod named `m` with parent `p`, then // returns `Some(id, m, p)`. If `id` has no mod in its parent // chain, then returns `None`. - fn find_first_mod_parent<'a>(map: &'a Map<'_>, mut id: NodeId) -> Option<(NodeId, Name)> { + fn find_first_mod_parent<'a>(map: &'a Map<'_>, mut id: HirId) -> Option<(HirId, Name)> { loop { - if let Node::Item(item) = map.find(id)? { + if let Node::Item(item) = map.find_by_hir_id(id)? { if item_is_mod(&item) { return Some((id, item.ident.name)) } } - let parent = map.get_parent(id); + let parent = map.get_parent_item(id); if parent == id { return None } id = parent; } @@ -1154,35 +1179,21 @@ impl<'a, 'hir> NodesMatchingSuffix<'a, 'hir> { // We are looking at some node `n` with a given name and parent // id; do their names match what I am seeking? - fn matches_names(&self, parent_of_n: NodeId, name: Name) -> bool { + fn matches_names(&self, parent_of_n: HirId, name: Name) -> bool { name == &**self.item_name && self.suffix_matches(parent_of_n) } -} -impl<'a, 'hir> Iterator for NodesMatchingSuffix<'a, 'hir> { - type Item = NodeId; - - fn next(&mut self) -> Option { - loop { - let idx = self.idx; - if idx.as_usize() >= self.map.entry_count() { - return None; - } - self.idx = NodeId::from_u32(self.idx.as_u32() + 1); - let hir_idx = self.map.node_to_hir_id(idx); - let name = match self.map.find_entry(hir_idx).map(|entry| entry.node) { - Some(Node::Item(n)) => n.name(), - Some(Node::ForeignItem(n)) => n.name(), - Some(Node::TraitItem(n)) => n.name(), - Some(Node::ImplItem(n)) => n.name(), - Some(Node::Variant(n)) => n.name(), - Some(Node::Field(n)) => n.name(), - _ => continue, - }; - if self.matches_names(self.map.get_parent(idx), name) { - return Some(idx) - } - } + fn matces_suffix(&self, hir: HirId) -> bool { + let name = match self.map.find_entry(hir).map(|entry| entry.node) { + Some(Node::Item(n)) => n.name(), + Some(Node::ForeignItem(n)) => n.name(), + Some(Node::TraitItem(n)) => n.name(), + Some(Node::ImplItem(n)) => n.name(), + Some(Node::Variant(n)) => n.name(), + Some(Node::Field(n)) => n.name(), + _ => return false, + }; + self.matches_names(self.map.get_parent_item(hir), name) } } diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index ad8825bc5de5a..e8c7965ab4f45 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -408,9 +408,6 @@ impl Session { pub fn next_node_id(&self) -> NodeId { self.reserve_node_ids(1) } - pub(crate) fn current_node_id_count(&self) -> usize { - self.next_node_id.get().as_u32() as usize - } pub fn diagnostic<'a>(&'a self) -> &'a errors::Handler { &self.parse_sess.span_diagnostic } diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 4fdcdafcab86c..a339ec30a74f8 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -543,12 +543,12 @@ impl FromStr for UserIdentifiedItem { } } -enum NodesMatchingUII<'a, 'hir: 'a> { +enum NodesMatchingUII<'a> { NodesMatchingDirect(option::IntoIter), - NodesMatchingSuffix(hir_map::NodesMatchingSuffix<'a, 'hir>), + NodesMatchingSuffix(Box + 'a>), } -impl<'a, 'hir> Iterator for NodesMatchingUII<'a, 'hir> { +impl<'a> Iterator for NodesMatchingUII<'a> { type Item = ast::NodeId; fn next(&mut self) -> Option { @@ -576,10 +576,12 @@ impl UserIdentifiedItem { fn all_matching_node_ids<'a, 'hir>(&'a self, map: &'a hir_map::Map<'hir>) - -> NodesMatchingUII<'a, 'hir> { + -> NodesMatchingUII<'a> { match *self { ItemViaNode(node_id) => NodesMatchingDirect(Some(node_id).into_iter()), - ItemViaPath(ref parts) => NodesMatchingSuffix(map.nodes_matching_suffix(&parts)), + ItemViaPath(ref parts) => { + NodesMatchingSuffix(Box::new(map.nodes_matching_suffix(&parts))) + } } } From c87d2ccf88f1b9ca039d18530fd474e5ad868bc4 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 8 May 2019 09:56:26 +0300 Subject: [PATCH 122/212] test for #50518 It was fixed somewhere between 1.28.0 and 1.31.1 closes #50518 --- src/test/ui/issues/issue-50518.rs | 40 +++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/test/ui/issues/issue-50518.rs diff --git a/src/test/ui/issues/issue-50518.rs b/src/test/ui/issues/issue-50518.rs new file mode 100644 index 0000000000000..d776d181b6268 --- /dev/null +++ b/src/test/ui/issues/issue-50518.rs @@ -0,0 +1,40 @@ +// compile-pass +use std::marker::PhantomData; + +struct Meta { + value: i32, + type_: PhantomData +} + +trait MetaTrait { + fn get_value(&self) -> i32; +} + +impl MetaTrait for Meta { + fn get_value(&self) -> i32 { self.value } +} + +trait Bar { + fn get_const(&self) -> &dyn MetaTrait; +} + +struct Foo { + _value: A +} + +impl Foo { + const CONST: &'static dyn MetaTrait = &Meta:: { + value: 10, + type_: PhantomData + }; +} + +impl Bar for Foo { + fn get_const(&self) -> &dyn MetaTrait { Self::CONST } +} + +fn main() { + let foo = Foo:: { _value: 10 }; + let bar: &dyn Bar = &foo; + println!("const {}", bar.get_const().get_value()); +} From d33db6ed570a38fa52d8fdf29dbad9a5cdf4c44d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 8 May 2019 14:27:40 +0200 Subject: [PATCH 123/212] Rename HirMap to HirEntryMap and add some comments --- src/librustc/hir/map/collector.rs | 6 +++--- src/librustc/hir/map/mod.rs | 25 ++++++++++++++++++++----- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 24eaeb45ba5ec..136d683e76b48 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -1,7 +1,7 @@ use super::*; use crate::dep_graph::{DepGraph, DepKind, DepNodeIndex}; use crate::hir; -use crate::hir::map::HirMap; +use crate::hir::map::HirEntryMap; use crate::hir::def_id::{LOCAL_CRATE, CrateNum}; use crate::hir::intravisit::{Visitor, NestedVisitorMap}; use rustc_data_structures::svh::Svh; @@ -28,7 +28,7 @@ pub(super) struct NodeCollector<'a, 'hir> { source_map: &'a SourceMap, /// The node map - map: HirMap<'hir>, + map: HirEntryMap<'hir>, /// The parent of this node parent_node: hir::HirId, @@ -178,7 +178,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { crate_disambiguator: CrateDisambiguator, cstore: &dyn CrateStore, commandline_args_hash: u64) - -> (HirMap<'hir>, Svh) + -> (HirEntryMap<'hir>, Svh) { self.hir_body_nodes.sort_unstable_by_key(|bn| bn.0); diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index e6bc4beb450fc..c2b513a39a8b7 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -162,7 +162,12 @@ impl Forest { } } -pub(super) type HirMap<'hir> = [Vec>>>>; 2]; +/// This type is effectively a `HashMap>`, +/// but is implemented by 3 layers of arrays. +/// - the outer layer is `[A; 2]` and correspond to the 2 address spaces `DefIndex`es can be in +/// - then we have `A = Vec>` mapping a `DefIndex`'s index to a inner value +/// - which is `B = IndexVec>` which finally gives you the `Entry`. +pub(super) type HirEntryMap<'hir> = [Vec>>>>; 2]; /// Represents a mapping from `NodeId`s to AST elements and their parent `NodeId`s. #[derive(Clone)] @@ -177,7 +182,7 @@ pub struct Map<'hir> { /// The SVH of the local crate. pub crate_hash: Svh, - map: HirMap<'hir>, + map: HirEntryMap<'hir>, definitions: &'hir Definitions, @@ -1011,15 +1016,25 @@ impl<'hir> Map<'hir> { /// Returns an iterator that yields all the hir ids in the map. fn all_ids<'a>(&'a self) -> impl Iterator + 'a { + // This code is a bit awkward because the map is implemented as 3 levels of arrays, + // see the comment on `HirEntryMap`. let map = &self.map; + + // Look at both the def index address spaces let spaces = [DefIndexAddressSpace::Low, DefIndexAddressSpace::High].iter().cloned(); spaces.flat_map(move |space| { - map[space.index()].iter().enumerate().filter_map(|(i, local_map)| { + // Iterate over all the indices in the address space and return a reference to + // local maps and their index given that they exist. + let local_maps = map[space.index()].iter().enumerate().filter_map(|(i, local_map)| { local_map.as_ref().map(|m| (i, m)) - }).flat_map(move |(def_index, local_map)| { + }); + + local_maps.flat_map(move |(array_index, local_map)| { + // Iterate over each valid entry in the local map local_map.iter_enumerated().filter_map(move |(i, entry)| entry.map(move |_| { + // Reconstruct the HirId based on the 3 indices we used to find it HirId { - owner: DefIndex::from_array_index(def_index, space), + owner: DefIndex::from_array_index(array_index, space), local_id: i, } })) From 47768b2613393e39218c255ed990169665d69df9 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 8 May 2019 03:05:32 +0200 Subject: [PATCH 124/212] Document + Cleanup lang_items.rs --- src/librustc/middle/lang_items.rs | 97 +++++++++++++++++++------------ 1 file changed, 60 insertions(+), 37 deletions(-) diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 5d809f1407114..0e283ca6b1cf1 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -1,13 +1,13 @@ -// Detecting language items. -// -// Language items are items that represent concepts intrinsic to the language -// itself. Examples are: -// -// * Traits that specify "kinds"; e.g., "Sync", "Send". -// -// * Traits that represent operators; e.g., "Add", "Sub", "Index". -// -// * Functions called by the compiler itself. +//! Detecting language items. +//! +//! Language items are items that represent concepts intrinsic to the language +//! itself. Examples are: +//! +//! * Traits that specify "kinds"; e.g., "Sync", "Send". +//! +//! * Traits that represent operators; e.g., "Add", "Sub", "Index". +//! +//! * Functions called by the compiler itself. pub use self::LangItem::*; @@ -32,6 +32,7 @@ macro_rules! language_item_table { ) => { enum_from_u32! { + /// A representation of all the valid language items in Rust. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub enum LangItem { $($variant,)* @@ -39,6 +40,9 @@ enum_from_u32! { } impl LangItem { + /// Returns the `name` in `#[lang = "$name"]`. + /// For example, `LangItem::EqTraitLangItem`, + /// that is `#[lang = "eq"]` would result in `"eq"`. fn name(self) -> &'static str { match self { $( $variant => $name, )* @@ -48,28 +52,38 @@ impl LangItem { #[derive(HashStable)] pub struct LanguageItems { + /// Mappings from lang items to their possibly found `DefId`s. + /// The index corresponds to the order in `LangItem`. pub items: Vec>, + /// Lang items that were not found during collection. pub missing: Vec, } impl LanguageItems { - pub fn new() -> LanguageItems { - fn foo(_: LangItem) -> Option { None } + /// Construct an empty collection of lang items and no missing ones. + pub fn new() -> Self { + fn init_none(_: LangItem) -> Option { None } - LanguageItems { - items: vec![$(foo($variant)),*], + Self { + items: vec![$(init_none($variant)),*], missing: Vec::new(), } } + /// Returns the mappings to the possibly found `DefId`s for each lang item. pub fn items(&self) -> &[Option] { &*self.items } + /// Requires that a given `LangItem` was bound and returns the corresponding `DefId`. + /// If it wasn't bound, e.g. due to a missing `#[lang = ""]`, + /// returns an error message as a string. pub fn require(&self, it: LangItem) -> Result { self.items[it as usize].ok_or_else(|| format!("requires `{}` lang_item", it.name())) } + /// Returns the kind of closure that `id`, which is one of the `Fn*` traits, corresponds to. + /// If `id` is not one of the `Fn*` traits, `None` is returned. pub fn fn_trait_kind(&self, id: DefId) -> Option { match Some(id) { x if x == self.fn_trait() => Some(ty::ClosureKind::Fn), @@ -80,6 +94,9 @@ impl LanguageItems { } $( + /// Returns the corresponding `DefId` for the lang item + #[doc = $name] + /// if it exists. #[allow(dead_code)] pub fn $method(&self) -> Option { self.items[$variant as usize] @@ -90,6 +107,7 @@ impl LanguageItems { struct LanguageItemCollector<'a, 'tcx: 'a> { items: LanguageItems, tcx: TyCtxt<'a, 'tcx, 'tcx>, + /// A mapping from the name of the lang item to its order and the form it must be of. item_refs: FxHashMap<&'static str, (usize, Target)>, } @@ -105,32 +123,28 @@ impl<'a, 'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'a, 'tcx> { }, // Known lang item with attribute on incorrect target. Some((_, expected_target)) => { - let mut err = struct_span_err!( + struct_span_err!( self.tcx.sess, span, E0718, "`{}` language item must be applied to a {}", value, expected_target, - ); - err.span_label( + ).span_label( span, format!( "attribute should be applied to a {}, not a {}", expected_target, actual_target, ), - ); - err.emit(); + ).emit(); }, // Unknown lang item. _ => { - let mut err = struct_span_err!( + struct_span_err!( self.tcx.sess, span, E0522, "definition of an unknown language item: `{}`", value - ); - err.span_label( + ).span_label( span, format!("definition of unknown language item `{}`", value) - ); - err.emit(); + ).emit(); }, } } @@ -190,32 +204,39 @@ impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> { } } +/// Extract the first `lang = "$name"` out of a list of attributes. +/// The attributes `#[panic_handler]` and `#[alloc_error_handler]` +/// are also extracted out when found. pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> { - for attribute in attrs { - if attribute.check_name("lang") { - if let Some(value) = attribute.value_str() { - return Some((value, attribute.span)); - } - } else if attribute.check_name("panic_handler") { - return Some((Symbol::intern("panic_impl"), attribute.span)) - } else if attribute.check_name("alloc_error_handler") { - return Some((Symbol::intern("oom"), attribute.span)) - } - } - - None + attrs.iter().find_map(|attr| Some(match attr { + _ if attr.check_name("lang") => (attr.value_str()?, attr.span), + _ if attr.check_name("panic_handler") => (Symbol::intern("panic_impl"), attr.span), + _ if attr.check_name("alloc_error_handler") => (Symbol::intern("oom"), attr.span), + _ => return None, + })) } +/// Traverse and collect all the lang items in all crates. pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems { + // Initialize the collector. let mut collector = LanguageItemCollector::new(tcx); + + // Collect lang items in other crates. for &cnum in tcx.crates().iter() { for &(def_id, item_index) in tcx.defined_lang_items(cnum).iter() { collector.collect_item(item_index, def_id); } } + + // Collect lang items in this crate. tcx.hir().krate().visit_all_item_likes(&mut collector); + + // Extract out the found lang items. let LanguageItemCollector { mut items, .. } = collector; + + // Find all required but not-yet-defined lang items. weak_lang_items::check_crate(tcx, &mut items); + items } @@ -382,6 +403,8 @@ language_item_table! { } impl<'a, 'tcx, 'gcx> TyCtxt<'a, 'tcx, 'gcx> { + /// Returns the `DefId` for a given `LangItem`. + /// If not found, fatally abort compilation. pub fn require_lang_item(&self, lang_item: LangItem) -> DefId { self.lang_items().require(lang_item).unwrap_or_else(|msg| { self.sess.fatal(&msg) From 7e8035593d1900dc9db05b5aaf92d421d248eb22 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 2 May 2019 15:24:40 -0700 Subject: [PATCH 125/212] std: Update compiler-builtins crate Pulls in a fix for ensuring that wasm targets have code in compiler-builtins for `ldexp` which LLVM can generate references to. --- Cargo.lock | 34 +++++++++++++++++----------------- src/libstd/Cargo.toml | 2 +- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ff66b4a0372ee..0154b96751d36 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,7 +17,7 @@ dependencies = [ name = "alloc" version = "0.0.0" dependencies = [ - "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -115,7 +115,7 @@ version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -450,7 +450,7 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", @@ -736,7 +736,7 @@ name = "dlmalloc" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -902,7 +902,7 @@ name = "fortanix-sgx-abi" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -1063,7 +1063,7 @@ name = "hashbrown" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-alloc 1.0.0", "rustc-std-workspace-core 1.0.0", ] @@ -1764,7 +1764,7 @@ dependencies = [ name = "panic_abort" version = "0.0.0" dependencies = [ - "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1774,7 +1774,7 @@ name = "panic_unwind" version = "0.0.0" dependencies = [ "alloc 0.0.0", - "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "unwind 0.0.0", @@ -1959,7 +1959,7 @@ name = "profiler_builtins" version = "0.0.0" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -2484,7 +2484,7 @@ name = "rustc-demangle" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -2612,7 +2612,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -2842,7 +2842,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -2904,7 +2904,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -3021,7 +3021,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -3290,7 +3290,7 @@ dependencies = [ "alloc 0.0.0", "backtrace-sys 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "dlmalloc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "fortanix-sgx-abi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3882,7 +3882,7 @@ name = "unwind" version = "0.0.0" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4078,7 +4078,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0aa3473e85a3161b59845d6096b289bb577874cafeaf75ea1b1beaa6572c7fc" "checksum commoncrypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d056a8586ba25a1e4d61cb090900e495952c7886786fc55f909ab2f819b69007" "checksum commoncrypto-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fed34f46747aa73dfaa578069fd8279d2818ade2b55f38f22a9401c7f4083e2" -"checksum compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4ada53ac629568219809178f988ca2aac9889e9a847379588c097d30ce185145" +"checksum compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "6549720ae78db799196d4af8f719facb4c7946710b4b64148482553e54b56d15" "checksum compiletest_rs 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "f40ecc9332b68270998995c00f8051ee856121764a0d3230e64c9efd059d27b6" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4e2640d6d0bf22e82bed1b73c6aef8d5dd31e5abe6666c57e6d45e2649f4f887" diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index ac1aff845d8c9..ad5d62f667ac9 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -19,7 +19,7 @@ panic_unwind = { path = "../libpanic_unwind", optional = true } panic_abort = { path = "../libpanic_abort" } core = { path = "../libcore" } libc = { version = "0.2.51", default-features = false, features = ['rustc-dep-of-std'] } -compiler_builtins = { version = "0.1.9" } +compiler_builtins = { version = "0.1.12" } profiler_builtins = { path = "../libprofiler_builtins", optional = true } unwind = { path = "../libunwind" } hashbrown = { version = "0.3.0", features = ['rustc-dep-of-std'] } From e65ef96eafc8772ae468a6f53547e8837dbc94da Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 30 Apr 2019 10:46:21 +0200 Subject: [PATCH 126/212] libprofiler_builtins: Set compilation flags more correctly for C code. In particular, set COMPILER_RT_HAS_FCNTL_LCK and COMPILER_RT_HAS_ATOMICS as appropriate. --- src/libprofiler_builtins/build.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/libprofiler_builtins/build.rs b/src/libprofiler_builtins/build.rs index ff52a03d9dd97..331edb73d6df9 100644 --- a/src/libprofiler_builtins/build.rs +++ b/src/libprofiler_builtins/build.rs @@ -44,6 +44,19 @@ fn main() { cfg.define("COMPILER_RT_HAS_UNAME", Some("1")); } + // Assume that the Unixes we are building this for have fnctl() available + if env::var_os("CARGO_CFG_UNIX").is_some() { + cfg.define("COMPILER_RT_HAS_FCNTL_LCK", Some("1")); + } + + // This should be a pretty good heuristic for when to set + // COMPILER_RT_HAS_ATOMICS + if env::var_os("CARGO_CFG_TARGET_HAS_ATOMIC").map(|features| { + features.to_string_lossy().to_lowercase().contains("cas") + }).unwrap_or(false) { + cfg.define("COMPILER_RT_HAS_ATOMICS", Some("1")); + } + // The source for `compiler-rt` comes from the `compiler-builtins` crate, so // load our env var set by cargo to find the source code. let root = env::var_os("DEP_COMPILER_RT_COMPILER_RT").unwrap(); From 0ffc57311030a1930edfa721fe57d0000a063af4 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 8 May 2019 17:05:02 +0200 Subject: [PATCH 127/212] AppVeyor: Update clang-cl from 7.0.0 to 8.0.0 --- appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index be960dc13af57..dffd79c56e48a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -158,9 +158,9 @@ install: # Note that the LLVM installer is an NSIS installer # # Original downloaded here came from - # http://releases.llvm.org/7.0.0/LLVM-7.0.0-win64.exe - - if NOT defined MINGW_URL appveyor-retry appveyor DownloadFile https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/LLVM-7.0.0-win64.exe - - if NOT defined MINGW_URL .\LLVM-7.0.0-win64.exe /S /NCRC /D=C:\clang-rust + # http://releases.llvm.org/8.0.0/LLVM-8.0.0-win64.exe + - if NOT defined MINGW_URL appveyor-retry appveyor DownloadFile https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/LLVM-8.0.0-win64.exe + - if NOT defined MINGW_URL .\LLVM-8.0.0-win64.exe /S /NCRC /D=C:\clang-rust - if NOT defined MINGW_URL set RUST_CONFIGURE_ARGS=%RUST_CONFIGURE_ARGS% --set llvm.clang-cl=C:\clang-rust\bin\clang-cl.exe # Here we do a pretty heinous thing which is to mangle the MinGW installation From cf0f2b041be6f580c18f7925551528bb1df564d8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 8 May 2019 17:20:43 +0200 Subject: [PATCH 128/212] pin: make the to-module link more visible --- src/libcore/pin.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index e74ed9b7889cb..4ced860948bee 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -274,7 +274,7 @@ use crate::ops::{Deref, DerefMut, Receiver, CoerceUnsized, DispatchFromDyn}; /// value in place, preventing the value referenced by that pointer from being moved /// unless it implements [`Unpin`]. /// -/// See the [`pin` module] documentation for further explanation on pinning. +/// *See the [`pin` module] documentation for an explanation of pinning.* /// /// [`Unpin`]: ../../std/marker/trait.Unpin.html /// [`pin` module]: ../../std/pin/index.html From cc40f41ee5baefa0dc1845dd9d794abe90511161 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 8 May 2019 10:23:55 -0700 Subject: [PATCH 129/212] Instead of ICEing on incorrect pattern, use delay_span_bug --- src/librustc/middle/mem_categorization.rs | 12 ++++++++++-- src/test/ui/fn-in-pat.rs | 16 ++++++++++++++++ src/test/ui/fn-in-pat.stderr | 9 +++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/fn-in-pat.rs create mode 100644 src/test/ui/fn-in-pat.stderr diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index f6caf357b393d..7edd5c5a9de1b 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -1300,8 +1300,16 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } } def => { - span_bug!(pat.span, "tuple struct pattern didn't resolve \ - to variant or struct {:?}", def); + debug!( + "tuple struct pattern didn't resolve to variant or struct {:?} at {:?}", + def, + pat.span, + ); + self.tcx.sess.delay_span_bug(pat.span, &format!( + "tuple struct pattern didn't resolve to variant or struct {:?}", + def, + )); + return Err(()); } }; diff --git a/src/test/ui/fn-in-pat.rs b/src/test/ui/fn-in-pat.rs new file mode 100644 index 0000000000000..ed76b2c5db025 --- /dev/null +++ b/src/test/ui/fn-in-pat.rs @@ -0,0 +1,16 @@ +struct A {} + +impl A { + fn new() {} +} + +fn hof(_: F) where F: FnMut(()) {} + +fn ice() { + hof(|c| match c { + A::new() => (), //~ ERROR expected tuple struct/variant, found method + _ => () + }) +} + +fn main() {} diff --git a/src/test/ui/fn-in-pat.stderr b/src/test/ui/fn-in-pat.stderr new file mode 100644 index 0000000000000..eee97fe9587c2 --- /dev/null +++ b/src/test/ui/fn-in-pat.stderr @@ -0,0 +1,9 @@ +error[E0164]: expected tuple struct/variant, found method `::new` + --> $DIR/fn-in-pat.rs:11:9 + | +LL | A::new() => (), + | ^^^^^^^^ not a tuple variant or struct + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0164`. From eb7d47cba90ac716c84fe720418e58c6eb84ac4e Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Wed, 8 May 2019 13:34:23 -0500 Subject: [PATCH 130/212] fix incorrect assert --- src/libsyntax/ext/tt/transcribe.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 3a40e8403ccff..0cefcf1ce034b 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -71,7 +71,10 @@ pub fn transcribe( interp: &FxHashMap>, src: Vec, ) -> TokenStream { - assert!(src.len() > 0); + // Nothing for us to transcribe... + if src.is_empty() { + return TokenStream::empty(); + } // We descend into the RHS (`src`), expanding things as we go. This stack contains the things // we have yet to expand/are still expanding. We start the stack off with the whole RHS. From 0fce5c1bf0b5f12d4e3efe8d31b1df576d5abf45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 8 May 2019 11:42:47 -0700 Subject: [PATCH 131/212] Use `delay_span_bug` for "Failed to unify obligation" --- src/librustc/traits/project.rs | 15 ++++++++---- src/test/ui/issues/issue-60283.rs | 17 ++++++++++++++ src/test/ui/issues/issue-60283.stderr | 34 +++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/issues/issue-60283.rs create mode 100644 src/test/ui/issues/issue-60283.stderr diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index dabb8a728901c..b5232e828c4cd 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -1454,13 +1454,18 @@ fn confirm_param_env_candidate<'cx, 'gcx, 'tcx>( } } Err(e) => { - span_bug!( - obligation.cause.span, - "Failed to unify obligation `{:?}` \ - with poly_projection `{:?}`: {:?}", + let msg = format!( + "Failed to unify obligation `{:?}` with poly_projection `{:?}`: {:?}", obligation, poly_cache_entry, - e); + e, + ); + debug!("confirm_param_env_candidate: {}", msg); + infcx.tcx.sess.delay_span_bug(obligation.cause.span, &msg); + Progress { + ty: infcx.tcx.types.err, + obligations: vec![], + } } } } diff --git a/src/test/ui/issues/issue-60283.rs b/src/test/ui/issues/issue-60283.rs new file mode 100644 index 0000000000000..e5a9caa32fae7 --- /dev/null +++ b/src/test/ui/issues/issue-60283.rs @@ -0,0 +1,17 @@ +pub trait Trait<'a> { + type Item; +} + +impl<'a> Trait<'a> for () { + type Item = (); +} + +pub fn foo(_: T, _: F) +where T: for<'a> Trait<'a>, + F: for<'a> FnMut(>::Item) {} + +fn main() { + foo((), drop) + //~^ ERROR type mismatch in function arguments + //~| ERROR type mismatch resolving +} diff --git a/src/test/ui/issues/issue-60283.stderr b/src/test/ui/issues/issue-60283.stderr new file mode 100644 index 0000000000000..a79b1959dca2f --- /dev/null +++ b/src/test/ui/issues/issue-60283.stderr @@ -0,0 +1,34 @@ +error[E0631]: type mismatch in function arguments + --> $DIR/issue-60283.rs:14:5 + | +LL | foo((), drop) + | ^^^ + | | + | expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _` + | found signature of `fn(_) -> _` + | +note: required by `foo` + --> $DIR/issue-60283.rs:9:1 + | +LL | / pub fn foo(_: T, _: F) +LL | | where T: for<'a> Trait<'a>, +LL | | F: for<'a> FnMut(>::Item) {} + | |_________________________________________________^ + +error[E0271]: type mismatch resolving `for<'a> } as std::ops::FnOnce<(<() as Trait<'a>>::Item,)>>::Output == ()` + --> $DIR/issue-60283.rs:14:5 + | +LL | foo((), drop) + | ^^^ expected bound lifetime parameter 'a, found concrete lifetime + | +note: required by `foo` + --> $DIR/issue-60283.rs:9:1 + | +LL | / pub fn foo(_: T, _: F) +LL | | where T: for<'a> Trait<'a>, +LL | | F: for<'a> FnMut(>::Item) {} + | |_________________________________________________^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0271`. From 58d39a93a04ca1f322a1a899f59390339f696c36 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Wed, 8 May 2019 23:45:19 +0200 Subject: [PATCH 132/212] save-analysis: Fix ICE when processing associated constant --- src/librustc_save_analysis/dump_visitor.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index a45e32ddb6690..1e65f868ebac0 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -463,10 +463,12 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { } // walk type and init value - self.visit_ty(typ); - if let Some(expr) = expr { - self.visit_expr(expr); - } + self.nest_tables(id, |v| { + v.visit_ty(typ); + if let Some(expr) = expr { + v.visit_expr(expr); + } + }); } // FIXME tuple structs should generate tuple-specific data. From ee6d31520071b38f9a2996d60a66d6e2cd965fe7 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 8 May 2019 22:07:12 +0300 Subject: [PATCH 133/212] cleanup: Remove `DefIndexAddressSpace` --- src/librustc/hir/def_id.rs | 67 ++------ src/librustc/hir/lowering.rs | 5 +- src/librustc/hir/map/collector.rs | 9 +- src/librustc/hir/map/def_collector.rs | 36 ++-- src/librustc/hir/map/definitions.rs | 159 ++++++------------ src/librustc/hir/map/mod.rs | 52 +++--- src/librustc/traits/specialize/mod.rs | 4 +- src/librustc_driver/pretty.rs | 3 +- src/librustc_metadata/decoder.rs | 6 +- src/librustc_metadata/index.rs | 34 ++-- src/librustc_metadata/index_builder.rs | 2 +- src/librustc_mir/util/graphviz.rs | 3 +- src/librustc_resolve/lib.rs | 2 +- src/librustc_resolve/macros.rs | 6 +- src/librustdoc/core.rs | 15 +- src/test/mir-opt/graphviz.rs | 2 +- .../mir-opt/inline-closure-borrows-arg.rs | 2 +- src/test/mir-opt/inline-closure.rs | 2 +- src/test/mir-opt/retag.rs | 2 +- .../escape-argument-callee.stderr | 6 +- .../escape-argument.stderr | 6 +- .../escape-upvar-nested.stderr | 6 +- .../escape-upvar-ref.stderr | 4 +- ...pagate-approximated-fail-no-postdom.stderr | 6 +- .../propagate-approximated-ref.stderr | 6 +- ...er-to-static-comparing-against-free.stderr | 12 +- ...oximated-shorter-to-static-no-bound.stderr | 6 +- ...mated-shorter-to-static-wrong-bound.stderr | 6 +- .../propagate-approximated-val.stderr | 6 +- .../propagate-despite-same-free-region.stderr | 6 +- ...ail-to-approximate-longer-no-bounds.stderr | 6 +- ...-to-approximate-longer-wrong-bounds.stderr | 6 +- .../propagate-from-trait-match.stderr | 4 +- .../return-wrong-bound-region.stderr | 6 +- .../projection-no-regions-closure.stderr | 16 +- .../projection-one-region-closure.stderr | 18 +- ...tion-one-region-trait-bound-closure.stderr | 20 +-- ...e-region-trait-bound-static-closure.stderr | 20 +-- ...tion-two-region-trait-bound-closure.stderr | 34 ++-- ...ram-closure-approximate-lower-bound.stderr | 14 +- ...m-closure-outlives-from-return-type.stderr | 4 +- ...-closure-outlives-from-where-clause.stderr | 20 +-- 42 files changed, 246 insertions(+), 403 deletions(-) diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs index 8536f38e48c6d..b268a1a494d10 100644 --- a/src/librustc/hir/def_id.rs +++ b/src/librustc/hir/def_id.rs @@ -1,5 +1,5 @@ use crate::ty::{self, TyCtxt}; -use crate::hir::map::definitions::FIRST_FREE_HIGH_DEF_INDEX; +use crate::hir::map::definitions::FIRST_FREE_DEF_INDEX; use rustc_data_structures::indexed_vec::Idx; use serialize; use std::fmt; @@ -99,17 +99,6 @@ impl serialize::UseSpecializedDecodable for CrateNum {} /// A DefIndex is an index into the hir-map for a crate, identifying a /// particular definition. It should really be considered an interned /// shorthand for a particular DefPath. -/// -/// At the moment we are allocating the numerical values of DefIndexes from two -/// address spaces: DefIndexAddressSpace::Low and DefIndexAddressSpace::High. -/// This allows us to allocate the DefIndexes of all item-likes -/// (Items, TraitItems, and ImplItems) into one of these spaces and -/// consequently use a simple array for lookup tables keyed by DefIndex and -/// known to be densely populated. This is especially important for the HIR map. -/// -/// Since the DefIndex is mostly treated as an opaque ID, you probably -/// don't have to care about these address spaces. - #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)] pub struct DefIndex(u32); @@ -119,33 +108,20 @@ pub const CRATE_DEF_INDEX: DefIndex = DefIndex(0); impl fmt::Debug for DefIndex { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, - "DefIndex({}:{})", - self.address_space().index(), - self.as_array_index()) + write!(f, "DefIndex({})", self.as_array_index()) } } impl DefIndex { - #[inline] - pub fn address_space(&self) -> DefIndexAddressSpace { - match self.0 & 1 { - 0 => DefIndexAddressSpace::Low, - 1 => DefIndexAddressSpace::High, - _ => unreachable!() - } - } - /// Converts this DefIndex into a zero-based array index. - /// This index is the offset within the given DefIndexAddressSpace. #[inline] pub fn as_array_index(&self) -> usize { - (self.0 >> 1) as usize + self.0 as usize } #[inline] - pub fn from_array_index(i: usize, address_space: DefIndexAddressSpace) -> DefIndex { - DefIndex::from_raw_u32(((i << 1) | (address_space as usize)) as u32) + pub fn from_array_index(i: usize) -> DefIndex { + DefIndex(i as u32) } // Proc macros from a proc-macro crate have a kind of virtual DefIndex. This @@ -153,33 +129,28 @@ impl DefIndex { // index of the macro in the CrateMetadata::proc_macros array) to the // corresponding DefIndex. pub fn from_proc_macro_index(proc_macro_index: usize) -> DefIndex { - // DefIndex for proc macros start from FIRST_FREE_HIGH_DEF_INDEX, - // because the first FIRST_FREE_HIGH_DEF_INDEX indexes are reserved + // DefIndex for proc macros start from FIRST_FREE_DEF_INDEX, + // because the first FIRST_FREE_DEF_INDEX indexes are reserved // for internal use. let def_index = DefIndex::from_array_index( - proc_macro_index.checked_add(FIRST_FREE_HIGH_DEF_INDEX) - .expect("integer overflow adding `proc_macro_index`"), - DefIndexAddressSpace::High); + proc_macro_index.checked_add(FIRST_FREE_DEF_INDEX) + .expect("integer overflow adding `proc_macro_index`")); assert!(def_index != CRATE_DEF_INDEX); def_index } // This function is the reverse of from_proc_macro_index() above. pub fn to_proc_macro_index(self: DefIndex) -> usize { - assert_eq!(self.address_space(), DefIndexAddressSpace::High); - - self.as_array_index().checked_sub(FIRST_FREE_HIGH_DEF_INDEX) + self.as_array_index().checked_sub(FIRST_FREE_DEF_INDEX) .unwrap_or_else(|| { bug!("using local index {:?} as proc-macro index", self) }) } - // Don't use this if you don't know about the DefIndex encoding. pub fn from_raw_u32(x: u32) -> DefIndex { DefIndex(x) } - // Don't use this if you don't know about the DefIndex encoding. pub fn as_raw_u32(&self) -> u32 { self.0 } @@ -188,19 +159,6 @@ impl DefIndex { impl serialize::UseSpecializedEncodable for DefIndex {} impl serialize::UseSpecializedDecodable for DefIndex {} -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub enum DefIndexAddressSpace { - Low = 0, - High = 1, -} - -impl DefIndexAddressSpace { - #[inline] - pub fn index(&self) -> usize { - *self as usize - } -} - /// A `DefId` identifies a particular *definition*, by combining a crate /// index and a def index. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)] @@ -211,10 +169,7 @@ pub struct DefId { impl fmt::Debug for DefId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "DefId({}/{}:{}", - self.krate, - self.index.address_space().index(), - self.index.as_array_index())?; + write!(f, "DefId({}:{}", self.krate, self.index.as_array_index())?; ty::tls::with_opt(|opt_tcx| { if let Some(tcx) = opt_tcx { diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 20e016b8b5b1e..848e9ca58e595 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -36,7 +36,7 @@ use crate::dep_graph::DepGraph; use crate::hir::{self, ParamName}; use crate::hir::HirVec; use crate::hir::map::{DefKey, DefPathData, Definitions}; -use crate::hir::def_id::{DefId, DefIndex, DefIndexAddressSpace, CRATE_DEF_INDEX}; +use crate::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX}; use crate::hir::def::{Res, DefKind, PartialRes, PerNS}; use crate::hir::{GenericArg, ConstArg}; use crate::lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES, @@ -418,7 +418,6 @@ impl<'a> LoweringContext<'a> { owner, id, DefPathData::Misc, - DefIndexAddressSpace::High, Mark::root(), tree.prefix.span, ); @@ -962,7 +961,6 @@ impl<'a> LoweringContext<'a> { parent_index, node_id, DefPathData::LifetimeNs(str_name), - DefIndexAddressSpace::High, Mark::root(), span, ); @@ -1763,7 +1761,6 @@ impl<'a> LoweringContext<'a> { self.parent, def_node_id, DefPathData::LifetimeNs(name.ident().as_interned_str()), - DefIndexAddressSpace::High, Mark::root(), lifetime.span, ); diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 136d683e76b48..a1cf338bf12ea 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -145,15 +145,10 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { ); } - let (lo, hi) = definitions.def_index_counts_lo_hi(); - let mut collector = NodeCollector { krate, source_map: sess.source_map(), - map: [ - repeat(None).take(lo).collect(), - repeat(None).take(hi).collect(), - ], + map: vec![None; definitions.def_index_count()], parent_node: hir::CRATE_HIR_ID, current_signature_dep_index: root_mod_sig_dep_index, current_full_dep_index: root_mod_full_dep_index, @@ -231,7 +226,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { fn insert_entry(&mut self, id: HirId, entry: Entry<'hir>) { debug!("hir_map: {:?} => {:?}", id, entry); - let local_map = &mut self.map[id.owner.address_space().index()][id.owner.as_array_index()]; + let local_map = &mut self.map[id.owner.as_array_index()]; let i = id.local_id.as_u32() as usize; if local_map.is_none() { *local_map = Some(IndexVec::with_capacity(i + 1)); diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index ddef64f27e810..6e7a8f5bc234f 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -1,5 +1,5 @@ use crate::hir::map::definitions::*; -use crate::hir::def_id::{CRATE_DEF_INDEX, DefIndex, DefIndexAddressSpace}; +use crate::hir::def_id::{CRATE_DEF_INDEX, DefIndex}; use crate::session::CrateDisambiguator; use syntax::ast::*; @@ -10,8 +10,6 @@ use syntax::symbol::Symbol; use syntax::parse::token::{self, Token}; use syntax_pos::Span; -use crate::hir::map::{ITEM_LIKE_SPACE, REGULAR_SPACE}; - /// Creates `DefId`s for nodes in the AST. pub struct DefCollector<'a> { definitions: &'a mut Definitions, @@ -47,13 +45,12 @@ impl<'a> DefCollector<'a> { fn create_def(&mut self, node_id: NodeId, data: DefPathData, - address_space: DefIndexAddressSpace, span: Span) -> DefIndex { let parent_def = self.parent_def.unwrap(); debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def); self.definitions - .create_def_with_parent(parent_def, node_id, data, address_space, self.expansion, span) + .create_def_with_parent(parent_def, node_id, data, self.expansion, span) } pub fn with_parent(&mut self, parent_def: DefIndex, f: F) { @@ -85,9 +82,9 @@ impl<'a> DefCollector<'a> { // For async functions, we need to create their inner defs inside of a // closure to match their desugared representation. let fn_def_data = DefPathData::ValueNs(name.as_interned_str()); - let fn_def = self.create_def(id, fn_def_data, ITEM_LIKE_SPACE, span); + let fn_def = self.create_def(id, fn_def_data, span); return self.with_parent(fn_def, |this| { - this.create_def(*return_impl_trait_id, DefPathData::ImplTrait, REGULAR_SPACE, span); + this.create_def(*return_impl_trait_id, DefPathData::ImplTrait, span); visit::walk_generics(this, generics); @@ -106,7 +103,7 @@ impl<'a> DefCollector<'a> { visit::walk_fn_ret_ty(this, &decl.output); let closure_def = this.create_def( - *closure_id, DefPathData::ClosureExpr, REGULAR_SPACE, span, + *closure_id, DefPathData::ClosureExpr, span, ); this.with_parent(closure_def, |this| { use visit::Visitor; @@ -173,14 +170,14 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { return visit::walk_item(self, i); } }; - let def = self.create_def(i.id, def_data, ITEM_LIKE_SPACE, i.span); + let def = self.create_def(i.id, def_data, i.span); self.with_parent(def, |this| { match i.node { ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => { // If this is a unit or tuple-like struct, register the constructor. if let Some(ctor_hir_id) = struct_def.ctor_id() { - this.create_def(ctor_hir_id, DefPathData::Ctor, REGULAR_SPACE, i.span); + this.create_def(ctor_hir_id, DefPathData::Ctor, i.span); } } _ => {} @@ -190,7 +187,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { } fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) { - self.create_def(id, DefPathData::Misc, ITEM_LIKE_SPACE, use_tree.span); + self.create_def(id, DefPathData::Misc, use_tree.span); visit::walk_use_tree(self, use_tree, id); } @@ -201,7 +198,6 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { let def = self.create_def(foreign_item.id, DefPathData::ValueNs(foreign_item.ident.as_interned_str()), - REGULAR_SPACE, foreign_item.span); self.with_parent(def, |this| { @@ -212,11 +208,10 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_variant(&mut self, v: &'a Variant, g: &'a Generics, item_id: NodeId) { let def = self.create_def(v.node.id, DefPathData::TypeNs(v.node.ident.as_interned_str()), - REGULAR_SPACE, v.span); self.with_parent(def, |this| { if let Some(ctor_hir_id) = v.node.data.ctor_id() { - this.create_def(ctor_hir_id, DefPathData::Ctor, REGULAR_SPACE, v.span); + this.create_def(ctor_hir_id, DefPathData::Ctor, v.span); } visit::walk_variant(this, v, g, item_id) }); @@ -229,7 +224,6 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { .unwrap_or_else(|| Symbol::intern(&index.to_string())); let def = self.create_def(field.id, DefPathData::ValueNs(name.as_interned_str()), - REGULAR_SPACE, field.span); self.with_parent(def, |this| this.visit_struct_field(field)); } @@ -242,7 +236,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { GenericParamKind::Type { .. } => DefPathData::TypeNs(name), GenericParamKind::Const { .. } => DefPathData::ValueNs(name), }; - self.create_def(param.id, def_path_data, REGULAR_SPACE, param.ident.span); + self.create_def(param.id, def_path_data, param.ident.span); visit::walk_generic_param(self, param); } @@ -257,7 +251,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id), }; - let def = self.create_def(ti.id, def_data, ITEM_LIKE_SPACE, ti.span); + let def = self.create_def(ti.id, def_data, ti.span); self.with_parent(def, |this| visit::walk_trait_item(this, ti)); } @@ -286,7 +280,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id), }; - let def = self.create_def(ii.id, def_data, ITEM_LIKE_SPACE, ii.span); + let def = self.create_def(ii.id, def_data, ii.span); self.with_parent(def, |this| visit::walk_impl_item(this, ii)); } @@ -300,7 +294,6 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_anon_const(&mut self, constant: &'a AnonConst) { let def = self.create_def(constant.id, DefPathData::AnonConst, - REGULAR_SPACE, constant.value.span); self.with_parent(def, |this| visit::walk_anon_const(this, constant)); } @@ -313,7 +306,6 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { ExprKind::Closure(_, ref asyncness, ..) => { let closure_def = self.create_def(expr.id, DefPathData::ClosureExpr, - REGULAR_SPACE, expr.span); self.parent_def = Some(closure_def); @@ -322,7 +314,6 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { if let IsAsync::Async { closure_id, .. } = asyncness { let async_def = self.create_def(*closure_id, DefPathData::ClosureExpr, - REGULAR_SPACE, expr.span); self.parent_def = Some(async_def); } @@ -330,7 +321,6 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { ExprKind::Async(_, async_id, _) => { let async_def = self.create_def(async_id, DefPathData::ClosureExpr, - REGULAR_SPACE, expr.span); self.parent_def = Some(async_def); } @@ -345,7 +335,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { match ty.node { TyKind::Mac(..) => return self.visit_macro_invoc(ty.id), TyKind::ImplTrait(node_id, _) => { - self.create_def(node_id, DefPathData::ImplTrait, REGULAR_SPACE, ty.span); + self.create_def(node_id, DefPathData::ImplTrait, ty.span); } _ => {} } diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index fc9d6d86500ba..dc6cddc89f912 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -5,8 +5,7 @@ //! expressions) that are mostly just leftovers. use crate::hir; -use crate::hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, DefIndexAddressSpace, - CRATE_DEF_INDEX}; +use crate::hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, CRATE_DEF_INDEX}; use crate::ich::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::{IndexVec}; @@ -26,59 +25,41 @@ use crate::util::nodemap::NodeMap; /// Internally the DefPathTable holds a tree of DefKeys, where each DefKey /// stores the DefIndex of its parent. /// There is one DefPathTable for each crate. -#[derive(Default)] +#[derive(Clone, Default)] pub struct DefPathTable { - index_to_key: [Vec; 2], - def_path_hashes: [Vec; 2], -} - -// Unfortunately we have to provide a manual impl of Clone because of the -// fixed-sized array field. -impl Clone for DefPathTable { - fn clone(&self) -> Self { - DefPathTable { - index_to_key: [self.index_to_key[0].clone(), - self.index_to_key[1].clone()], - def_path_hashes: [self.def_path_hashes[0].clone(), - self.def_path_hashes[1].clone()], - } - } + index_to_key: Vec, + def_path_hashes: Vec, } impl DefPathTable { fn allocate(&mut self, key: DefKey, - def_path_hash: DefPathHash, - address_space: DefIndexAddressSpace) + def_path_hash: DefPathHash) -> DefIndex { let index = { - let index_to_key = &mut self.index_to_key[address_space.index()]; - let index = DefIndex::from_array_index(index_to_key.len(), address_space); + let index = DefIndex::from_array_index(self.index_to_key.len()); debug!("DefPathTable::insert() - {:?} <-> {:?}", key, index); - index_to_key.push(key); + self.index_to_key.push(key); index }; - self.def_path_hashes[address_space.index()].push(def_path_hash); - debug_assert!(self.def_path_hashes[address_space.index()].len() == - self.index_to_key[address_space.index()].len()); + self.def_path_hashes.push(def_path_hash); + debug_assert!(self.def_path_hashes.len() == self.index_to_key.len()); index } - pub fn next_id(&self, address_space: DefIndexAddressSpace) -> DefIndex { - DefIndex::from_array_index(self.index_to_key[address_space.index()].len(), address_space) + pub fn next_id(&self) -> DefIndex { + DefIndex::from_array_index(self.index_to_key.len()) } #[inline(always)] pub fn def_key(&self, index: DefIndex) -> DefKey { - self.index_to_key[index.address_space().index()] - [index.as_array_index()].clone() + self.index_to_key[index.as_array_index()].clone() } #[inline(always)] pub fn def_path_hash(&self, index: DefIndex) -> DefPathHash { - let ret = self.def_path_hashes[index.address_space().index()] - [index.as_array_index()]; + let ret = self.def_path_hashes[index.as_array_index()]; debug!("def_path_hash({:?}) = {:?}", index, ret); return ret } @@ -86,24 +67,22 @@ impl DefPathTable { pub fn add_def_path_hashes_to(&self, cnum: CrateNum, out: &mut FxHashMap) { - for &address_space in &[DefIndexAddressSpace::Low, DefIndexAddressSpace::High] { - out.extend( - (&self.def_path_hashes[address_space.index()]) - .iter() - .enumerate() - .map(|(index, &hash)| { - let def_id = DefId { - krate: cnum, - index: DefIndex::from_array_index(index, address_space), - }; - (hash, def_id) - }) - ); - } + out.extend( + self.def_path_hashes + .iter() + .enumerate() + .map(|(index, &hash)| { + let def_id = DefId { + krate: cnum, + index: DefIndex::from_array_index(index), + }; + (hash, def_id) + }) + ); } pub fn size(&self) -> usize { - self.index_to_key.iter().map(|v| v.len()).sum() + self.index_to_key.len() } } @@ -111,12 +90,10 @@ impl DefPathTable { impl Encodable for DefPathTable { fn encode(&self, s: &mut S) -> Result<(), S::Error> { // Index to key - self.index_to_key[DefIndexAddressSpace::Low.index()].encode(s)?; - self.index_to_key[DefIndexAddressSpace::High.index()].encode(s)?; + self.index_to_key.encode(s)?; // DefPath hashes - self.def_path_hashes[DefIndexAddressSpace::Low.index()].encode(s)?; - self.def_path_hashes[DefIndexAddressSpace::High.index()].encode(s)?; + self.def_path_hashes.encode(s)?; Ok(()) } @@ -124,18 +101,9 @@ impl Encodable for DefPathTable { impl Decodable for DefPathTable { fn decode(d: &mut D) -> Result { - let index_to_key_lo: Vec = Decodable::decode(d)?; - let index_to_key_hi: Vec = Decodable::decode(d)?; - - let def_path_hashes_lo: Vec = Decodable::decode(d)?; - let def_path_hashes_hi: Vec = Decodable::decode(d)?; - - let index_to_key = [index_to_key_lo, index_to_key_hi]; - let def_path_hashes = [def_path_hashes_lo, def_path_hashes_hi]; - Ok(DefPathTable { - index_to_key, - def_path_hashes, + index_to_key: Decodable::decode(d)?, + def_path_hashes : Decodable::decode(d)?, }) } } @@ -147,7 +115,7 @@ impl Decodable for DefPathTable { pub struct Definitions { table: DefPathTable, node_to_def_index: NodeMap, - def_index_to_node: [Vec; 2], + def_index_to_node: Vec, pub(super) node_to_hir_id: IndexVec, /// If `Mark` is an ID of some macro expansion, /// then `DefId` is the normal module (`mod`) in which the expanded macro was defined. @@ -374,30 +342,13 @@ impl Borrow for DefPathHash { } impl Definitions { - /// Creates new empty definition map. - /// - /// The `DefIndex` returned from a new `Definitions` are as follows: - /// 1. At `DefIndexAddressSpace::Low`, - /// CRATE_ROOT has index 0:0, and then new indexes are allocated in - /// ascending order. - /// 2. At `DefIndexAddressSpace::High`, - /// the first `FIRST_FREE_HIGH_DEF_INDEX` indexes are reserved for - /// internal use, then `1:FIRST_FREE_HIGH_DEF_INDEX` are allocated in - /// ascending order. - // - // FIXME: there is probably a better place to put this comment. - pub fn new() -> Self { - Self::default() - } - pub fn def_path_table(&self) -> &DefPathTable { &self.table } /// Gets the number of definitions. - pub fn def_index_counts_lo_hi(&self) -> (usize, usize) { - (self.table.index_to_key[DefIndexAddressSpace::Low.index()].len(), - self.table.index_to_key[DefIndexAddressSpace::High.index()].len()) + pub fn def_index_count(&self) -> usize { + self.table.index_to_key.len() } pub fn def_key(&self, index: DefIndex) -> DefKey { @@ -436,17 +387,12 @@ impl Definitions { #[inline] pub fn as_local_node_id(&self, def_id: DefId) -> Option { if def_id.krate == LOCAL_CRATE { - let space_index = def_id.index.address_space().index(); - let array_index = def_id.index.as_array_index(); - let node_id = self.def_index_to_node[space_index][array_index]; + let node_id = self.def_index_to_node[def_id.index.as_array_index()]; if node_id != ast::DUMMY_NODE_ID { - Some(node_id) - } else { - None + return Some(node_id); } - } else { - None } + None } // FIXME(@ljedrz): replace the NodeId variant @@ -471,9 +417,7 @@ impl Definitions { #[inline] pub fn def_index_to_hir_id(&self, def_index: DefIndex) -> hir::HirId { - let space_index = def_index.address_space().index(); - let array_index = def_index.as_array_index(); - let node_id = self.def_index_to_node[space_index][array_index]; + let node_id = self.def_index_to_node[def_index.as_array_index()]; self.node_to_hir_id[node_id] } @@ -488,7 +432,11 @@ impl Definitions { } } - /// Adds a root definition (no parent). + /// Adds a root definition (no parent) and a few other reserved definitions. + /// + /// After the initial definitions are created the first `FIRST_FREE_DEF_INDEX` indexes + /// are taken, so the "user" indexes will be allocated starting with `FIRST_FREE_DEF_INDEX` + /// in ascending order. pub fn create_root_def(&mut self, crate_name: &str, crate_disambiguator: CrateDisambiguator) @@ -506,11 +454,10 @@ impl Definitions { let def_path_hash = key.compute_stable_hash(parent_hash); // Create the definition. - let address_space = super::ITEM_LIKE_SPACE; - let root_index = self.table.allocate(key, def_path_hash, address_space); + let root_index = self.table.allocate(key, def_path_hash); assert_eq!(root_index, CRATE_DEF_INDEX); - assert!(self.def_index_to_node[address_space.index()].is_empty()); - self.def_index_to_node[address_space.index()].push(ast::CRATE_NODE_ID); + assert!(self.def_index_to_node.is_empty()); + self.def_index_to_node.push(ast::CRATE_NODE_ID); self.node_to_def_index.insert(ast::CRATE_NODE_ID, root_index); // Allocate some other DefIndices that always must exist. @@ -524,7 +471,6 @@ impl Definitions { parent: DefIndex, node_id: ast::NodeId, data: DefPathData, - address_space: DefIndexAddressSpace, expansion: Mark, span: Span) -> DefIndex { @@ -561,10 +507,9 @@ impl Definitions { debug!("create_def_with_parent: after disambiguation, key = {:?}", key); // Create the definition. - let index = self.table.allocate(key, def_path_hash, address_space); - assert_eq!(index.as_array_index(), - self.def_index_to_node[address_space.index()].len()); - self.def_index_to_node[address_space.index()].push(node_id); + let index = self.table.allocate(key, def_path_hash); + assert_eq!(index.as_array_index(), self.def_index_to_node.len()); + self.def_index_to_node.push(node_id); // Some things for which we allocate DefIndices don't correspond to // anything in the AST, so they don't have a NodeId. For these cases @@ -673,8 +618,7 @@ macro_rules! define_global_metadata_kind { $($variant),* } - const GLOBAL_MD_ADDRESS_SPACE: DefIndexAddressSpace = DefIndexAddressSpace::High; - pub const FIRST_FREE_HIGH_DEF_INDEX: usize = count!($($variant)*); + pub const FIRST_FREE_DEF_INDEX: usize = 1 + count!($($variant)*); impl GlobalMetaDataKind { fn allocate_def_indices(definitions: &mut Definitions) { @@ -684,7 +628,6 @@ macro_rules! define_global_metadata_kind { CRATE_DEF_INDEX, ast::DUMMY_NODE_ID, DefPathData::GlobalMetaData(instance.name().as_interned_str()), - GLOBAL_MD_ADDRESS_SPACE, Mark::root(), DUMMY_SP ); @@ -705,12 +648,12 @@ macro_rules! define_global_metadata_kind { // These DefKeys are all right after the root, // so a linear search is fine. - let index = def_path_table.index_to_key[GLOBAL_MD_ADDRESS_SPACE.index()] + let index = def_path_table.index_to_key .iter() .position(|k| *k == def_key) .unwrap(); - DefIndex::from_array_index(index, GLOBAL_MD_ADDRESS_SPACE) + DefIndex::from_array_index(index) } fn name(&self) -> Symbol { diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index c2b513a39a8b7..9088d0c165670 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -5,7 +5,7 @@ pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData, use crate::dep_graph::{DepGraph, DepNode, DepKind, DepNodeIndex}; -use crate::hir::def_id::{CRATE_DEF_INDEX, DefId, LocalDefId, DefIndexAddressSpace}; +use crate::hir::def_id::{CRATE_DEF_INDEX, DefId, LocalDefId}; use crate::middle::cstore::CrateStoreDyn; @@ -34,9 +34,6 @@ mod def_collector; pub mod definitions; mod hir_id_validator; -pub const ITEM_LIKE_SPACE: DefIndexAddressSpace = DefIndexAddressSpace::Low; -pub const REGULAR_SPACE: DefIndexAddressSpace = DefIndexAddressSpace::High; - /// Represents an entry and its parent `NodeId`. #[derive(Copy, Clone, Debug)] pub struct Entry<'hir> { @@ -163,11 +160,10 @@ impl Forest { } /// This type is effectively a `HashMap>`, -/// but is implemented by 3 layers of arrays. -/// - the outer layer is `[A; 2]` and correspond to the 2 address spaces `DefIndex`es can be in -/// - then we have `A = Vec>` mapping a `DefIndex`'s index to a inner value -/// - which is `B = IndexVec>` which finally gives you the `Entry`. -pub(super) type HirEntryMap<'hir> = [Vec>>>>; 2]; +/// but it is implemented as 2 layers of arrays. +/// - first we have `A = Vec>` mapping a `DefIndex`'s index to an inner value +/// - which is `B = IndexVec>` which gives you the `Entry`. +pub(super) type HirEntryMap<'hir> = Vec>>>>; /// Represents a mapping from `NodeId`s to AST elements and their parent `NodeId`s. #[derive(Clone)] @@ -193,7 +189,7 @@ pub struct Map<'hir> { impl<'hir> Map<'hir> { #[inline] fn lookup(&self, id: HirId) -> Option<&Entry<'hir>> { - let local_map = self.map[id.owner.address_space().index()].get(id.owner.as_array_index())?; + let local_map = self.map.get(id.owner.as_array_index())?; local_map.as_ref()?.get(id.local_id)?.as_ref() } @@ -1016,29 +1012,21 @@ impl<'hir> Map<'hir> { /// Returns an iterator that yields all the hir ids in the map. fn all_ids<'a>(&'a self) -> impl Iterator + 'a { - // This code is a bit awkward because the map is implemented as 3 levels of arrays, + // This code is a bit awkward because the map is implemented as 2 levels of arrays, // see the comment on `HirEntryMap`. - let map = &self.map; - - // Look at both the def index address spaces - let spaces = [DefIndexAddressSpace::Low, DefIndexAddressSpace::High].iter().cloned(); - spaces.flat_map(move |space| { - // Iterate over all the indices in the address space and return a reference to - // local maps and their index given that they exist. - let local_maps = map[space.index()].iter().enumerate().filter_map(|(i, local_map)| { - local_map.as_ref().map(|m| (i, m)) - }); - - local_maps.flat_map(move |(array_index, local_map)| { - // Iterate over each valid entry in the local map - local_map.iter_enumerated().filter_map(move |(i, entry)| entry.map(move |_| { - // Reconstruct the HirId based on the 3 indices we used to find it - HirId { - owner: DefIndex::from_array_index(array_index, space), - local_id: i, - } - })) - }) + // Iterate over all the indices and return a reference to + // local maps and their index given that they exist. + self.map.iter().enumerate().filter_map(|(i, local_map)| { + local_map.as_ref().map(|m| (i, m)) + }).flat_map(move |(array_index, local_map)| { + // Iterate over each valid entry in the local map + local_map.iter_enumerated().filter_map(move |(i, entry)| entry.map(move |_| { + // Reconstruct the HirId based on the 3 indices we used to find it + HirId { + owner: DefIndex::from_array_index(array_index), + local_id: i, + } + })) }) } diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 384a5862cde0c..2496419640c2e 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -298,9 +298,7 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>( // negated `CrateNum` (so remote definitions are visited first) and then // by a flattened version of the `DefIndex`. trait_impls.sort_unstable_by_key(|def_id| { - (-(def_id.krate.as_u32() as i64), - def_id.index.address_space().index(), - def_id.index.as_array_index()) + (-(def_id.krate.as_u32() as i64), def_id.index.as_array_index()) }); for impl_def_id in trait_impls { diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index a339ec30a74f8..fc8bf0baa99f6 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -647,8 +647,7 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec, // alphanumeric. This does not appear in the rendered graph, so it does not // have to be user friendly. let name = format!( - "hir_id_{}_{}_{}", - hir_id.owner.address_space().index(), + "hir_id_{}_{}", hir_id.owner.as_array_index(), hir_id.local_id.index(), ); diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 048acf56ea7a7..4b9db466da843 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -9,8 +9,7 @@ use rustc::hir; use rustc::middle::cstore::LinkagePreference; use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc::hir::def::{self, Res, DefKind, CtorOf, CtorKind}; -use rustc::hir::def_id::{CrateNum, DefId, DefIndex, DefIndexAddressSpace, - CRATE_DEF_INDEX, LOCAL_CRATE, LocalDefId}; +use rustc::hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc::hir::map::definitions::DefPathTable; use rustc_data_structures::fingerprint::Fingerprint; use rustc::middle::lang_items; @@ -449,7 +448,7 @@ crate fn proc_macro_def_path_table(crate_root: &CrateRoot, proc_macros: &[(ast::Name, Lrc)]) -> DefPathTable { - let mut definitions = Definitions::new(); + let mut definitions = Definitions::default(); let name = crate_root.name.as_str(); let disambiguator = crate_root.disambiguator; @@ -460,7 +459,6 @@ crate fn proc_macro_def_path_table(crate_root: &CrateRoot, crate_root, ast::DUMMY_NODE_ID, DefPathData::MacroNs(name.as_interned_str()), - DefIndexAddressSpace::High, Mark::root(), DUMMY_SP); debug!("definition for {:?} is {:?}", name, def_index); diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/index.rs index f9543a18c68a7..4c1e39cd0a9e1 100644 --- a/src/librustc_metadata/index.rs +++ b/src/librustc_metadata/index.rs @@ -1,6 +1,6 @@ use crate::schema::*; -use rustc::hir::def_id::{DefId, DefIndex, DefIndexAddressSpace}; +use rustc::hir::def_id::{DefId, DefIndex}; use rustc_serialize::opaque::Encoder; use std::u32; use log::debug; @@ -75,14 +75,13 @@ impl FixedSizeEncoding for u32 { /// appropriate spot by calling `record_position`. We should never /// visit the same index twice. pub struct Index { - positions: [Vec; 2] + positions: Vec, } impl Index { - pub fn new((max_index_lo, max_index_hi): (usize, usize)) -> Index { + pub fn new(max_index: usize) -> Index { Index { - positions: [vec![0xff; max_index_lo * 4], - vec![0xff; max_index_hi * 4]], + positions: vec![0xff; max_index * 4], } } @@ -94,10 +93,9 @@ impl Index { pub fn record_index(&mut self, item: DefIndex, entry: Lazy>) { assert!(entry.position < (u32::MAX as usize)); let position = entry.position as u32; - let space_index = item.address_space().index(); let array_index = item.as_array_index(); - let positions = &mut self.positions[space_index]; + let positions = &mut self.positions; assert!(u32::read_from_bytes_at(positions, array_index) == u32::MAX, "recorded position for item {:?} twice, first at {:?} and now at {:?}", item, @@ -111,13 +109,10 @@ impl Index { let pos = buf.position(); // First we write the length of the lower range ... - buf.emit_raw_bytes(&(self.positions[0].len() as u32 / 4).to_le_bytes()); - // ... then the values in the lower range ... - buf.emit_raw_bytes(&self.positions[0]); - // ... then the values in the higher range. - buf.emit_raw_bytes(&self.positions[1]); - LazySeq::with_position_and_length(pos as usize, - (self.positions[0].len() + self.positions[1].len()) / 4 + 1) + buf.emit_raw_bytes(&(self.positions.len() as u32 / 4).to_le_bytes()); + // ... then the values. + buf.emit_raw_bytes(&self.positions); + LazySeq::with_position_and_length(pos as usize, self.positions.len() / 4 + 1) } } @@ -131,16 +126,7 @@ impl<'tcx> LazySeq { def_index, self.len); - let i = def_index.as_array_index() + match def_index.address_space() { - DefIndexAddressSpace::Low => 0, - DefIndexAddressSpace::High => { - // This is a DefIndex in the higher range, so find out where - // that starts: - u32::read_from_bytes_at(bytes, 0) as usize - } - }; - - let position = u32::read_from_bytes_at(bytes, 1 + i); + let position = u32::read_from_bytes_at(bytes, 1 + def_index.as_array_index()); if position == u32::MAX { debug!("Index::lookup: position=u32::MAX"); None diff --git a/src/librustc_metadata/index_builder.rs b/src/librustc_metadata/index_builder.rs index b77feeee06f57..e780693a5a92d 100644 --- a/src/librustc_metadata/index_builder.rs +++ b/src/librustc_metadata/index_builder.rs @@ -80,7 +80,7 @@ impl<'a, 'b, 'tcx> DerefMut for IndexBuilder<'a, 'b, 'tcx> { impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { pub fn new(ecx: &'a mut EncodeContext<'b, 'tcx>) -> Self { IndexBuilder { - items: Index::new(ecx.tcx.hir().definitions().def_index_counts_lo_hi()), + items: Index::new(ecx.tcx.hir().definitions().def_index_count()), ecx, } } diff --git a/src/librustc_mir/util/graphviz.rs b/src/librustc_mir/util/graphviz.rs index f87714b58c442..04b0e16cd9a81 100644 --- a/src/librustc_mir/util/graphviz.rs +++ b/src/librustc_mir/util/graphviz.rs @@ -25,9 +25,8 @@ pub fn write_mir_graphviz<'tcx, W>(tcx: TyCtxt<'_, '_, 'tcx>, // it does not have to be user friendly. pub fn graphviz_safe_def_name(def_id: DefId) -> String { format!( - "{}_{}_{}", + "{}_{}", def_id.krate.index(), - def_id.index.address_space().index(), def_id.index.as_array_index(), ) } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index f8f6e5b1cd012..18da89b9099a5 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1970,7 +1970,7 @@ impl<'a> Resolver<'a> { let mut module_map = FxHashMap::default(); module_map.insert(DefId::local(CRATE_DEF_INDEX), graph_root); - let mut definitions = Definitions::new(); + let mut definitions = Definitions::default(); DefCollector::new(&mut definitions, Mark::root()) .collect_root(crate_name, session.local_crate_disambiguator()); diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index f1706a4616b06..79a92d595c2ed 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -6,8 +6,7 @@ use crate::ModuleOrUniformRoot; use crate::Namespace::*; use crate::build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport}; use crate::resolve_imports::ImportResolver; -use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, DefIndex, - CrateNum, DefIndexAddressSpace}; +use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX}; use rustc::hir::def::{self, DefKind, NonMacroAttrKind}; use rustc::hir::map::{self, DefCollector}; use rustc::{ty, lint}; @@ -173,8 +172,7 @@ impl<'a> base::Resolver for Resolver<'a> { fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc) { let def_id = DefId { krate: CrateNum::BuiltinMacros, - index: DefIndex::from_array_index(self.macro_map.len(), - DefIndexAddressSpace::Low), + index: DefIndex::from_array_index(self.macro_map.len()), }; let kind = ext.kind(); self.macro_map.insert(def_id, ext); diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 5555ea302c96f..e91e3a029dacf 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -1,6 +1,6 @@ use rustc_lint; use rustc::session::{self, config}; -use rustc::hir::def_id::{DefId, DefIndex, DefIndexAddressSpace, CrateNum, LOCAL_CRATE}; +use rustc::hir::def_id::{DefId, DefIndex, CrateNum, LOCAL_CRATE}; use rustc::hir::HirId; use rustc::middle::cstore::CrateStore; use rustc::middle::privacy::AccessLevels; @@ -112,8 +112,8 @@ impl<'tcx> DocContext<'tcx> { // registered after the AST is constructed would require storing the defid mapping in a // RefCell, decreasing the performance for normal compilation for very little gain. // - // Instead, we construct 'fake' def ids, which start immediately after the last DefId in - // DefIndexAddressSpace::Low. In the Debug impl for clean::Item, we explicitly check for fake + // Instead, we construct 'fake' def ids, which start immediately after the last DefId. + // In the Debug impl for clean::Item, we explicitly check for fake // def ids, as we'll end up with a panic if we use the DefId Debug impl for fake DefIds pub fn next_def_id(&self, crate_num: CrateNum) -> DefId { let start_def_id = { @@ -122,11 +122,11 @@ impl<'tcx> DocContext<'tcx> { .hir() .definitions() .def_path_table() - .next_id(DefIndexAddressSpace::Low) + .next_id() } else { self.cstore .def_path_table(crate_num) - .next_id(DefIndexAddressSpace::Low) + .next_id() }; DefId { @@ -142,10 +142,7 @@ impl<'tcx> DocContext<'tcx> { crate_num, DefId { krate: crate_num, - index: DefIndex::from_array_index( - def_id.index.as_array_index() + 1, - def_id.index.address_space(), - ), + index: DefIndex::from_array_index(def_id.index.as_array_index() + 1), }, ); diff --git a/src/test/mir-opt/graphviz.rs b/src/test/mir-opt/graphviz.rs index 660576996e5d4..67a6d1d263bf5 100644 --- a/src/test/mir-opt/graphviz.rs +++ b/src/test/mir-opt/graphviz.rs @@ -7,7 +7,7 @@ fn main() {} // END RUST SOURCE // START rustc.main.mir_map.0.dot -// digraph Mir_0_0_3 { // The name here MUST be an ASCII identifier. +// digraph Mir_0_12 { // The name here MUST be an ASCII identifier. // graph [fontname="monospace"]; // node [fontname="monospace"]; // edge [fontname="monospace"]; diff --git a/src/test/mir-opt/inline-closure-borrows-arg.rs b/src/test/mir-opt/inline-closure-borrows-arg.rs index 84567e1b4b8f2..0e1db68f37255 100644 --- a/src/test/mir-opt/inline-closure-borrows-arg.rs +++ b/src/test/mir-opt/inline-closure-borrows-arg.rs @@ -20,7 +20,7 @@ fn foo(_t: T, q: &i32) -> i32 { // ... // bb0: { // ... -// _3 = [closure@HirId { owner: DefIndex(0:4), local_id: 31 }]; +// _3 = [closure@HirId { owner: DefIndex(13), local_id: 31 }]; // ... // _4 = &_3; // ... diff --git a/src/test/mir-opt/inline-closure.rs b/src/test/mir-opt/inline-closure.rs index 2be48927fd3b7..fa8557f3b38a7 100644 --- a/src/test/mir-opt/inline-closure.rs +++ b/src/test/mir-opt/inline-closure.rs @@ -16,7 +16,7 @@ fn foo(_t: T, q: i32) -> i32 { // ... // bb0: { // ... -// _3 = [closure@HirId { owner: DefIndex(0:4), local_id: 15 }]; +// _3 = [closure@HirId { owner: DefIndex(13), local_id: 15 }]; // ... // _4 = &_3; // ... diff --git a/src/test/mir-opt/retag.rs b/src/test/mir-opt/retag.rs index 6b7c863fcd43f..33ee0fe61b288 100644 --- a/src/test/mir-opt/retag.rs +++ b/src/test/mir-opt/retag.rs @@ -98,7 +98,7 @@ fn main() { // } // END rustc.main.EraseRegions.after.mir // START rustc.main-{{closure}}.EraseRegions.after.mir -// fn main::{{closure}}#0(_1: &[closure@HirId { owner: DefIndex(0:7), local_id: 72 }], _2: &i32) -> &i32 { +// fn main::{{closure}}#0(_1: &[closure@HirId { owner: DefIndex(20), local_id: 72 }], _2: &i32) -> &i32 { // ... // bb0: { // Retag([fn entry] _1); diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr index 20041389b3c38..cc5ffca10475e 100644 --- a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr +++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr @@ -4,9 +4,9 @@ note: No external requirements LL | let mut closure = expect_sig(|p, y| *p = y); | ^^^^^^^^^^^^^ | - = note: defining type: DefId(0/1:9 ~ escape_argument_callee[317d]::test[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:13 ~ escape_argument_callee[317d]::test[0]::{{closure}}[0]) with closure substs [ i16, - for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) mut &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) i32)), + for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) mut &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't0)) i32)), ] error: lifetime may not live long enough @@ -30,7 +30,7 @@ LL | | deref(p); LL | | } | |_^ | - = note: defining type: DefId(0/0:3 ~ escape_argument_callee[317d]::test[0]) with substs [] + = note: defining type: DefId(0:12 ~ escape_argument_callee[317d]::test[0]) with substs [] error: aborting due to previous error diff --git a/src/test/ui/nll/closure-requirements/escape-argument.stderr b/src/test/ui/nll/closure-requirements/escape-argument.stderr index b08ec9539318a..fdf95b8acebfc 100644 --- a/src/test/ui/nll/closure-requirements/escape-argument.stderr +++ b/src/test/ui/nll/closure-requirements/escape-argument.stderr @@ -4,9 +4,9 @@ note: No external requirements LL | let mut closure = expect_sig(|p, y| *p = y); | ^^^^^^^^^^^^^ | - = note: defining type: DefId(0/1:9 ~ escape_argument[317d]::test[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:13 ~ escape_argument[317d]::test[0]::{{closure}}[0]) with closure substs [ i16, - for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) mut &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) i32)), + for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) mut &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) i32)), ] note: No external requirements @@ -21,7 +21,7 @@ LL | | deref(p); LL | | } | |_^ | - = note: defining type: DefId(0/0:3 ~ escape_argument[317d]::test[0]) with substs [] + = note: defining type: DefId(0:12 ~ escape_argument[317d]::test[0]) with substs [] error[E0597]: `y` does not live long enough --> $DIR/escape-argument.rs:27:25 diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr index 7178b22bb5f2d..135de0445a799 100644 --- a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr +++ b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr @@ -4,7 +4,7 @@ note: External requirements LL | let mut closure1 = || p = &y; | ^^^^^^^^^ | - = note: defining type: DefId(0/1:10 ~ escape_upvar_nested[317d]::test[0]::{{closure}}[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:14 ~ escape_upvar_nested[317d]::test[0]::{{closure}}[0]::{{closure}}[0]) with closure substs [ i16, extern "rust-call" fn(()), &'_#1r mut &'_#2r i32, @@ -23,7 +23,7 @@ LL | | closure1(); LL | | }; | |_________^ | - = note: defining type: DefId(0/1:9 ~ escape_upvar_nested[317d]::test[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:13 ~ escape_upvar_nested[317d]::test[0]::{{closure}}[0]) with closure substs [ i16, extern "rust-call" fn(()), &'_#1r mut &'_#2r i32, @@ -44,7 +44,7 @@ LL | | deref(p); LL | | } | |_^ | - = note: defining type: DefId(0/0:3 ~ escape_upvar_nested[317d]::test[0]) with substs [] + = note: defining type: DefId(0:12 ~ escape_upvar_nested[317d]::test[0]) with substs [] error[E0597]: `y` does not live long enough --> $DIR/escape-upvar-nested.rs:21:40 diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr index d129f945f252a..8c37ab7b768c3 100644 --- a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr +++ b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr @@ -4,7 +4,7 @@ note: External requirements LL | let mut closure = || p = &y; | ^^^^^^^^^ | - = note: defining type: DefId(0/1:9 ~ escape_upvar_ref[317d]::test[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:13 ~ escape_upvar_ref[317d]::test[0]::{{closure}}[0]) with closure substs [ i16, extern "rust-call" fn(()), &'_#1r mut &'_#2r i32, @@ -25,7 +25,7 @@ LL | | deref(p); LL | | } | |_^ | - = note: defining type: DefId(0/0:3 ~ escape_upvar_ref[317d]::test[0]) with substs [] + = note: defining type: DefId(0:12 ~ escape_upvar_ref[317d]::test[0]) with substs [] error[E0597]: `y` does not live long enough --> $DIR/escape-upvar-ref.rs:23:35 diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr index 4db1f04077043..8916fdcfc88f1 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr @@ -8,9 +8,9 @@ LL | | demand_y(x, y, p) LL | | }, | |_________^ | - = note: defining type: DefId(0/1:20 ~ propagate_approximated_fail_no_postdom[317d]::supply[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:27 ~ propagate_approximated_fail_no_postdom[317d]::supply[0]::{{closure}}[0]) with closure substs [ i16, - for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>)), + for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) u32>)), ] = note: late-bound region is '_#4r = note: late-bound region is '_#5r @@ -39,7 +39,7 @@ LL | | ); LL | | } | |_^ | - = note: defining type: DefId(0/0:6 ~ propagate_approximated_fail_no_postdom[317d]::supply[0]) with substs [] + = note: defining type: DefId(0:23 ~ propagate_approximated_fail_no_postdom[317d]::supply[0]) with substs [] error: aborting due to previous error diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr index 7dedae715bea0..fa8384311ea57 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr @@ -9,9 +9,9 @@ LL | | LL | | }); | |_____^ | - = note: defining type: DefId(0/1:18 ~ propagate_approximated_ref[317d]::supply[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:25 ~ propagate_approximated_ref[317d]::supply[0]::{{closure}}[0]) with closure substs [ i16, - for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>)), + for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't1)) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't1)) u32>)), ] = note: late-bound region is '_#3r = note: late-bound region is '_#4r @@ -30,7 +30,7 @@ LL | | }); LL | | } | |_^ | - = note: defining type: DefId(0/0:6 ~ propagate_approximated_ref[317d]::supply[0]) with substs [] + = note: defining type: DefId(0:22 ~ propagate_approximated_ref[317d]::supply[0]) with substs [] error: lifetime may not live long enough --> $DIR/propagate-approximated-ref.rs:45:9 diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr index 6d1baf9f827db..cfaa75b8ef861 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr @@ -8,9 +8,9 @@ LL | | LL | | }) | |_____^ | - = note: defining type: DefId(0/1:12 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case1[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:18 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case1[0]::{{closure}}[0]) with closure substs [ i32, - for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>)), + for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) u32>)), ] error[E0521]: borrowed data escapes outside of closure @@ -35,7 +35,7 @@ LL | | }) LL | | } | |_^ | - = note: defining type: DefId(0/0:5 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case1[0]) with substs [] + = note: defining type: DefId(0:17 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case1[0]) with substs [] note: External requirements --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:35:15 @@ -46,9 +46,9 @@ LL | | cell_x.set(cell_a.get()); // forces 'a: 'x, implies 'a = 'static LL | | }) | |_____^ | - = note: defining type: DefId(0/1:13 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case2[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:20 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case2[0]::{{closure}}[0]) with closure substs [ i32, - for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>)), + for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) u32>)), ] = note: number of external vids: 2 = note: where '_#1r: '_#0r @@ -65,7 +65,7 @@ LL | | }) LL | | } | |_^ | - = note: defining type: DefId(0/0:6 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case2[0]) with substs [] + = note: defining type: DefId(0:19 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case2[0]) with substs [] error[E0597]: `a` does not live long enough --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:30:26 diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr index ea04a47a4804b..601b3577e0eec 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr @@ -10,9 +10,9 @@ LL | | demand_y(x, y, x.get()) LL | | }); | |_____^ | - = note: defining type: DefId(0/1:18 ~ propagate_approximated_shorter_to_static_no_bound[317d]::supply[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:25 ~ propagate_approximated_shorter_to_static_no_bound[317d]::supply[0]::{{closure}}[0]) with closure substs [ i16, - for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) u32>)), + for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't1)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't2)) u32>)), ] = note: late-bound region is '_#2r = note: late-bound region is '_#3r @@ -31,7 +31,7 @@ LL | | }); LL | | } | |_^ | - = note: defining type: DefId(0/0:6 ~ propagate_approximated_shorter_to_static_no_bound[317d]::supply[0]) with substs [] + = note: defining type: DefId(0:22 ~ propagate_approximated_shorter_to_static_no_bound[317d]::supply[0]) with substs [] error[E0521]: borrowed data escapes outside of function --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:32:5 diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr index 033357b09fb2e..5b5440e7a9641 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr @@ -10,9 +10,9 @@ LL | | demand_y(x, y, x.get()) LL | | }); | |_____^ | - = note: defining type: DefId(0/1:18 ~ propagate_approximated_shorter_to_static_wrong_bound[317d]::supply[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:25 ~ propagate_approximated_shorter_to_static_wrong_bound[317d]::supply[0]::{{closure}}[0]) with closure substs [ i16, - for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>)), + for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't0)) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't1)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't1)) u32>)), ] = note: late-bound region is '_#3r = note: late-bound region is '_#4r @@ -31,7 +31,7 @@ LL | | }); LL | | } | |_^ | - = note: defining type: DefId(0/0:6 ~ propagate_approximated_shorter_to_static_wrong_bound[317d]::supply[0]) with substs [] + = note: defining type: DefId(0:22 ~ propagate_approximated_shorter_to_static_wrong_bound[317d]::supply[0]) with substs [] error[E0521]: borrowed data escapes outside of function --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:35:5 diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr index 223c29f596922..a08cde2c9c635 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr @@ -9,9 +9,9 @@ LL | | LL | | }); | |_____^ | - = note: defining type: DefId(0/1:18 ~ propagate_approximated_val[317d]::test[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:25 ~ propagate_approximated_val[317d]::test[0]::{{closure}}[0]) with closure substs [ i16, - for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>)), + for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) u32>)), ] = note: late-bound region is '_#3r = note: late-bound region is '_#4r @@ -30,7 +30,7 @@ LL | | }); LL | | } | |_^ | - = note: defining type: DefId(0/0:6 ~ propagate_approximated_val[317d]::test[0]) with substs [] + = note: defining type: DefId(0:22 ~ propagate_approximated_val[317d]::test[0]) with substs [] error: lifetime may not live long enough --> $DIR/propagate-approximated-val.rs:38:9 diff --git a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr index d618b4d06a1d8..60847bb2e9290 100644 --- a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr @@ -8,9 +8,9 @@ LL | | demand_y(x, y, p) LL | | }, | |_________^ | - = note: defining type: DefId(0/1:16 ~ propagate_despite_same_free_region[317d]::supply[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:23 ~ propagate_despite_same_free_region[317d]::supply[0]::{{closure}}[0]) with closure substs [ i16, - for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>)), + for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) u32>)), ] = note: late-bound region is '_#3r = note: number of external vids: 4 @@ -28,5 +28,5 @@ LL | | ); LL | | } | |_^ | - = note: defining type: DefId(0/0:6 ~ propagate_despite_same_free_region[317d]::supply[0]) with substs [] + = note: defining type: DefId(0:21 ~ propagate_despite_same_free_region[317d]::supply[0]) with substs [] diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr index 07fb4d0d5e3ae..a660c763bff78 100644 --- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr @@ -9,9 +9,9 @@ LL | | LL | | }); | |_____^ | - = note: defining type: DefId(0/1:18 ~ propagate_fail_to_approximate_longer_no_bounds[317d]::supply[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:25 ~ propagate_fail_to_approximate_longer_no_bounds[317d]::supply[0]::{{closure}}[0]) with closure substs [ i16, - for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>)), + for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't1)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) u32>)), ] = note: late-bound region is '_#2r = note: late-bound region is '_#3r @@ -39,7 +39,7 @@ LL | | }); LL | | } | |_^ | - = note: defining type: DefId(0/0:6 ~ propagate_fail_to_approximate_longer_no_bounds[317d]::supply[0]) with substs [] + = note: defining type: DefId(0:22 ~ propagate_fail_to_approximate_longer_no_bounds[317d]::supply[0]) with substs [] error: aborting due to previous error diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr index a0744c27db72c..9671b8ebff3a4 100644 --- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr @@ -9,9 +9,9 @@ LL | | LL | | }); | |_____^ | - = note: defining type: DefId(0/1:18 ~ propagate_fail_to_approximate_longer_wrong_bounds[317d]::supply[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:25 ~ propagate_fail_to_approximate_longer_wrong_bounds[317d]::supply[0]::{{closure}}[0]) with closure substs [ i16, - for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>)), + for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't1)) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 't1)) u32>)), ] = note: late-bound region is '_#3r = note: late-bound region is '_#4r @@ -39,7 +39,7 @@ LL | | }); LL | | } | |_^ | - = note: defining type: DefId(0/0:6 ~ propagate_fail_to_approximate_longer_wrong_bounds[317d]::supply[0]) with substs [] + = note: defining type: DefId(0:22 ~ propagate_fail_to_approximate_longer_wrong_bounds[317d]::supply[0]) with substs [] error: aborting due to previous error diff --git a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr index 282246f81666b..457b5950b7ff0 100644 --- a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr @@ -11,7 +11,7 @@ LL | | require(value); LL | | }); | |_____^ | - = note: defining type: DefId(0/1:16 ~ propagate_from_trait_match[317d]::supply[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:23 ~ propagate_from_trait_match[317d]::supply[0]::{{closure}}[0]) with closure substs [ '_#1r, T, i32, @@ -32,7 +32,7 @@ LL | | }); LL | | } | |_^ | - = note: defining type: DefId(0/0:6 ~ propagate_from_trait_match[317d]::supply[0]) with substs [ + = note: defining type: DefId(0:20 ~ propagate_from_trait_match[317d]::supply[0]) with substs [ '_#1r, T, ] diff --git a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr index c5645413c77cd..8aff6d5b89279 100644 --- a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr +++ b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr @@ -4,9 +4,9 @@ note: No external requirements LL | expect_sig(|a, b| b); // ought to return `a` | ^^^^^^^^ | - = note: defining type: DefId(0/1:9 ~ return_wrong_bound_region[317d]::test[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:13 ~ return_wrong_bound_region[317d]::test[0]::{{closure}}[0]) with closure substs [ i16, - for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) i32)) -> &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) i32, + for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) i32)) -> &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 'r)) i32, ] error: lifetime may not live long enough @@ -27,7 +27,7 @@ LL | | LL | | } | |_^ | - = note: defining type: DefId(0/0:3 ~ return_wrong_bound_region[317d]::test[0]) with substs [] + = note: defining type: DefId(0:12 ~ return_wrong_bound_region[317d]::test[0]) with substs [] error: aborting due to previous error diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr index cda1f7d36311c..9fa54e83812f7 100644 --- a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr @@ -4,7 +4,7 @@ note: External requirements LL | with_signature(x, |mut y| Box::new(y.next())) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: defining type: DefId(0/1:15 ~ projection_no_regions_closure[317d]::no_region[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:22 ~ projection_no_regions_closure[317d]::no_region[0]::{{closure}}[0]) with closure substs [ '_#1r, T, i32, @@ -25,7 +25,7 @@ LL | | LL | | } | |_^ | - = note: defining type: DefId(0/0:6 ~ projection_no_regions_closure[317d]::no_region[0]) with substs [ + = note: defining type: DefId(0:19 ~ projection_no_regions_closure[317d]::no_region[0]) with substs [ '_#1r, T, ] @@ -44,7 +44,7 @@ note: External requirements LL | with_signature(x, |mut y| Box::new(y.next())) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: defining type: DefId(0/1:18 ~ projection_no_regions_closure[317d]::correct_region[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:26 ~ projection_no_regions_closure[317d]::correct_region[0]::{{closure}}[0]) with closure substs [ '_#1r, T, i32, @@ -64,7 +64,7 @@ LL | | with_signature(x, |mut y| Box::new(y.next())) LL | | } | |_^ | - = note: defining type: DefId(0/0:7 ~ projection_no_regions_closure[317d]::correct_region[0]) with substs [ + = note: defining type: DefId(0:23 ~ projection_no_regions_closure[317d]::correct_region[0]) with substs [ '_#1r, T, ] @@ -75,7 +75,7 @@ note: External requirements LL | with_signature(x, |mut y| Box::new(y.next())) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: defining type: DefId(0/1:22 ~ projection_no_regions_closure[317d]::wrong_region[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:31 ~ projection_no_regions_closure[317d]::wrong_region[0]::{{closure}}[0]) with closure substs [ '_#1r, '_#2r, T, @@ -97,7 +97,7 @@ LL | | LL | | } | |_^ | - = note: defining type: DefId(0/0:8 ~ projection_no_regions_closure[317d]::wrong_region[0]) with substs [ + = note: defining type: DefId(0:27 ~ projection_no_regions_closure[317d]::wrong_region[0]) with substs [ '_#1r, '_#2r, T, @@ -117,7 +117,7 @@ note: External requirements LL | with_signature(x, |mut y| Box::new(y.next())) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: defining type: DefId(0/1:26 ~ projection_no_regions_closure[317d]::outlives_region[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:36 ~ projection_no_regions_closure[317d]::outlives_region[0]::{{closure}}[0]) with closure substs [ '_#1r, '_#2r, T, @@ -139,7 +139,7 @@ LL | | with_signature(x, |mut y| Box::new(y.next())) LL | | } | |_^ | - = note: defining type: DefId(0/0:9 ~ projection_no_regions_closure[317d]::outlives_region[0]) with substs [ + = note: defining type: DefId(0:32 ~ projection_no_regions_closure[317d]::outlives_region[0]) with substs [ '_#1r, '_#2r, T, diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr index 9d716006500b7..10b2bd1af4702 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr @@ -4,7 +4,7 @@ note: External requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: defining type: DefId(0/1:19 ~ projection_one_region_closure[317d]::no_relationships_late[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:28 ~ projection_one_region_closure[317d]::no_relationships_late[0]::{{closure}}[0]) with closure substs [ '_#1r, T, i32, @@ -27,7 +27,7 @@ LL | | LL | | } | |_^ | - = note: defining type: DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]) with substs [ + = note: defining type: DefId(0:24 ~ projection_one_region_closure[317d]::no_relationships_late[0]) with substs [ '_#1r, T, ] @@ -38,7 +38,7 @@ error[E0309]: the parameter type `T` may not live long enough LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))`... + = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0:24 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(25), 'a))`... error: lifetime may not live long enough --> $DIR/projection-one-region-closure.rs:45:39 @@ -57,7 +57,7 @@ note: External requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: defining type: DefId(0/1:23 ~ projection_one_region_closure[317d]::no_relationships_early[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:33 ~ projection_one_region_closure[317d]::no_relationships_early[0]::{{closure}}[0]) with closure substs [ '_#1r, '_#2r, T, @@ -80,7 +80,7 @@ LL | | LL | | } | |_^ | - = note: defining type: DefId(0/0:9 ~ projection_one_region_closure[317d]::no_relationships_early[0]) with substs [ + = note: defining type: DefId(0:29 ~ projection_one_region_closure[317d]::no_relationships_early[0]) with substs [ '_#1r, '_#2r, T, @@ -111,7 +111,7 @@ note: External requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: defining type: DefId(0/1:27 ~ projection_one_region_closure[317d]::projection_outlives[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:38 ~ projection_one_region_closure[317d]::projection_outlives[0]::{{closure}}[0]) with closure substs [ '_#1r, '_#2r, T, @@ -133,7 +133,7 @@ LL | | with_signature(cell, t, |cell, t| require(cell, t)); LL | | } | |_^ | - = note: defining type: DefId(0/0:10 ~ projection_one_region_closure[317d]::projection_outlives[0]) with substs [ + = note: defining type: DefId(0:34 ~ projection_one_region_closure[317d]::projection_outlives[0]) with substs [ '_#1r, '_#2r, T, @@ -145,7 +145,7 @@ note: External requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: defining type: DefId(0/1:31 ~ projection_one_region_closure[317d]::elements_outlive[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:43 ~ projection_one_region_closure[317d]::elements_outlive[0]::{{closure}}[0]) with closure substs [ '_#1r, '_#2r, T, @@ -168,7 +168,7 @@ LL | | with_signature(cell, t, |cell, t| require(cell, t)); LL | | } | |_^ | - = note: defining type: DefId(0/0:11 ~ projection_one_region_closure[317d]::elements_outlive[0]) with substs [ + = note: defining type: DefId(0:39 ~ projection_one_region_closure[317d]::elements_outlive[0]) with substs [ '_#1r, '_#2r, T, diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr index 0fa4060137a3f..b4b74bfc1284f 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr @@ -4,7 +4,7 @@ note: External requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: defining type: DefId(0/1:19 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_late[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:28 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_late[0]::{{closure}}[0]) with closure substs [ '_#1r, T, i32, @@ -26,7 +26,7 @@ LL | | LL | | } | |_^ | - = note: defining type: DefId(0/0:8 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_late[0]) with substs [ + = note: defining type: DefId(0:24 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_late[0]) with substs [ '_#1r, T, ] @@ -48,7 +48,7 @@ note: External requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: defining type: DefId(0/1:23 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_early[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:33 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_early[0]::{{closure}}[0]) with closure substs [ '_#1r, '_#2r, T, @@ -70,7 +70,7 @@ LL | | LL | | } | |_^ | - = note: defining type: DefId(0/0:9 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_early[0]) with substs [ + = note: defining type: DefId(0:29 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_early[0]) with substs [ '_#1r, '_#2r, T, @@ -93,7 +93,7 @@ note: External requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: defining type: DefId(0/1:27 ~ projection_one_region_trait_bound_closure[317d]::projection_outlives[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:38 ~ projection_one_region_trait_bound_closure[317d]::projection_outlives[0]::{{closure}}[0]) with closure substs [ '_#1r, '_#2r, T, @@ -115,7 +115,7 @@ LL | | with_signature(cell, t, |cell, t| require(cell, t)); LL | | } | |_^ | - = note: defining type: DefId(0/0:10 ~ projection_one_region_trait_bound_closure[317d]::projection_outlives[0]) with substs [ + = note: defining type: DefId(0:34 ~ projection_one_region_trait_bound_closure[317d]::projection_outlives[0]) with substs [ '_#1r, '_#2r, T, @@ -127,7 +127,7 @@ note: External requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: defining type: DefId(0/1:31 ~ projection_one_region_trait_bound_closure[317d]::elements_outlive[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:43 ~ projection_one_region_trait_bound_closure[317d]::elements_outlive[0]::{{closure}}[0]) with closure substs [ '_#1r, '_#2r, T, @@ -149,7 +149,7 @@ LL | | with_signature(cell, t, |cell, t| require(cell, t)); LL | | } | |_^ | - = note: defining type: DefId(0/0:11 ~ projection_one_region_trait_bound_closure[317d]::elements_outlive[0]) with substs [ + = note: defining type: DefId(0:39 ~ projection_one_region_trait_bound_closure[317d]::elements_outlive[0]) with substs [ '_#1r, '_#2r, T, @@ -161,7 +161,7 @@ note: External requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: defining type: DefId(0/1:34 ~ projection_one_region_trait_bound_closure[317d]::one_region[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:47 ~ projection_one_region_trait_bound_closure[317d]::one_region[0]::{{closure}}[0]) with closure substs [ '_#1r, T, i32, @@ -182,7 +182,7 @@ LL | | with_signature(cell, t, |cell, t| require(cell, t)); LL | | } | |_^ | - = note: defining type: DefId(0/0:12 ~ projection_one_region_trait_bound_closure[317d]::one_region[0]) with substs [ + = note: defining type: DefId(0:44 ~ projection_one_region_trait_bound_closure[317d]::one_region[0]) with substs [ '_#1r, T, ] diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr index f616a7feae3f0..a757a43499f4b 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr @@ -4,7 +4,7 @@ note: No external requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: defining type: DefId(0/1:19 ~ projection_one_region_trait_bound_static_closure[317d]::no_relationships_late[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:28 ~ projection_one_region_trait_bound_static_closure[317d]::no_relationships_late[0]::{{closure}}[0]) with closure substs [ '_#1r, T, i32, @@ -23,7 +23,7 @@ LL | | with_signature(cell, t, |cell, t| require(cell, t)); LL | | } | |_^ | - = note: defining type: DefId(0/0:8 ~ projection_one_region_trait_bound_static_closure[317d]::no_relationships_late[0]) with substs [ + = note: defining type: DefId(0:24 ~ projection_one_region_trait_bound_static_closure[317d]::no_relationships_late[0]) with substs [ '_#1r, T, ] @@ -34,7 +34,7 @@ note: No external requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: defining type: DefId(0/1:23 ~ projection_one_region_trait_bound_static_closure[317d]::no_relationships_early[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:33 ~ projection_one_region_trait_bound_static_closure[317d]::no_relationships_early[0]::{{closure}}[0]) with closure substs [ '_#1r, '_#2r, T, @@ -54,7 +54,7 @@ LL | | with_signature(cell, t, |cell, t| require(cell, t)); LL | | } | |_^ | - = note: defining type: DefId(0/0:9 ~ projection_one_region_trait_bound_static_closure[317d]::no_relationships_early[0]) with substs [ + = note: defining type: DefId(0:29 ~ projection_one_region_trait_bound_static_closure[317d]::no_relationships_early[0]) with substs [ '_#1r, '_#2r, T, @@ -66,7 +66,7 @@ note: No external requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: defining type: DefId(0/1:27 ~ projection_one_region_trait_bound_static_closure[317d]::projection_outlives[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:38 ~ projection_one_region_trait_bound_static_closure[317d]::projection_outlives[0]::{{closure}}[0]) with closure substs [ '_#1r, '_#2r, T, @@ -86,7 +86,7 @@ LL | | with_signature(cell, t, |cell, t| require(cell, t)); LL | | } | |_^ | - = note: defining type: DefId(0/0:10 ~ projection_one_region_trait_bound_static_closure[317d]::projection_outlives[0]) with substs [ + = note: defining type: DefId(0:34 ~ projection_one_region_trait_bound_static_closure[317d]::projection_outlives[0]) with substs [ '_#1r, '_#2r, T, @@ -98,7 +98,7 @@ note: No external requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: defining type: DefId(0/1:31 ~ projection_one_region_trait_bound_static_closure[317d]::elements_outlive[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:43 ~ projection_one_region_trait_bound_static_closure[317d]::elements_outlive[0]::{{closure}}[0]) with closure substs [ '_#1r, '_#2r, T, @@ -118,7 +118,7 @@ LL | | with_signature(cell, t, |cell, t| require(cell, t)); LL | | } | |_^ | - = note: defining type: DefId(0/0:11 ~ projection_one_region_trait_bound_static_closure[317d]::elements_outlive[0]) with substs [ + = note: defining type: DefId(0:39 ~ projection_one_region_trait_bound_static_closure[317d]::elements_outlive[0]) with substs [ '_#1r, '_#2r, T, @@ -130,7 +130,7 @@ note: No external requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: defining type: DefId(0/1:34 ~ projection_one_region_trait_bound_static_closure[317d]::one_region[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:47 ~ projection_one_region_trait_bound_static_closure[317d]::one_region[0]::{{closure}}[0]) with closure substs [ '_#1r, T, i32, @@ -149,7 +149,7 @@ LL | | with_signature(cell, t, |cell, t| require(cell, t)); LL | | } | |_^ | - = note: defining type: DefId(0/0:12 ~ projection_one_region_trait_bound_static_closure[317d]::one_region[0]) with substs [ + = note: defining type: DefId(0:44 ~ projection_one_region_trait_bound_static_closure[317d]::one_region[0]) with substs [ '_#1r, T, ] diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr index b761b031444da..a48766cd7340b 100644 --- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr @@ -4,7 +4,7 @@ note: External requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: defining type: DefId(0/1:22 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:31 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]::{{closure}}[0]) with closure substs [ '_#1r, '_#2r, T, @@ -27,7 +27,7 @@ LL | | LL | | } | |_^ | - = note: defining type: DefId(0/0:8 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]) with substs [ + = note: defining type: DefId(0:26 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]) with substs [ '_#1r, '_#2r, T, @@ -39,7 +39,7 @@ error[E0309]: the associated type `>::AssocType` may LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: consider adding an explicit lifetime bound `>::AssocType: ReFree(DefId(0/0:8 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:18), 'a))`... + = help: consider adding an explicit lifetime bound `>::AssocType: ReFree(DefId(0:26 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(27), 'a))`... note: External requirements --> $DIR/projection-two-region-trait-bound-closure.rs:48:29 @@ -47,7 +47,7 @@ note: External requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: defining type: DefId(0/1:27 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_early[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:37 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_early[0]::{{closure}}[0]) with closure substs [ '_#1r, '_#2r, '_#3r, @@ -70,7 +70,7 @@ LL | | LL | | } | |_^ | - = note: defining type: DefId(0/0:9 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_early[0]) with substs [ + = note: defining type: DefId(0:32 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_early[0]) with substs [ '_#1r, '_#2r, '_#3r, @@ -91,7 +91,7 @@ note: External requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: defining type: DefId(0/1:32 ~ projection_two_region_trait_bound_closure[317d]::projection_outlives[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:43 ~ projection_two_region_trait_bound_closure[317d]::projection_outlives[0]::{{closure}}[0]) with closure substs [ '_#1r, '_#2r, '_#3r, @@ -114,7 +114,7 @@ LL | | with_signature(cell, t, |cell, t| require(cell, t)); LL | | } | |_^ | - = note: defining type: DefId(0/0:10 ~ projection_two_region_trait_bound_closure[317d]::projection_outlives[0]) with substs [ + = note: defining type: DefId(0:38 ~ projection_two_region_trait_bound_closure[317d]::projection_outlives[0]) with substs [ '_#1r, '_#2r, '_#3r, @@ -127,7 +127,7 @@ note: External requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: defining type: DefId(0/1:37 ~ projection_two_region_trait_bound_closure[317d]::elements_outlive1[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:49 ~ projection_two_region_trait_bound_closure[317d]::elements_outlive1[0]::{{closure}}[0]) with closure substs [ '_#1r, '_#2r, '_#3r, @@ -150,7 +150,7 @@ LL | | with_signature(cell, t, |cell, t| require(cell, t)); LL | | } | |_^ | - = note: defining type: DefId(0/0:11 ~ projection_two_region_trait_bound_closure[317d]::elements_outlive1[0]) with substs [ + = note: defining type: DefId(0:44 ~ projection_two_region_trait_bound_closure[317d]::elements_outlive1[0]) with substs [ '_#1r, '_#2r, '_#3r, @@ -163,7 +163,7 @@ note: External requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: defining type: DefId(0/1:42 ~ projection_two_region_trait_bound_closure[317d]::elements_outlive2[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:55 ~ projection_two_region_trait_bound_closure[317d]::elements_outlive2[0]::{{closure}}[0]) with closure substs [ '_#1r, '_#2r, '_#3r, @@ -186,7 +186,7 @@ LL | | with_signature(cell, t, |cell, t| require(cell, t)); LL | | } | |_^ | - = note: defining type: DefId(0/0:12 ~ projection_two_region_trait_bound_closure[317d]::elements_outlive2[0]) with substs [ + = note: defining type: DefId(0:50 ~ projection_two_region_trait_bound_closure[317d]::elements_outlive2[0]) with substs [ '_#1r, '_#2r, '_#3r, @@ -199,7 +199,7 @@ note: External requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: defining type: DefId(0/1:46 ~ projection_two_region_trait_bound_closure[317d]::two_regions[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:60 ~ projection_two_region_trait_bound_closure[317d]::two_regions[0]::{{closure}}[0]) with closure substs [ '_#1r, T, i32, @@ -221,7 +221,7 @@ LL | | LL | | } | |_^ | - = note: defining type: DefId(0/0:13 ~ projection_two_region_trait_bound_closure[317d]::two_regions[0]) with substs [ + = note: defining type: DefId(0:56 ~ projection_two_region_trait_bound_closure[317d]::two_regions[0]) with substs [ '_#1r, T, ] @@ -243,7 +243,7 @@ note: External requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: defining type: DefId(0/1:50 ~ projection_two_region_trait_bound_closure[317d]::two_regions_outlive[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:65 ~ projection_two_region_trait_bound_closure[317d]::two_regions_outlive[0]::{{closure}}[0]) with closure substs [ '_#1r, '_#2r, T, @@ -265,7 +265,7 @@ LL | | with_signature(cell, t, |cell, t| require(cell, t)); LL | | } | |_^ | - = note: defining type: DefId(0/0:14 ~ projection_two_region_trait_bound_closure[317d]::two_regions_outlive[0]) with substs [ + = note: defining type: DefId(0:61 ~ projection_two_region_trait_bound_closure[317d]::two_regions_outlive[0]) with substs [ '_#1r, '_#2r, T, @@ -277,7 +277,7 @@ note: External requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: defining type: DefId(0/1:53 ~ projection_two_region_trait_bound_closure[317d]::one_region[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:69 ~ projection_two_region_trait_bound_closure[317d]::one_region[0]::{{closure}}[0]) with closure substs [ '_#1r, T, i32, @@ -298,7 +298,7 @@ LL | | with_signature(cell, t, |cell, t| require(cell, t)); LL | | } | |_^ | - = note: defining type: DefId(0/0:15 ~ projection_two_region_trait_bound_closure[317d]::one_region[0]) with substs [ + = note: defining type: DefId(0:66 ~ projection_two_region_trait_bound_closure[317d]::one_region[0]) with substs [ '_#1r, T, ] diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr index 6f3071becfd0e..2ed94df1f3478 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr @@ -4,10 +4,10 @@ note: External requirements LL | twice(cell, value, |a, b| invoke(a, b)); | ^^^^^^^^^^^^^^^^^^^ | - = note: defining type: DefId(0/1:14 ~ ty_param_closure_approximate_lower_bound[317d]::generic[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:20 ~ ty_param_closure_approximate_lower_bound[317d]::generic[0]::{{closure}}[0]) with closure substs [ T, i16, - for<'r, 's> extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) T)), + for<'r, 's> extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) T)), ] = note: number of external vids: 2 = note: where T: '_#1r @@ -21,7 +21,7 @@ LL | | twice(cell, value, |a, b| invoke(a, b)); LL | | } | |_^ | - = note: defining type: DefId(0/0:5 ~ ty_param_closure_approximate_lower_bound[317d]::generic[0]) with substs [ + = note: defining type: DefId(0:18 ~ ty_param_closure_approximate_lower_bound[317d]::generic[0]) with substs [ T, ] @@ -31,10 +31,10 @@ note: External requirements LL | twice(cell, value, |a, b| invoke(a, b)); | ^^^^^^^^^^^^^^^^^^^ | - = note: defining type: DefId(0/1:17 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:24 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]::{{closure}}[0]) with closure substs [ T, i16, - for<'r, 's> extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) T)), + for<'r, 's> extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0), 's)) T)), ] = note: late-bound region is '_#2r = note: number of external vids: 3 @@ -49,7 +49,7 @@ LL | | LL | | } | |_^ | - = note: defining type: DefId(0/0:6 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]) with substs [ + = note: defining type: DefId(0:21 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]) with substs [ T, ] @@ -59,7 +59,7 @@ error[E0309]: the parameter type `T` may not live long enough LL | twice(cell, value, |a, b| invoke(a, b)); | ^^^^^^^^^^^^^^^^^^^ | - = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:6 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]), BrNamed(crate0:DefIndex(1:15), 'a))`... + = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0:21 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]), BrNamed(crate0:DefIndex(22), 'a))`... error: aborting due to previous error diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr index cdb715762031f..d689949969d7e 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr @@ -4,7 +4,7 @@ note: External requirements LL | with_signature(x, |y| y) | ^^^^^ | - = note: defining type: DefId(0/1:14 ~ ty_param_closure_outlives_from_return_type[317d]::no_region[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:20 ~ ty_param_closure_outlives_from_return_type[317d]::no_region[0]::{{closure}}[0]) with closure substs [ '_#1r, T, i32, @@ -25,7 +25,7 @@ LL | | LL | | } | |_^ | - = note: defining type: DefId(0/0:5 ~ ty_param_closure_outlives_from_return_type[317d]::no_region[0]) with substs [ + = note: defining type: DefId(0:17 ~ ty_param_closure_outlives_from_return_type[317d]::no_region[0]) with substs [ '_#1r, T, ] diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr index 68798a335f9df..11444c9f72bef 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr @@ -11,7 +11,7 @@ LL | | require(&x, &y) LL | | }) | |_____^ | - = note: defining type: DefId(0/1:16 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:23 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]::{{closure}}[0]) with closure substs [ T, i32, extern "rust-call" fn((std::cell::Cell<&'_#1r ()>, T)), @@ -32,7 +32,7 @@ LL | | }) LL | | } | |_^ | - = note: defining type: DefId(0/0:6 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]) with substs [ + = note: defining type: DefId(0:20 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]) with substs [ T, ] @@ -49,7 +49,7 @@ LL | | require(&x, &y) LL | | }) | |_____^ | - = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:6 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]), BrNamed(crate0:DefIndex(1:14), 'a))`... + = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0:20 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]), BrNamed(crate0:DefIndex(21), 'a))`... note: External requirements --> $DIR/ty-param-closure-outlives-from-where-clause.rs:43:26 @@ -64,7 +64,7 @@ LL | | require(&x, &y) LL | | }) | |_____^ | - = note: defining type: DefId(0/1:19 ~ ty_param_closure_outlives_from_where_clause[317d]::correct_region[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:27 ~ ty_param_closure_outlives_from_where_clause[317d]::correct_region[0]::{{closure}}[0]) with closure substs [ '_#1r, T, i32, @@ -85,7 +85,7 @@ LL | | }) LL | | } | |_^ | - = note: defining type: DefId(0/0:7 ~ ty_param_closure_outlives_from_where_clause[317d]::correct_region[0]) with substs [ + = note: defining type: DefId(0:24 ~ ty_param_closure_outlives_from_where_clause[317d]::correct_region[0]) with substs [ '_#1r, T, ] @@ -101,7 +101,7 @@ LL | | require(&x, &y) LL | | }) | |_____^ | - = note: defining type: DefId(0/1:23 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:32 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]::{{closure}}[0]) with closure substs [ '_#1r, T, i32, @@ -123,7 +123,7 @@ LL | | }) LL | | } | |_^ | - = note: defining type: DefId(0/0:8 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]) with substs [ + = note: defining type: DefId(0:28 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]) with substs [ '_#1r, T, ] @@ -139,7 +139,7 @@ LL | | require(&x, &y) LL | | }) | |_____^ | - = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]), BrNamed(crate0:DefIndex(1:20), 'a))`... + = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0:28 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]), BrNamed(crate0:DefIndex(29), 'a))`... note: External requirements --> $DIR/ty-param-closure-outlives-from-where-clause.rs:77:26 @@ -151,7 +151,7 @@ LL | | require(&x, &y) LL | | }) | |_____^ | - = note: defining type: DefId(0/1:27 ~ ty_param_closure_outlives_from_where_clause[317d]::outlives_region[0]::{{closure}}[0]) with closure substs [ + = note: defining type: DefId(0:37 ~ ty_param_closure_outlives_from_where_clause[317d]::outlives_region[0]::{{closure}}[0]) with closure substs [ '_#1r, '_#2r, T, @@ -173,7 +173,7 @@ LL | | }) LL | | } | |_^ | - = note: defining type: DefId(0/0:9 ~ ty_param_closure_outlives_from_where_clause[317d]::outlives_region[0]) with substs [ + = note: defining type: DefId(0:33 ~ ty_param_closure_outlives_from_where_clause[317d]::outlives_region[0]) with substs [ '_#1r, '_#2r, T, From d0ba8fe33f0eb426d01447b5159ce7e78afe7a74 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 9 May 2019 01:06:03 +0300 Subject: [PATCH 134/212] Skip codegen for one UI test with long file path --- .../region-lbr1-does-outlive-lbr2-because-implied-bound.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/test/ui/nll/closure-requirements/region-lbr1-does-outlive-lbr2-because-implied-bound.rs b/src/test/ui/nll/closure-requirements/region-lbr1-does-outlive-lbr2-because-implied-bound.rs index 66290f2ff230a..5a008ad26b444 100644 --- a/src/test/ui/nll/closure-requirements/region-lbr1-does-outlive-lbr2-because-implied-bound.rs +++ b/src/test/ui/nll/closure-requirements/region-lbr1-does-outlive-lbr2-because-implied-bound.rs @@ -3,8 +3,7 @@ // compile-flags:-Zborrowck=mir -Zverbose // compile-pass - -#![allow(warnings)] +// skip-codegen fn foo<'a, 'b>(x: &'a &'b u32) -> &'a u32 { &**x From b9c430129d5971df4410b6c829b100ce8191328e Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Wed, 8 May 2019 22:38:58 -0400 Subject: [PATCH 135/212] Inline some Cursor calls for slices (Partially) brings back https://github.com/rust-lang/rust/pull/33921 --- src/libstd/io/cursor.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs index 64f8659b8f8fe..f627fb0f562f0 100644 --- a/src/libstd/io/cursor.rs +++ b/src/libstd/io/cursor.rs @@ -265,6 +265,7 @@ impl BufRead for Cursor where T: AsRef<[u8]> { } // Non-resizing write implementation +#[inline] fn slice_write(pos_mut: &mut u64, slice: &mut [u8], buf: &[u8]) -> io::Result { let pos = cmp::min(*pos_mut, slice.len() as u64); let amt = (&mut slice[(pos as usize)..]).write(buf)?; @@ -272,6 +273,7 @@ fn slice_write(pos_mut: &mut u64, slice: &mut [u8], buf: &[u8]) -> io::Result { slice_write_vectored(&mut self.pos, self.inner, bufs) } + #[inline] fn flush(&mut self) -> io::Result<()> { Ok(()) } } @@ -354,6 +357,7 @@ impl Write for Cursor<&mut Vec> { vec_write_vectored(&mut self.pos, self.inner, bufs) } + #[inline] fn flush(&mut self) -> io::Result<()> { Ok(()) } } @@ -367,6 +371,7 @@ impl Write for Cursor> { vec_write_vectored(&mut self.pos, &mut self.inner, bufs) } + #[inline] fn flush(&mut self) -> io::Result<()> { Ok(()) } } @@ -382,6 +387,7 @@ impl Write for Cursor> { slice_write_vectored(&mut self.pos, &mut self.inner, bufs) } + #[inline] fn flush(&mut self) -> io::Result<()> { Ok(()) } } From 028e78d93aac664325d7ed49703032bc3ed3c185 Mon Sep 17 00:00:00 2001 From: Yuki OKUSHI Date: Thu, 9 May 2019 11:58:39 +0900 Subject: [PATCH 136/212] Stabilize and re-export core::array --- src/libcore/array.rs | 10 ++++++---- src/libstd/lib.rs | 3 ++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/libcore/array.rs b/src/libcore/array.rs index fb9c99f667df2..e4cadcbf75b90 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -4,10 +4,7 @@ //! //! *[See also the array primitive type](../../std/primitive.array.html).* -#![unstable(feature = "fixed_size_array", - reason = "traits and impls are better expressed through generic \ - integer constants", - issue = "27778")] +#![stable(feature = "core_array", since = "1.36.0")] use crate::borrow::{Borrow, BorrowMut}; use crate::cmp::Ordering; @@ -30,13 +27,17 @@ use crate::slice::{Iter, IterMut}; /// Note that the traits AsRef and AsMut provide similar methods for types that /// may not be fixed-size arrays. Implementors should prefer those traits /// instead. +#[unstable(feature = "fixed_size_array", issue = "27778")] pub unsafe trait FixedSizeArray { /// Converts the array to immutable slice + #[unstable(feature = "fixed_size_array", issue = "27778")] fn as_slice(&self) -> &[T]; /// Converts the array to mutable slice + #[unstable(feature = "fixed_size_array", issue = "27778")] fn as_mut_slice(&mut self) -> &mut [T]; } +#[unstable(feature = "fixed_size_array", issue = "27778")] unsafe impl> FixedSizeArray for A { #[inline] fn as_slice(&self) -> &[T] { @@ -53,6 +54,7 @@ unsafe impl> FixedSizeArray for A { #[derive(Debug, Copy, Clone)] pub struct TryFromSliceError(()); +#[stable(feature = "core_array", since = "1.36.0")] impl fmt::Display for TryFromSliceError { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 215f1bbc971af..3976f2344e241 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -259,7 +259,6 @@ #![feature(exact_size_is_empty)] #![feature(exhaustive_patterns)] #![feature(external_doc)] -#![feature(fixed_size_array)] #![feature(fn_traits)] #![feature(fnbox)] #![feature(generator_trait)] @@ -435,6 +434,8 @@ pub use core::char; pub use core::u128; #[stable(feature = "core_hint", since = "1.27.0")] pub use core::hint; +#[stable(feature = "core_array", since = "1.36.0")] +pub use core::array; pub mod f32; pub mod f64; From d4f071af23018bab33e7f33617573704323e6daa Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 9 May 2019 11:17:03 +0200 Subject: [PATCH 137/212] ci: update dist-various-2 to ubuntu 18.04 --- src/ci/docker/dist-various-2/Dockerfile | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/ci/docker/dist-various-2/Dockerfile b/src/ci/docker/dist-various-2/Dockerfile index c0f3326524d5c..1d6a0269c5b5b 100644 --- a/src/ci/docker/dist-various-2/Dockerfile +++ b/src/ci/docker/dist-various-2/Dockerfile @@ -1,9 +1,12 @@ -FROM ubuntu:17.10 +FROM ubuntu:18.04 COPY scripts/cross-apt-packages.sh /scripts/ RUN sh /scripts/cross-apt-packages.sh -RUN apt-get build-dep -y clang llvm && apt-get install -y --no-install-recommends \ +# Enable source repositories, which are disabled by default on Ubuntu >= 18.04 +RUN sed -i 's/^# deb-src/deb-src/' /etc/apt/sources.list + +RUN apt-get update && apt-get build-dep -y clang llvm && apt-get install -y --no-install-recommends \ build-essential \ gcc-multilib \ libedit-dev \ @@ -15,7 +18,10 @@ RUN apt-get build-dep -y clang llvm && apt-get install -y --no-install-recommend nodejs \ python2.7-dev \ software-properties-common \ - unzip + unzip \ + # Needed for apt-key to work: + dirmngr \ + gpg-agent RUN apt-key adv --batch --yes --keyserver keyserver.ubuntu.com --recv-keys 74DA7924C5513486 RUN add-apt-repository -y 'deb http://apt.dilos.org/dilos dilos2-testing main' From 8f9e90b9cd4d377c8a880dc9b66932bcaf1da72d Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 9 May 2019 11:32:41 +0200 Subject: [PATCH 138/212] ci: use our own mirror for fuchsia's zircon repository The canonical repository on fuchsia.googlesource.com is not accessible anymore, neither for anonymous access nor logged in access. This commit switches our CI to fetch the repository from our own mirror. --- src/ci/docker/dist-various-2/build-fuchsia-toolchain.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/docker/dist-various-2/build-fuchsia-toolchain.sh b/src/ci/docker/dist-various-2/build-fuchsia-toolchain.sh index 3b91918288a2b..73acdf5be6356 100755 --- a/src/ci/docker/dist-various-2/build-fuchsia-toolchain.sh +++ b/src/ci/docker/dist-various-2/build-fuchsia-toolchain.sh @@ -10,7 +10,7 @@ pushd zircon > /dev/null # Download sources git init -git remote add origin https://fuchsia.googlesource.com/zircon +git remote add origin https://github.com/rust-lang-nursery/mirror-google-fuchsia-zircon git fetch --depth=1 origin $ZIRCON git reset --hard FETCH_HEAD From c98a27c622394148bb94ecf5fc1d31c7c645f45d Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 9 May 2019 11:51:01 +0200 Subject: [PATCH 139/212] ci: bump ubuntu 18.10 images to 19.04 --- src/ci/docker/x86_64-gnu-debug/Dockerfile | 2 +- src/ci/docker/x86_64-gnu/Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ci/docker/x86_64-gnu-debug/Dockerfile b/src/ci/docker/x86_64-gnu-debug/Dockerfile index 1c7eff68adc15..7a503ea4e98c5 100644 --- a/src/ci/docker/x86_64-gnu-debug/Dockerfile +++ b/src/ci/docker/x86_64-gnu-debug/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:18.10 +FROM ubuntu:19.04 RUN apt-get update && apt-get install -y --no-install-recommends \ g++ \ diff --git a/src/ci/docker/x86_64-gnu/Dockerfile b/src/ci/docker/x86_64-gnu/Dockerfile index dd94f2652b4c9..c3519a0077872 100644 --- a/src/ci/docker/x86_64-gnu/Dockerfile +++ b/src/ci/docker/x86_64-gnu/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:18.10 +FROM ubuntu:19.04 RUN apt-get update && apt-get install -y --no-install-recommends \ g++ \ From f3993d0619eeb5fee94905725ca16de48b16e0e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 9 May 2019 13:56:14 +0200 Subject: [PATCH 140/212] Fix typo --- src/librustc/hir/map/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index c2b513a39a8b7..807b90b08073f 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -1057,7 +1057,7 @@ impl<'hir> Map<'hir> { in_which: &parts[..parts.len() - 1], }; - self.all_ids().filter(move |hir| nodes.matces_suffix(*hir)).map(move |hir| { + self.all_ids().filter(move |hir| nodes.matches_suffix(*hir)).map(move |hir| { self.hir_to_node_id(hir) }) } @@ -1198,7 +1198,7 @@ impl<'a> NodesMatchingSuffix<'a> { name == &**self.item_name && self.suffix_matches(parent_of_n) } - fn matces_suffix(&self, hir: HirId) -> bool { + fn matches_suffix(&self, hir: HirId) -> bool { let name = match self.map.find_entry(hir).map(|entry| entry.node) { Some(Node::Item(n)) => n.name(), Some(Node::ForeignItem(n)) => n.name(), From e73ba21ce1c788c43ce2efd70e00176c1caacf02 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Thu, 9 May 2019 14:06:36 +0200 Subject: [PATCH 141/212] save-analysis: Add UI testsuite --- src/test/ui/save-analysis/issue-59134-0.rs | 12 ++++++++++++ src/test/ui/save-analysis/issue-59134-0.stderr | 9 +++++++++ src/test/ui/save-analysis/issue-59134-1.rs | 12 ++++++++++++ src/test/ui/save-analysis/issue-59134-1.stderr | 9 +++++++++ 4 files changed, 42 insertions(+) create mode 100644 src/test/ui/save-analysis/issue-59134-0.rs create mode 100644 src/test/ui/save-analysis/issue-59134-0.stderr create mode 100644 src/test/ui/save-analysis/issue-59134-1.rs create mode 100644 src/test/ui/save-analysis/issue-59134-1.stderr diff --git a/src/test/ui/save-analysis/issue-59134-0.rs b/src/test/ui/save-analysis/issue-59134-0.rs new file mode 100644 index 0000000000000..93c7fbbca8461 --- /dev/null +++ b/src/test/ui/save-analysis/issue-59134-0.rs @@ -0,0 +1,12 @@ +// compile-flags: -Zsave-analysis + +// Check that this doesn't ICE when processing associated const (field expr). + +pub fn f() { + trait Trait {} + impl Trait { + const FLAG: u32 = bogus.field; //~ ERROR cannot find value `bogus` + } +} + +fn main() {} \ No newline at end of file diff --git a/src/test/ui/save-analysis/issue-59134-0.stderr b/src/test/ui/save-analysis/issue-59134-0.stderr new file mode 100644 index 0000000000000..4e9b2e6fdeb4d --- /dev/null +++ b/src/test/ui/save-analysis/issue-59134-0.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `bogus` in this scope + --> $DIR/issue-59134-0.rs:8:27 + | +LL | const FLAG: u32 = bogus.field; + | ^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/save-analysis/issue-59134-1.rs b/src/test/ui/save-analysis/issue-59134-1.rs new file mode 100644 index 0000000000000..085f22cacbc58 --- /dev/null +++ b/src/test/ui/save-analysis/issue-59134-1.rs @@ -0,0 +1,12 @@ +// compile-flags: -Zsave-analysis + +// Check that this doesn't ICE when processing associated const (type). + +fn func() { + trait Trait { + type MyType; + const CONST: Self::MyType = bogus.field; //~ ERROR cannot find value `bogus` + } +} + +fn main() {} \ No newline at end of file diff --git a/src/test/ui/save-analysis/issue-59134-1.stderr b/src/test/ui/save-analysis/issue-59134-1.stderr new file mode 100644 index 0000000000000..bdc335eaac041 --- /dev/null +++ b/src/test/ui/save-analysis/issue-59134-1.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `bogus` in this scope + --> $DIR/issue-59134-1.rs:8:37 + | +LL | const CONST: Self::MyType = bogus.field; + | ^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. From 0af18eed107f8b5d113e7d8e33f9182e37f0996b Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Thu, 9 May 2019 16:15:53 +0200 Subject: [PATCH 142/212] Appease tidy --- src/test/ui/save-analysis/issue-59134-0.rs | 2 +- src/test/ui/save-analysis/issue-59134-1.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/save-analysis/issue-59134-0.rs b/src/test/ui/save-analysis/issue-59134-0.rs index 93c7fbbca8461..3158328b3ff15 100644 --- a/src/test/ui/save-analysis/issue-59134-0.rs +++ b/src/test/ui/save-analysis/issue-59134-0.rs @@ -9,4 +9,4 @@ pub fn f() { } } -fn main() {} \ No newline at end of file +fn main() {} diff --git a/src/test/ui/save-analysis/issue-59134-1.rs b/src/test/ui/save-analysis/issue-59134-1.rs index 085f22cacbc58..3cb629777a497 100644 --- a/src/test/ui/save-analysis/issue-59134-1.rs +++ b/src/test/ui/save-analysis/issue-59134-1.rs @@ -9,4 +9,4 @@ fn func() { } } -fn main() {} \ No newline at end of file +fn main() {} From b2f71fb540faa4218de506c4d82bbcf237ea78d6 Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Thu, 9 May 2019 12:03:13 -0400 Subject: [PATCH 143/212] remove unneeded `extern crate`s from build tools --- Cargo.lock | 76 +++++++++++++--------------- src/bootstrap/Cargo.toml | 5 +- src/bootstrap/builder.rs | 4 ++ src/bootstrap/cache.rs | 2 + src/bootstrap/clean.rs | 2 + src/bootstrap/compile.rs | 3 +- src/bootstrap/config.rs | 2 + src/bootstrap/dist.rs | 2 +- src/bootstrap/doc.rs | 2 +- src/bootstrap/install.rs | 2 + src/bootstrap/lib.rs | 15 ++---- src/bootstrap/metadata.rs | 1 + src/bootstrap/native.rs | 2 +- src/bootstrap/sanity.rs | 2 +- src/bootstrap/test.rs | 2 +- src/bootstrap/tool.rs | 2 + src/bootstrap/toolstate.rs | 2 + src/bootstrap/util.rs | 2 + src/tools/build-manifest/Cargo.toml | 1 - src/tools/compiletest/Cargo.toml | 3 +- src/tools/compiletest/src/errors.rs | 2 + src/tools/compiletest/src/header.rs | 2 + src/tools/compiletest/src/json.rs | 1 + src/tools/compiletest/src/main.rs | 9 +--- src/tools/compiletest/src/runtest.rs | 3 ++ src/tools/compiletest/src/util.rs | 2 + src/tools/tidy/Cargo.toml | 3 +- src/tools/tidy/src/deps.rs | 2 +- 28 files changed, 81 insertions(+), 75 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ff66b4a0372ee..a7c806ad481ff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,7 +29,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "html5ever 0.22.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -170,13 +170,12 @@ dependencies = [ "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -192,7 +191,6 @@ name = "build-manifest" version = "0.1.0" dependencies = [ "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -266,7 +264,7 @@ dependencies = [ "ignore 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "im-rc 12.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "jobserver 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "libgit2-sys 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -374,7 +372,7 @@ dependencies = [ "clippy_lints 0.0.212", "compiletest_rs 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0", "rustc_tools_util 0.1.1", @@ -394,7 +392,7 @@ dependencies = [ "cargo_metadata 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "if_chain 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -465,14 +463,13 @@ dependencies = [ "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustfix 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -592,7 +589,7 @@ dependencies = [ "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -606,7 +603,7 @@ dependencies = [ "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -751,7 +748,7 @@ name = "elasticlunr-rs" version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1032,7 +1029,7 @@ name = "handlebars" version = "0.32.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "pest_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1047,7 +1044,7 @@ name = "handlebars" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "pest 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1143,7 +1140,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "globset 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1169,7 +1166,7 @@ dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "tar 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1265,7 +1262,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lazy_static" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1354,7 +1351,7 @@ name = "log_settings" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1441,7 +1438,7 @@ dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "handlebars 0.32.4 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1469,7 +1466,7 @@ dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "handlebars 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1703,7 +1700,7 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1971,7 +1968,7 @@ dependencies = [ "bit-set 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2045,7 +2042,7 @@ dependencies = [ "derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-ap-syntax 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2141,7 +2138,7 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2243,7 +2240,7 @@ dependencies = [ "home 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "lsp-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "lsp-types 0.57.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2349,7 +2346,7 @@ dependencies = [ "fmt_macros 0.0.0", "graphviz 0.0.0", "jobserver 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "measureme 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2402,7 +2399,7 @@ dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "jobserver 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-ap-graphviz 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2532,7 +2529,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2543,7 +2540,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2702,7 +2699,7 @@ dependencies = [ "ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "graphviz 0.0.0", "jobserver 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3097,7 +3094,7 @@ dependencies = [ "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "ignore 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-ap-rustc_target 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3143,7 +3140,7 @@ name = "schannel" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3313,7 +3310,7 @@ name = "string_cache" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3404,7 +3401,7 @@ name = "syntax" version = "0.0.0" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", @@ -3549,7 +3546,7 @@ name = "thread_local" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3558,7 +3555,6 @@ version = "0.1.0" dependencies = [ "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3664,7 +3660,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3783,7 +3779,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3795,7 +3791,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4160,7 +4156,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum jsonrpc-core 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a5152c3fda235dfd68341b3edf4121bc4428642c93acbd6de88c26bf95fc5d7" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" -"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" +"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" "checksum libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)" = "c6785aa7dd976f5fbf3b71cfd9cd49d7f783c1ff565a858d71031c6c313aa5c6" "checksum libgit2-sys 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "48441cb35dc255da8ae72825689a95368bf510659ae1ad55dc4aa88cb1789bf1" diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 3151b56d8e84e..589ee9276a5a3 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -42,11 +42,10 @@ num_cpus = "1.0" getopts = "0.2.19" cc = "1.0.35" libc = "0.2" -serde = "1.0.8" -serde_derive = "1.0.8" +serde = { version = "1.0.8", features = ["derive"] } serde_json = "1.0.2" toml = "0.4" -lazy_static = "0.2" +lazy_static = "1.3.0" time = "0.1" petgraph = "0.4.13" diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index c84eb6476e087..51663e9316982 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -11,6 +11,8 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::time::{Duration, Instant}; +use build_helper::t; + use crate::cache::{Cache, Interned, INTERNER}; use crate::check; use crate::compile; @@ -1308,6 +1310,8 @@ mod __test { use crate::config::Config; use std::thread; + use pretty_assertions::assert_eq; + fn configure(host: &[&str], target: &[&str]) -> Config { let mut config = Config::default_opts(); // don't save toolstates diff --git a/src/bootstrap/cache.rs b/src/bootstrap/cache.rs index 239959682cb00..f137a7b8cc281 100644 --- a/src/bootstrap/cache.rs +++ b/src/bootstrap/cache.rs @@ -13,6 +13,8 @@ use std::path::{Path, PathBuf}; use std::sync::Mutex; use std::cmp::{PartialOrd, Ord, Ordering}; +use lazy_static::lazy_static; + use crate::builder::Step; pub struct Interned(usize, PhantomData<*const T>); diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs index b52e1a7b0e681..73be8bfed8e88 100644 --- a/src/bootstrap/clean.rs +++ b/src/bootstrap/clean.rs @@ -9,6 +9,8 @@ use std::fs; use std::io::{self, ErrorKind}; use std::path::Path; +use build_helper::t; + use crate::Build; pub fn clean(build: &Build, all: bool) { diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 66443d472d334..9c4e856f0b88b 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -15,8 +15,9 @@ use std::path::{Path, PathBuf}; use std::process::{Command, Stdio, exit}; use std::str; -use build_helper::{output, mtime, up_to_date}; +use build_helper::{output, mtime, t, up_to_date}; use filetime::FileTime; +use serde::Deserialize; use serde_json; use crate::dist; diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 0c31c41ceda86..b1d009a674066 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -10,8 +10,10 @@ use std::path::{Path, PathBuf}; use std::process; use std::cmp; +use build_helper::t; use num_cpus; use toml; +use serde::Deserialize; use crate::cache::{INTERNER, Interned}; use crate::flags::Flags; pub use crate::flags::Subcommand; diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 57c06061c34ae..b0616ff66918c 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -14,7 +14,7 @@ use std::io::Write; use std::path::{PathBuf, Path}; use std::process::{Command, Stdio}; -use build_helper::output; +use build_helper::{output, t}; use crate::{Compiler, Mode, LLVM_TOOLS}; use crate::channel; diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 330f66c1df0df..9c3a17bff6b7a 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -13,7 +13,7 @@ use std::io; use std::path::{PathBuf, Path}; use crate::Mode; -use build_helper::up_to_date; +use build_helper::{t, up_to_date}; use crate::util::symlink_dir; use crate::builder::{Builder, Compiler, RunConfig, ShouldRun, Step}; diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index 2d040d60e5fd7..deda30b6bbd9b 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -8,6 +8,8 @@ use std::fs; use std::path::{Path, PathBuf, Component}; use std::process::Command; +use build_helper::t; + use crate::dist::{self, pkgname, sanitize_sh, tmpdir}; use crate::builder::{Builder, RunConfig, ShouldRun, Step}; diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index f63aac0f0e249..ca4489655ca7b 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -108,17 +108,6 @@ #![feature(core_intrinsics)] #![feature(drain_filter)] -#[macro_use] -extern crate build_helper; -#[macro_use] -extern crate serde_derive; -#[macro_use] -extern crate lazy_static; - -#[cfg(test)] -#[macro_use] -extern crate pretty_assertions; - use std::cell::{RefCell, Cell}; use std::collections::{HashSet, HashMap}; use std::env; @@ -134,7 +123,9 @@ use std::os::unix::fs::symlink as symlink_file; #[cfg(windows)] use std::os::windows::fs::symlink_file; -use build_helper::{run_silent, run_suppressed, try_run_silent, try_run_suppressed, output, mtime}; +use build_helper::{ + mtime, output, run_silent, run_suppressed, t, try_run_silent, try_run_suppressed, +}; use filetime::FileTime; use crate::util::{exe, libdir, OutputFolder, CiEnv}; diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs index 7fa377f310b4f..4a71fd2ce0bd2 100644 --- a/src/bootstrap/metadata.rs +++ b/src/bootstrap/metadata.rs @@ -4,6 +4,7 @@ use std::path::PathBuf; use std::collections::HashSet; use build_helper::output; +use serde::Deserialize; use serde_json; use crate::{Build, Crate}; diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 285f9458c44b6..5777331b9bfd5 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -14,7 +14,7 @@ use std::fs::{self, File}; use std::path::{Path, PathBuf}; use std::process::Command; -use build_helper::output; +use build_helper::{output, t}; use cmake; use cc; diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index fa6857cdc1125..dc65fb9b79706 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -15,7 +15,7 @@ use std::fs; use std::path::PathBuf; use std::process::Command; -use build_helper::output; +use build_helper::{output, t}; use crate::Build; diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 38027aded9c53..a3d96836aad54 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -11,7 +11,7 @@ use std::iter; use std::path::{Path, PathBuf}; use std::process::Command; -use build_helper::{self, output}; +use build_helper::{self, output, t}; use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; use crate::cache::{Interned, INTERNER}; diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index c23ddbdbc6810..edcd68d010e84 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -4,6 +4,8 @@ use std::path::PathBuf; use std::process::{Command, exit}; use std::collections::HashSet; +use build_helper::t; + use crate::Mode; use crate::Compiler; use crate::builder::{Step, RunConfig, ShouldRun, Builder}; diff --git a/src/bootstrap/toolstate.rs b/src/bootstrap/toolstate.rs index 8ff7c09fc2996..e86209be91fe1 100644 --- a/src/bootstrap/toolstate.rs +++ b/src/bootstrap/toolstate.rs @@ -1,3 +1,5 @@ +use serde::{Deserialize, Serialize}; + #[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] #[serde(rename_all = "kebab-case")] /// Whether a tool can be compiled, tested or neither diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index bda1e56e1e73b..a162c65672f82 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -11,6 +11,8 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::time::{SystemTime, Instant}; +use build_helper::t; + use crate::config::Config; use crate::builder::Builder; diff --git a/src/tools/build-manifest/Cargo.toml b/src/tools/build-manifest/Cargo.toml index 93d0f61e1d9f0..63b6399bb9034 100644 --- a/src/tools/build-manifest/Cargo.toml +++ b/src/tools/build-manifest/Cargo.toml @@ -7,4 +7,3 @@ edition = "2018" [dependencies] toml = "0.4" serde = { version = "1.0", features = ["derive"] } -serde_derive = "1.0" diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml index 00e1a53473cda..336d7e32024b7 100644 --- a/src/tools/compiletest/Cargo.toml +++ b/src/tools/compiletest/Cargo.toml @@ -11,9 +11,8 @@ filetime = "0.2" getopts = "0.2" log = "0.4" regex = "1.0" -serde = "1.0" +serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -serde_derive = "1.0" rustfix = "0.4.1" lazy_static = "1.0" walkdir = "2" diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs index 0329fb0db1422..5b3936ffc1e3b 100644 --- a/src/tools/compiletest/src/errors.rs +++ b/src/tools/compiletest/src/errors.rs @@ -7,6 +7,8 @@ use std::io::BufReader; use std::path::Path; use std::str::FromStr; +use log::*; + #[derive(Clone, Debug, PartialEq)] pub enum ErrorKind { Help, diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 54e9b76a21ee0..dbc477585cbfc 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -4,6 +4,8 @@ use std::io::prelude::*; use std::io::BufReader; use std::path::{Path, PathBuf}; +use log::*; + use crate::common::{self, CompareMode, Config, Mode}; use crate::util; diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs index d651b9a92b649..02b09e21ff022 100644 --- a/src/tools/compiletest/src/json.rs +++ b/src/tools/compiletest/src/json.rs @@ -3,6 +3,7 @@ use crate::errors::{Error, ErrorKind}; use crate::runtest::ProcRes; +use serde::Deserialize; use serde_json; use std::path::{Path, PathBuf}; use std::str::FromStr; diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index dc5d1b9a853ef..e253934e566a7 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -3,14 +3,6 @@ #![feature(vec_remove_item)] #![deny(warnings, rust_2018_idioms)] -#[cfg(unix)] -extern crate libc; -#[macro_use] -extern crate log; -#[macro_use] -extern crate lazy_static; -#[macro_use] -extern crate serde_derive; extern crate test; use crate::common::CompareMode; @@ -30,6 +22,7 @@ use crate::util::logv; use walkdir::WalkDir; use env_logger; use getopts; +use log::*; use self::header::{EarlyProps, Ignore}; diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index a11a4f17eb504..3689946c055e5 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -29,6 +29,9 @@ use std::path::{Path, PathBuf}; use std::process::{Child, Command, ExitStatus, Output, Stdio}; use std::str; +use lazy_static::lazy_static; +use log::*; + use crate::extract_gdb_version; use crate::is_android_gdb_target; diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index 50dce4b55ae86..adc1224bcd367 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -3,6 +3,8 @@ use std::env; use std::path::PathBuf; use crate::common::Config; +use log::*; + /// Conversion table from triple OS name to Rust SYSNAME const OS_TABLE: &'static [(&'static str, &'static str)] = &[ ("android", "android"), diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml index 433e9264dd1dc..eeac6cfbb30e0 100644 --- a/src/tools/tidy/Cargo.toml +++ b/src/tools/tidy/Cargo.toml @@ -6,6 +6,5 @@ edition = "2018" [dependencies] regex = "1" -serde = "1.0.8" -serde_derive = "1.0.8" +serde = { version = "1.0.8", features = ["derive"] } serde_json = "1.0.2" diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index e90737febd5bf..8626ba060bf71 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -5,7 +5,7 @@ use std::fs; use std::path::Path; use std::process::Command; -use serde_derive::Deserialize; +use serde::Deserialize; use serde_json; const LICENSES: &[&str] = &[ From e57c7b859d3d60ee9c1ed63ac87234e83b088f82 Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 9 May 2019 18:13:21 +0100 Subject: [PATCH 144/212] Add regression test for #60674. This commit adds a regression test (with current broken behaviour) that tests that `mut` patterns are not lost when provided as input to a proc macro. --- src/test/ui/async-await/auxiliary/issue-60674.rs | 12 ++++++++++++ src/test/ui/async-await/issue-60674.rs | 14 ++++++++++++++ src/test/ui/async-await/issue-60674.stdout | 1 + 3 files changed, 27 insertions(+) create mode 100644 src/test/ui/async-await/auxiliary/issue-60674.rs create mode 100644 src/test/ui/async-await/issue-60674.rs create mode 100644 src/test/ui/async-await/issue-60674.stdout diff --git a/src/test/ui/async-await/auxiliary/issue-60674.rs b/src/test/ui/async-await/auxiliary/issue-60674.rs new file mode 100644 index 0000000000000..680c6e55e5668 --- /dev/null +++ b/src/test/ui/async-await/auxiliary/issue-60674.rs @@ -0,0 +1,12 @@ +// force-host +// no-prefer-dynamic +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn attr(_args: TokenStream, input: TokenStream) -> TokenStream { + println!("{}", input); + TokenStream::new() +} diff --git a/src/test/ui/async-await/issue-60674.rs b/src/test/ui/async-await/issue-60674.rs new file mode 100644 index 0000000000000..37e356e5baf48 --- /dev/null +++ b/src/test/ui/async-await/issue-60674.rs @@ -0,0 +1,14 @@ +// aux-build:issue-60674.rs +// compile-pass +// edition:2018 +#![feature(async_await)] + +// This is a regression test that ensures that `mut` patterns are not lost when provided as input +// to a proc macro. + +extern crate issue_60674; + +#[issue_60674::attr] +async fn f(mut x: u8) {} + +fn main() {} diff --git a/src/test/ui/async-await/issue-60674.stdout b/src/test/ui/async-await/issue-60674.stdout new file mode 100644 index 0000000000000..f1dbcbaac0bf4 --- /dev/null +++ b/src/test/ui/async-await/issue-60674.stdout @@ -0,0 +1 @@ +async fn f(x: u8) { } From df41e4f695a057fb14fdbc63b9009dafe4d7f681 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Thu, 9 May 2019 10:49:39 -0700 Subject: [PATCH 145/212] Remove the old await! macro This doesn't work anymore, and its continued presence is cause for confusion. --- src/libstd/macros.rs | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 9eba76cc04a64..03aebeda47c48 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -357,29 +357,6 @@ macro_rules! dbg { }; } -/// Awaits the completion of an async call. -#[macro_export] -#[unstable(feature = "await_macro", issue = "50547")] -#[allow_internal_unstable(gen_future, generators)] -#[allow_internal_unsafe] -macro_rules! r#await { - ($e:expr) => { { - let mut pinned = $e; - loop { - if let $crate::task::Poll::Ready(x) = - $crate::future::poll_with_tls_context(unsafe { - $crate::pin::Pin::new_unchecked(&mut pinned) - }) - { - break x; - } - // FIXME(cramertj) prior to stabilizing await, we have to ensure that this - // can't be used to create a generator on stable via `|| await!()`. - yield - } - } } -} - /// Selects the first successful receive event from a number of receivers. /// /// This macro is used to wait for the first event to occur on a number of From dcd3cf70177f5af115d4799fc7fff836b3bcf649 Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 9 May 2019 19:10:27 +0100 Subject: [PATCH 146/212] Do not modify mutability of simple bindings. This commit removes the modification of the mutability of simple bindings. While the mutability isn't used, it is important that it is kept so that the input to procedural macros matches what the user wrote. This commit also modifies the span of the binding mode so that it is considered a compiler desugaring and won't be linted against for being unused.. --- src/librustc/hir/lowering.rs | 44 ++++++---------------- src/libsyntax/parse/parser.rs | 23 ++++++----- src/libsyntax/source_map.rs | 21 +++++++++++ src/test/ui/async-await/issue-60674.stdout | 2 +- 4 files changed, 46 insertions(+), 44 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 20e016b8b5b1e..2f1bb1475bff6 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -50,7 +50,6 @@ use errors::Applicability; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::thin_vec::ThinVec; -use rustc_data_structures::sync::Lrc; use std::collections::{BTreeSet, BTreeMap}; use std::mem; @@ -59,10 +58,10 @@ use syntax::attr; use syntax::ast; use syntax::ast::*; use syntax::errors; -use syntax::ext::hygiene::{Mark, SyntaxContext}; +use syntax::ext::hygiene::Mark; use syntax::print::pprust; use syntax::ptr::P; -use syntax::source_map::{self, respan, CompilerDesugaringKind, Spanned}; +use syntax::source_map::{respan, CompilerDesugaringKind, Spanned}; use syntax::std_inject; use syntax::symbol::{keywords, Symbol}; use syntax::tokenstream::{TokenStream, TokenTree}; @@ -855,27 +854,6 @@ impl<'a> LoweringContext<'a> { Ident::with_empty_ctxt(Symbol::gensym(s)) } - /// Reuses the span but adds information like the kind of the desugaring and features that are - /// allowed inside this span. - fn mark_span_with_reason( - &self, - reason: CompilerDesugaringKind, - span: Span, - allow_internal_unstable: Option>, - ) -> Span { - let mark = Mark::fresh(Mark::root()); - mark.set_expn_info(source_map::ExpnInfo { - call_site: span, - def_site: Some(span), - format: source_map::CompilerDesugaring(reason), - allow_internal_unstable, - allow_internal_unsafe: false, - local_inner_macros: false, - edition: source_map::hygiene::default_edition(), - }); - span.with_ctxt(SyntaxContext::empty().apply_mark(mark)) - } - fn with_anonymous_lifetime_mode( &mut self, anonymous_lifetime_mode: AnonymousLifetimeMode, @@ -1164,7 +1142,7 @@ impl<'a> LoweringContext<'a> { attrs: ThinVec::new(), }; - let unstable_span = self.mark_span_with_reason( + let unstable_span = self.sess.source_map().mark_span_with_reason( CompilerDesugaringKind::Async, span, Some(vec![ @@ -1571,7 +1549,7 @@ impl<'a> LoweringContext<'a> { // desugaring that explicitly states that we don't want to track that. // Not tracking it makes lints in rustc and clippy very fragile as // frequently opened issues show. - let exist_ty_span = self.mark_span_with_reason( + let exist_ty_span = self.sess.source_map().mark_span_with_reason( CompilerDesugaringKind::ExistentialReturnType, span, None, @@ -2446,7 +2424,7 @@ impl<'a> LoweringContext<'a> { ) -> hir::FunctionRetTy { let span = output.span(); - let exist_ty_span = self.mark_span_with_reason( + let exist_ty_span = self.sess.source_map().mark_span_with_reason( CompilerDesugaringKind::Async, span, None, @@ -4182,7 +4160,7 @@ impl<'a> LoweringContext<'a> { }), ExprKind::TryBlock(ref body) => { self.with_catch_scope(body.id, |this| { - let unstable_span = this.mark_span_with_reason( + let unstable_span = this.sess.source_map().mark_span_with_reason( CompilerDesugaringKind::TryBlock, body.span, Some(vec![ @@ -4615,7 +4593,7 @@ impl<'a> LoweringContext<'a> { // expand let mut head = self.lower_expr(head); let head_sp = head.span; - let desugared_span = self.mark_span_with_reason( + let desugared_span = self.sess.source_map().mark_span_with_reason( CompilerDesugaringKind::ForLoop, head_sp, None, @@ -4776,7 +4754,7 @@ impl<'a> LoweringContext<'a> { // return Try::from_error(From::from(err)), // } - let unstable_span = self.mark_span_with_reason( + let unstable_span = self.sess.source_map().mark_span_with_reason( CompilerDesugaringKind::QuestionMark, e.span, Some(vec![ @@ -4784,7 +4762,7 @@ impl<'a> LoweringContext<'a> { ].into()), ); let try_span = self.sess.source_map().end_point(e.span); - let try_span = self.mark_span_with_reason( + let try_span = self.sess.source_map().mark_span_with_reason( CompilerDesugaringKind::QuestionMark, try_span, Some(vec![ @@ -5569,12 +5547,12 @@ impl<'a> LoweringContext<'a> { ); self.sess.abort_if_errors(); } - let span = self.mark_span_with_reason( + let span = self.sess.source_map().mark_span_with_reason( CompilerDesugaringKind::Await, await_span, None, ); - let gen_future_span = self.mark_span_with_reason( + let gen_future_span = self.sess.source_map().mark_span_with_reason( CompilerDesugaringKind::Await, await_span, Some(vec![Symbol::intern("gen_future")].into()), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index f3eac71ee7761..ab4de4891a5b0 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -50,7 +50,10 @@ use crate::symbol::{Symbol, keywords}; use errors::{Applicability, DiagnosticBuilder, DiagnosticId, FatalError}; use rustc_target::spec::abi::{self, Abi}; -use syntax_pos::{Span, MultiSpan, BytePos, FileName}; +use syntax_pos::{ + Span, MultiSpan, BytePos, FileName, + hygiene::CompilerDesugaringKind, +}; use log::{debug, trace}; use std::borrow::Cow; @@ -8741,6 +8744,15 @@ impl<'a> Parser<'a> { // statement. let (binding_mode, ident, is_simple_pattern) = match input.pat.node { PatKind::Ident(binding_mode @ BindingMode::ByValue(_), ident, _) => { + // Simple patterns like this don't have a generated argument, but they are + // moved into the closure with a statement, so any `mut` bindings on the + // argument will be unused. This binding mode can't be removed, because + // this would affect the input to procedural macros, but they can have + // their span marked as being the result of a compiler desugaring so + // that they aren't linted against. + input.pat.span = self.sess.source_map().mark_span_with_reason( + CompilerDesugaringKind::Async, span, None); + (binding_mode, ident, true) } _ => (BindingMode::ByValue(Mutability::Mutable), ident, false), @@ -8810,15 +8822,6 @@ impl<'a> Parser<'a> { }) }; - // Remove mutability from arguments. If this is not a simple pattern, - // those arguments are replaced by `__argN`, so there is no need to do this. - if let PatKind::Ident(BindingMode::ByValue(mutability @ Mutability::Mutable), ..) = - &mut input.pat.node - { - assert!(is_simple_pattern); - *mutability = Mutability::Immutable; - } - let move_stmt = Stmt { id, node: StmtKind::Local(P(move_local)), span }; arguments.push(AsyncArgument { ident, arg, pat_stmt, move_stmt }); } diff --git a/src/libsyntax/source_map.rs b/src/libsyntax/source_map.rs index 08abbf5e8a4dc..215618bd09ca3 100644 --- a/src/libsyntax/source_map.rs +++ b/src/libsyntax/source_map.rs @@ -930,6 +930,27 @@ impl SourceMap { None } + + /// Reuses the span but adds information like the kind of the desugaring and features that are + /// allowed inside this span. + pub fn mark_span_with_reason( + &self, + reason: hygiene::CompilerDesugaringKind, + span: Span, + allow_internal_unstable: Option>, + ) -> Span { + let mark = Mark::fresh(Mark::root()); + mark.set_expn_info(ExpnInfo { + call_site: span, + def_site: Some(span), + format: CompilerDesugaring(reason), + allow_internal_unstable, + allow_internal_unsafe: false, + local_inner_macros: false, + edition: hygiene::default_edition(), + }); + span.with_ctxt(SyntaxContext::empty().apply_mark(mark)) + } } impl SourceMapper for SourceMap { diff --git a/src/test/ui/async-await/issue-60674.stdout b/src/test/ui/async-await/issue-60674.stdout index f1dbcbaac0bf4..a93944db1c591 100644 --- a/src/test/ui/async-await/issue-60674.stdout +++ b/src/test/ui/async-await/issue-60674.stdout @@ -1 +1 @@ -async fn f(x: u8) { } +async fn f(mut x: u8) { } From d5e04067cb23df91070fea1a01aa6417afa714ed Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 9 May 2019 19:14:39 +0100 Subject: [PATCH 147/212] Add FIXME about `construct_async_arguments`. This is unrelated to the rest of this PR but it made sense to add a FIXME explaining that the function shouldn't really be in the parser. --- src/libsyntax/parse/parser.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index ab4de4891a5b0..5fd6276a237cd 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -8730,6 +8730,10 @@ impl<'a> Parser<'a> { /// The arguments of the function are replaced in HIR lowering with the arguments created by /// this function and the statements created here are inserted at the top of the closure body. fn construct_async_arguments(&mut self, asyncness: &mut Spanned, decl: &mut FnDecl) { + // FIXME(davidtwco): This function should really live in the HIR lowering but because + // the types constructed here need to be used in parts of resolve so that the correct + // locals are considered upvars, it is currently easier for it to live here in the parser, + // where it can be constructed once. if let IsAsync::Async { ref mut arguments, .. } = asyncness.node { for (index, input) in decl.inputs.iter_mut().enumerate() { let id = ast::DUMMY_NODE_ID; From 1fe3ce1c42b8125f4f93dd3c3a5d5eed8c0cb651 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 30 Apr 2019 19:37:25 -0700 Subject: [PATCH 148/212] Omit the vendor component in the WASI triple This renames wasm32-unknown-wasi to wasm32-wasi, omitting the vendor component. This follows aarch64-linux-android, x86_64-fuchsia, and others in omitting the vendor field, which has the advantage of aligning with the [multiarch tuple](https://wiki.debian.org/Multiarch/Tuples), and of being less noisy. --- config.toml.example | 2 +- src/ci/docker/dist-various-2/Dockerfile | 4 +-- .../dist-various-2/build-wasi-toolchain.sh | 2 +- src/librustc_target/spec/mod.rs | 2 +- ...{wasm32_unknown_wasi.rs => wasm32_wasi.rs} | 34 +++++++++---------- src/tools/build-manifest/src/main.rs | 2 +- 6 files changed, 23 insertions(+), 23 deletions(-) rename src/librustc_target/spec/{wasm32_unknown_wasi.rs => wasm32_wasi.rs} (80%) diff --git a/config.toml.example b/config.toml.example index 8b2153cd2e63c..556625b531d1c 100644 --- a/config.toml.example +++ b/config.toml.example @@ -480,7 +480,7 @@ # linked binaries #musl-root = "..." -# The root location of the `wasm32-unknown-wasi` sysroot. +# The root location of the `wasm32-wasi` sysroot. #wasi-root = "..." # Used in testing for configuring where the QEMU images are located, you diff --git a/src/ci/docker/dist-various-2/Dockerfile b/src/ci/docker/dist-various-2/Dockerfile index c0f3326524d5c..b0a3f715b494a 100644 --- a/src/ci/docker/dist-various-2/Dockerfile +++ b/src/ci/docker/dist-various-2/Dockerfile @@ -69,7 +69,7 @@ ENV TARGETS=x86_64-fuchsia ENV TARGETS=$TARGETS,aarch64-fuchsia ENV TARGETS=$TARGETS,sparcv9-sun-solaris ENV TARGETS=$TARGETS,wasm32-unknown-unknown -ENV TARGETS=$TARGETS,wasm32-unknown-wasi +ENV TARGETS=$TARGETS,wasm32-wasi ENV TARGETS=$TARGETS,x86_64-sun-solaris ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnux32 ENV TARGETS=$TARGETS,x86_64-unknown-cloudabi @@ -79,5 +79,5 @@ ENV TARGETS=$TARGETS,nvptx64-nvidia-cuda ENV X86_FORTANIX_SGX_LIBS="/x86_64-fortanix-unknown-sgx/lib/" ENV RUST_CONFIGURE_ARGS --enable-extended --enable-lld --disable-docs \ - --set target.wasm32-unknown-wasi.wasi-root=/wasm32-unknown-wasi + --set target.wasm32-wasi.wasi-root=/wasm32-wasi ENV SCRIPT python2.7 ../x.py dist --target $TARGETS diff --git a/src/ci/docker/dist-various-2/build-wasi-toolchain.sh b/src/ci/docker/dist-various-2/build-wasi-toolchain.sh index 965286e5bcf64..98d6df043baca 100755 --- a/src/ci/docker/dist-various-2/build-wasi-toolchain.sh +++ b/src/ci/docker/dist-various-2/build-wasi-toolchain.sh @@ -13,7 +13,7 @@ git clone https://github.com/CraneStation/wasi-sysroot cd wasi-sysroot git reset --hard e5f14be38362f1ab83302895a6e74b2ffd0e2302 -make -j$(nproc) INSTALL_DIR=/wasm32-unknown-wasi install +make -j$(nproc) INSTALL_DIR=/wasm32-wasi install cd .. rm -rf reference-sysroot-wasi diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 46fefd78f4519..b30a4fe76a2da 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -444,7 +444,7 @@ supported_targets! { ("asmjs-unknown-emscripten", asmjs_unknown_emscripten), ("wasm32-unknown-emscripten", wasm32_unknown_emscripten), ("wasm32-unknown-unknown", wasm32_unknown_unknown), - ("wasm32-unknown-wasi", wasm32_unknown_wasi), + ("wasm32-wasi", wasm32_wasi), ("wasm32-experimental-emscripten", wasm32_experimental_emscripten), ("thumbv6m-none-eabi", thumbv6m_none_eabi), diff --git a/src/librustc_target/spec/wasm32_unknown_wasi.rs b/src/librustc_target/spec/wasm32_wasi.rs similarity index 80% rename from src/librustc_target/spec/wasm32_unknown_wasi.rs rename to src/librustc_target/spec/wasm32_wasi.rs index 0412635bfe2db..bb33493a77333 100644 --- a/src/librustc_target/spec/wasm32_unknown_wasi.rs +++ b/src/librustc_target/spec/wasm32_wasi.rs @@ -1,4 +1,4 @@ -//! The `wasm32-unknown-wasi` target is a new and still (as of March 2019) +//! The `wasm32-wasi` target is a new and still (as of April 2019) an //! experimental target. The definition in this file is likely to be tweaked //! over time and shouldn't be relied on too much. //! @@ -13,14 +13,14 @@ //! serve two use cases here with this target: //! //! * First, we want Rust usage of the target to be as hassle-free as possible, -//! ideally avoiding the need to configure and install a local -//! wasm32-unknown-wasi toolchain. +//! ideally avoiding the need to configure and install a local wasm32-wasi +//! toolchain. //! //! * Second, one of the primary use cases of LLVM's new wasm backend and the //! wasm support in LLD is that any compiled language can interoperate with -//! any other. To that the `wasm32-unknown-wasi` target is the first with a -//! viable C standard library and sysroot common definition, so we want Rust -//! and C/C++ code to interoperate when compiled to `wasm32-unknown-unknown`. +//! any other. To that the `wasm32-wasi` target is the first with a viable C +//! standard library and sysroot common definition, so we want Rust and C/C++ +//! code to interoperate when compiled to `wasm32-unknown-unknown`. //! //! You'll note, however, that the two goals above are somewhat at odds with one //! another. To attempt to solve both use cases in one go we define a target @@ -39,8 +39,8 @@ //! necessary. //! //! All in all, by default, no external dependencies are required. You can -//! compile `wasm32-unknown-wasi` binaries straight out of the box. You can't, -//! however, reliably interoperate with C code in this mode (yet). +//! compile `wasm32-wasi` binaries straight out of the box. You can't, however, +//! reliably interoperate with C code in this mode (yet). //! //! ## Interop with C required //! @@ -53,17 +53,17 @@ //! //! 2. If you're using rustc to build a linked artifact then you'll need to //! specify `-C linker` to a `clang` binary that supports -//! `wasm32-unknown-wasi` and is configured with the `wasm32-unknown-wasi` -//! sysroot. This will cause Rust code to be linked against the libc.a that -//! the specified `clang` provides. +//! `wasm32-wasi` and is configured with the `wasm32-wasi` sysroot. This +//! will cause Rust code to be linked against the libc.a that the specified +//! `clang` provides. //! //! 3. If you're building a staticlib and integrating Rust code elsewhere, then //! compiling with `-C target-feature=-crt-static` is all you need to do. //! //! You can configure the linker via Cargo using the -//! `CARGO_TARGET_WASM32_UNKNOWN_WASI_LINKER` env var. Be sure to also set -//! `CC_wasm32-unknown-wasi` if any crates in the dependency graph are using -//! the `cc` crate. +//! `CARGO_TARGET_WASM32_WASI_LINKER` env var. Be sure to also set +//! `CC_wasm32-wasi` if any crates in the dependency graph are using the `cc` +//! crate. //! //! ## Remember, this is all in flux //! @@ -82,7 +82,7 @@ pub fn target() -> Result { .pre_link_args .entry(LinkerFlavor::Gcc) .or_insert(Vec::new()) - .push("--target=wasm32-unknown-wasi".to_string()); + .push("--target=wasm32-wasi".to_string()); // When generating an executable be sure to put the startup object at the // front so the main function is correctly hooked up. @@ -98,13 +98,13 @@ pub fn target() -> Result { options.crt_static_respected = true; Ok(Target { - llvm_target: "wasm32-unknown-wasi".to_string(), + llvm_target: "wasm32-wasi".to_string(), target_endian: "little".to_string(), target_pointer_width: "32".to_string(), target_c_int_width: "32".to_string(), target_os: "wasi".to_string(), target_env: String::new(), - target_vendor: "unknown".to_string(), + target_vendor: String::new(), data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(), arch: "wasm32".to_string(), linker_flavor: LinkerFlavor::Lld(LldFlavor::Wasm), diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 61cc78ad807af..5efd51b65c14a 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -108,7 +108,7 @@ static TARGETS: &[&str] = &[ "thumbv8m.main-none-eabihf", "wasm32-unknown-emscripten", "wasm32-unknown-unknown", - "wasm32-unknown-wasi", + "wasm32-wasi", "x86_64-apple-darwin", "x86_64-apple-ios", "x86_64-fortanix-unknown-sgx", From adb998fe21f148e8f84fc1262725c4385216c95d Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Thu, 9 May 2019 15:00:06 -0700 Subject: [PATCH 149/212] Fix cfg(test) build on SGX --- src/libstd/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 3976f2344e241..2401946536ffa 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -223,6 +223,7 @@ #![cfg_attr(all(target_vendor = "fortanix", target_env = "sgx"), feature(global_asm, slice_index_methods, decl_macro, coerce_unsized, sgx_platform, ptr_wrapping_offset_from))] +#![cfg_attr(all(test, target_vendor = "fortanix", target_env = "sgx"), feature(fixed_size_array))] // std is implemented with unstable features, many of which are internal // compiler details that will never be stable From 8c465b4efab9dec55434193acacf0a10e83c3ae0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 9 May 2019 11:45:56 +1000 Subject: [PATCH 150/212] Add `InternedString::with2`. This lets comparisons occur with a single access to the interner, instead of two. --- src/libsyntax_pos/symbol.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 20759217b54a0..107cf8360c4f9 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -725,6 +725,15 @@ impl InternedString { unsafe { f(&*str) } } + fn with2 R, R>(self, other: &InternedString, f: F) -> R { + let (self_str, other_str) = with_interner(|interner| { + (interner.get(self.symbol) as *const str, + interner.get(other.symbol) as *const str) + }); + // This is safe for the same reason that `with` is safe. + unsafe { f(&*self_str, &*other_str) } + } + pub fn as_symbol(self) -> Symbol { self.symbol } @@ -745,7 +754,7 @@ impl PartialOrd for InternedString { if self.symbol == other.symbol { return Some(Ordering::Equal); } - self.with(|self_str| other.with(|other_str| self_str.partial_cmp(other_str))) + self.with2(other, |self_str, other_str| self_str.partial_cmp(other_str)) } } @@ -754,7 +763,7 @@ impl Ord for InternedString { if self.symbol == other.symbol { return Ordering::Equal; } - self.with(|self_str| other.with(|other_str| self_str.cmp(&other_str))) + self.with2(other, |self_str, other_str| self_str.cmp(other_str)) } } From c2cae7bbc3880ec2874b32756c7c5dc52997a552 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 9 May 2019 11:54:47 +1000 Subject: [PATCH 151/212] Avoid recursion in de-gensym functions. --- src/libsyntax_pos/symbol.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 107cf8360c4f9..e8472e1b9f1f2 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -492,7 +492,7 @@ impl Interner { if (symbol.0.as_usize()) < self.strings.len() { symbol } else { - self.interned(self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize]) + self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize] } } @@ -513,7 +513,10 @@ impl Interner { pub fn get(&self, symbol: Symbol) -> &str { match self.strings.get(symbol.0.as_usize()) { Some(string) => string, - None => self.get(self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize]), + None => { + let symbol = self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize]; + self.strings[symbol.0.as_usize()] + } } } } From 0e27c36145594dcf3f00707543f11f591a63ec95 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 9 May 2019 12:09:57 +1000 Subject: [PATCH 152/212] Add various comments. Lots of details I wish I'd known when I first looked at this code. --- src/libsyntax_pos/symbol.rs | 52 ++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index e8472e1b9f1f2..ee4a581123f88 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -344,9 +344,22 @@ impl Decodable for Ident { } } -/// A symbol is an interned or gensymed string. The use of `newtype_index!` means -/// that `Option` only takes up 4 bytes, because `newtype_index!` reserves -/// the last 256 values for tagging purposes. +/// A symbol is an interned or gensymed string. A gensym is a symbol that is +/// never equal to any other symbol. E.g.: +/// ``` +/// assert_eq!(Symbol::intern("x"), Symbol::intern("x")) +/// assert_ne!(Symbol::gensym("x"), Symbol::intern("x")) +/// assert_ne!(Symbol::gensym("x"), Symbol::gensym("x")) +/// ``` +/// Conceptually, a gensym can be thought of as a normal symbol with an +/// invisible unique suffix. Gensyms are useful when creating new identifiers +/// that must not match any existing identifiers, e.g. during macro expansion +/// and syntax desugaring. +/// +/// Internally, a Symbol is implemented as an index, and all operations +/// (including hashing, equality, and ordering) operate on that index. The use +/// of `newtype_index!` means that `Option` only takes up 4 bytes, +/// because `newtype_index!` reserves the last 256 values for tagging purposes. /// /// Note that `Symbol` cannot directly be a `newtype_index!` because it implements /// `fmt::Debug`, `Encodable`, and `Decodable` in special ways. @@ -380,6 +393,7 @@ impl Symbol { with_interner(|interner| interner.gensymed(self)) } + // WARNING: this function is deprecated and will be removed in the future. pub fn is_gensymed(self) -> bool { with_interner(|interner| interner.is_gensymed(self)) } @@ -510,6 +524,8 @@ impl Interner { symbol.0.as_usize() >= self.strings.len() } + // Get the symbol as a string. `Symbol::as_str()` should be used in + // preference to this function. pub fn get(&self, symbol: Symbol) -> &str { match self.strings.get(symbol.0.as_usize()) { Some(string) => string, @@ -614,11 +630,17 @@ fn with_interner T>(f: F) -> T { GLOBALS.with(|globals| f(&mut *globals.symbol_interner.lock())) } -/// Represents a string stored in the interner. Because the interner outlives any thread -/// which uses this type, we can safely treat `string` which points to interner data, -/// as an immortal string, as long as this type never crosses between threads. -// FIXME: ensure that the interner outlives any thread which uses `LocalInternedString`, -// by creating a new thread right after constructing the interner. +/// An alternative to `Symbol` and `InternedString`, useful when the chars +/// within the symbol need to be accessed. It is best used for temporary +/// values. +/// +/// Because the interner outlives any thread which uses this type, we can +/// safely treat `string` which points to interner data, as an immortal string, +/// as long as this type never crosses between threads. +// +// FIXME: ensure that the interner outlives any thread which uses +// `LocalInternedString`, by creating a new thread right after constructing the +// interner. #[derive(Clone, Copy, Hash, PartialOrd, Eq, Ord)] pub struct LocalInternedString { string: &'static str, @@ -711,7 +733,19 @@ impl Encodable for LocalInternedString { } } -/// Represents a string stored in the string interner. +/// An alternative to `Symbol` that is focused on string contents. It has two +/// main differences to `Symbol`. +/// +/// First, its implementations of `Hash`, `PartialOrd` and `Ord` work with the +/// string chars rather than the symbol integer. This is useful when hash +/// stability is required across compile sessions, or a guaranteed sort +/// ordering is required. +/// +/// Second, gensym-ness is irrelevant. E.g.: +/// ``` +/// assert_ne!(Symbol::gensym("x"), Symbol::gensym("x")) +/// assert_eq!(Symbol::gensym("x").as_interned_str(), Symbol::gensym("x").as_interned_str()) +/// ``` #[derive(Clone, Copy, Eq)] pub struct InternedString { symbol: Symbol, From cb7eacb1d2f856f52f2daf3b58325e667f654eca Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 9 May 2019 12:14:30 +1000 Subject: [PATCH 153/212] Remove the `From for String` impl. It's not used. --- src/libsyntax_pos/symbol.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index ee4a581123f88..231cfb793f844 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -840,12 +840,6 @@ impl<'a> PartialEq for &'a String { } } -impl std::convert::From for String { - fn from(val: InternedString) -> String { - val.as_symbol().to_string() - } -} - impl fmt::Debug for InternedString { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.with(|str| fmt::Debug::fmt(&str, f)) From e53bb1aefb0aba8fcadaf73b2c0f334dd36c2b23 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 9 May 2019 14:06:10 +1000 Subject: [PATCH 154/212] Reduce `Symbol`'s interface slightly. --- src/libsyntax_pos/symbol.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 231cfb793f844..d0ba09af30b06 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -380,10 +380,6 @@ impl Symbol { with_interner(|interner| interner.intern(string)) } - pub fn interned(self) -> Self { - with_interner(|interner| interner.interned(self)) - } - /// Gensyms a new `usize`, using the current interner. pub fn gensym(string: &str) -> Self { with_interner(|interner| interner.gensym(string)) @@ -502,7 +498,7 @@ impl Interner { name } - pub fn interned(&self, symbol: Symbol) -> Symbol { + fn interned(&self, symbol: Symbol) -> Symbol { if (symbol.0.as_usize()) < self.strings.len() { symbol } else { From d28b7afd17e26c6b17a65b981684d03a0905c293 Mon Sep 17 00:00:00 2001 From: David Wood Date: Fri, 10 May 2019 08:55:54 +0100 Subject: [PATCH 155/212] Extend existing test for nested mut patterns. At request of `@centril`, this commit extends the existing test added by #60676 to include nested `mut` patterns. --- src/test/ui/async-await/issue-60674.rs | 6 ++++++ src/test/ui/async-await/issue-60674.stdout | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/test/ui/async-await/issue-60674.rs b/src/test/ui/async-await/issue-60674.rs index 37e356e5baf48..ecb80803383b4 100644 --- a/src/test/ui/async-await/issue-60674.rs +++ b/src/test/ui/async-await/issue-60674.rs @@ -11,4 +11,10 @@ extern crate issue_60674; #[issue_60674::attr] async fn f(mut x: u8) {} +#[issue_60674::attr] +async fn g((mut x, y, mut z): (u8, u8, u8)) {} + +#[issue_60674::attr] +async fn g(mut x: u8, (a, mut b, c): (u8, u8, u8), y: u8) {} + fn main() {} diff --git a/src/test/ui/async-await/issue-60674.stdout b/src/test/ui/async-await/issue-60674.stdout index a93944db1c591..86c3591b3afc0 100644 --- a/src/test/ui/async-await/issue-60674.stdout +++ b/src/test/ui/async-await/issue-60674.stdout @@ -1 +1,3 @@ async fn f(mut x: u8) { } +async fn g((mut x, y, mut z): (u8, u8, u8)) { } +async fn g(mut x: u8, (a, mut b, c): (u8, u8, u8), y: u8) { } From c81780b156c446819d94c9382eb590e881fa87b0 Mon Sep 17 00:00:00 2001 From: Marcel Hellwig Date: Fri, 10 May 2019 12:02:31 +0200 Subject: [PATCH 156/212] add regression test for #60629 --- src/test/incremental/issue-60629.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/test/incremental/issue-60629.rs diff --git a/src/test/incremental/issue-60629.rs b/src/test/incremental/issue-60629.rs new file mode 100644 index 0000000000000..4807af4b3cf70 --- /dev/null +++ b/src/test/incremental/issue-60629.rs @@ -0,0 +1,10 @@ +// revisions:rpass1 rpass2 + +struct A; + +#[cfg(rpass2)] +impl From for () { + fn from(_: A) {} +} + +fn main() {} From aeee1fb1f250accccd85f8d7f7a501ed81db68e8 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 10 May 2019 16:57:15 +0300 Subject: [PATCH 157/212] syntax_pos: Optimize symbol interner pre-filling slightly --- src/libsyntax_pos/symbol.rs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 20759217b54a0..23ab3e2bf9456 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -453,15 +453,16 @@ pub struct Interner { impl Interner { fn prefill(init: &[&str]) -> Self { let mut this = Interner::default(); - for &string in init { - if string == "" { - // We can't allocate empty strings in the arena, so handle this here. - let name = Symbol::new(this.strings.len() as u32); - this.names.insert("", name); - this.strings.push(""); - } else { - this.intern(string); - } + this.names.reserve(init.len()); + this.strings.reserve(init.len()); + + // We can't allocate empty strings in the arena, so handle this here. + assert!(keywords::Invalid.name().as_u32() == 0 && init[0].is_empty()); + this.names.insert("", keywords::Invalid.name()); + this.strings.push(""); + + for string in &init[1..] { + this.intern(string); } this } From f74debbe7d2bf43171270d5f3f5b42f2cc2e6243 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Thu, 2 May 2019 17:22:14 +0200 Subject: [PATCH 158/212] Make tests compatible with musl host --- src/bootstrap/test.rs | 4 ++++ src/ci/docker/dist-x86_64-musl/Dockerfile | 6 ++---- src/ci/docker/scripts/musl-toolchain.sh | 7 +++++++ src/test/run-make-fulldeps/link-cfg/Makefile | 2 +- .../linker-output-non-utf8/Makefile | 2 +- .../run-make-fulldeps/reproducible-build/Makefile | 4 ++++ src/test/run-make/rustc-macro-dep-files/Makefile | 5 ++++- src/tools/compiletest/src/runtest.rs | 15 ++++++++++++++- 8 files changed, 37 insertions(+), 8 deletions(-) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index a3d96836aad54..9867113e48f43 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1870,6 +1870,10 @@ impl Step for CrateRustdoc { cargo.arg("--"); cargo.args(&builder.config.cmd.test_args()); + if self.host.contains("musl") { + cargo.arg("'-Ctarget-feature=-crt-static'"); + } + if !builder.config.verbose_tests { cargo.arg("--quiet"); } diff --git a/src/ci/docker/dist-x86_64-musl/Dockerfile b/src/ci/docker/dist-x86_64-musl/Dockerfile index 39ad785b41ac6..bc3a3bd6fbc68 100644 --- a/src/ci/docker/dist-x86_64-musl/Dockerfile +++ b/src/ci/docker/dist-x86_64-musl/Dockerfile @@ -35,10 +35,7 @@ ENV RUST_CONFIGURE_ARGS \ --enable-extended \ --disable-docs \ --set target.x86_64-unknown-linux-musl.crt-static=false \ - --build $HOSTS \ - --set target.x86_64-unknown-linux-musl.cc=x86_64-linux-musl-gcc \ - --set target.x86_64-unknown-linux-musl.cxx=x86_64-linux-musl-g++ \ - --set target.x86_64-unknown-linux-musl.linker=x86_64-linux-musl-gcc + --build $HOSTS # Newer binutils broke things on some vms/distros (i.e., linking against # unknown relocs disabled by the following flag), so we need to go out of our @@ -49,4 +46,5 @@ ENV RUST_CONFIGURE_ARGS \ ENV CFLAGS_x86_64_unknown_linux_musl="-Wa,-mrelax-relocations=no -Wa,--compress-debug-sections=none \ -Wl,--compress-debug-sections=none" +# To run native tests replace `dist` below with `test` ENV SCRIPT python2.7 ../x.py dist --build $HOSTS diff --git a/src/ci/docker/scripts/musl-toolchain.sh b/src/ci/docker/scripts/musl-toolchain.sh index 8cdbfebea4dd9..e132615738bac 100644 --- a/src/ci/docker/scripts/musl-toolchain.sh +++ b/src/ci/docker/scripts/musl-toolchain.sh @@ -45,6 +45,13 @@ cd - ln -s $OUTPUT/$TARGET/lib/libc.so /lib/ld-musl-$ARCH.so.1 echo $OUTPUT/$TARGET/lib >> /etc/ld-musl-$ARCH.path +# Now when musl bootstraps itself create proper toolchain symlinks to make build and tests easier +for exec in cc gcc; do + ln -s $TARGET-gcc /usr/local/bin/$exec +done +for exec in cpp c++ g++; do + ln -s $TARGET-g++ /usr/local/bin/$exec +done export CC=$TARGET-gcc export CXX=$TARGET-g++ diff --git a/src/test/run-make-fulldeps/link-cfg/Makefile b/src/test/run-make-fulldeps/link-cfg/Makefile index 188cba5fe4127..2701b4a593cc6 100644 --- a/src/test/run-make-fulldeps/link-cfg/Makefile +++ b/src/test/run-make-fulldeps/link-cfg/Makefile @@ -2,7 +2,7 @@ all: $(call DYLIB,return1) $(call DYLIB,return2) $(call NATIVE_STATICLIB,return3) ls $(TMPDIR) - $(RUSTC) --print cfg --target x86_64-unknown-linux-musl | $(CGREP) crt-static + $(BARE_RUSTC) --print cfg --target x86_64-unknown-linux-musl | $(CGREP) crt-static $(RUSTC) no-deps.rs --cfg foo $(call RUN,no-deps) diff --git a/src/test/run-make-fulldeps/linker-output-non-utf8/Makefile b/src/test/run-make-fulldeps/linker-output-non-utf8/Makefile index 3fffd1e7aa2a2..b47ce17ec8baa 100644 --- a/src/test/run-make-fulldeps/linker-output-non-utf8/Makefile +++ b/src/test/run-make-fulldeps/linker-output-non-utf8/Makefile @@ -20,4 +20,4 @@ all: $(RUSTC) library.rs mkdir $(bad_dir) mv $(TMPDIR)/liblibrary.a $(bad_dir) - LIBRARY_PATH=$(bad_dir) $(RUSTC) exec.rs 2>&1 | $(CGREP) this_symbol_not_defined + $(RUSTC) -L $(bad_dir) exec.rs 2>&1 | $(CGREP) this_symbol_not_defined diff --git a/src/test/run-make-fulldeps/reproducible-build/Makefile b/src/test/run-make-fulldeps/reproducible-build/Makefile index ca76a5e5d77b6..a17ec212cfd58 100644 --- a/src/test/run-make-fulldeps/reproducible-build/Makefile +++ b/src/test/run-make-fulldeps/reproducible-build/Makefile @@ -1,4 +1,8 @@ -include ../tools.mk + +# ignore-musl +# Objects are reproducible but their path is not. + all: \ smoke \ debug \ diff --git a/src/test/run-make/rustc-macro-dep-files/Makefile b/src/test/run-make/rustc-macro-dep-files/Makefile index 0420a389168f1..a08a63fb44bf5 100644 --- a/src/test/run-make/rustc-macro-dep-files/Makefile +++ b/src/test/run-make/rustc-macro-dep-files/Makefile @@ -2,7 +2,10 @@ # FIXME(eddyb) provide `HOST_RUSTC` and `TARGET_RUSTC` # instead of hardcoding them everywhere they're needed. +ifeq ($(IS_MUSL_HOST),1) +ADDITIONAL_ARGS := $(RUSTFLAGS) +endif all: - $(BARE_RUSTC) foo.rs --out-dir $(TMPDIR) + $(BARE_RUSTC) $(ADDITIONAL_ARGS) foo.rs --out-dir $(TMPDIR) $(RUSTC) bar.rs --target $(TARGET) --emit dep-info $(CGREP) -v "proc-macro source" < $(TMPDIR)/bar.d diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 3689946c055e5..10b8133326bba 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1650,7 +1650,9 @@ impl<'test> TestCx<'test> { (true, None) } else if self.config.target.contains("cloudabi") || self.config.target.contains("emscripten") - || (self.config.target.contains("musl") && !aux_props.force_host) + || (self.config.target.contains("musl") + && !aux_props.force_host + && !self.config.host.contains("musl")) || self.config.target.contains("wasm32") || self.config.target.contains("nvptx") { @@ -1932,6 +1934,11 @@ impl<'test> TestCx<'test> { } } + // Use dynamic musl for tests because static doesn't allow creating dylibs + if self.config.host.contains("musl") { + rustc.arg("-Ctarget-feature=-crt-static"); + } + rustc.args(&self.props.compile_flags); rustc @@ -2725,6 +2732,12 @@ impl<'test> TestCx<'test> { // compiler flags set in the test cases: cmd.env_remove("RUSTFLAGS"); + // Use dynamic musl for tests because static doesn't allow creating dylibs + if self.config.host.contains("musl") { + cmd.env("RUSTFLAGS", "-Ctarget-feature=-crt-static") + .env("IS_MUSL_HOST", "1"); + } + if self.config.target.contains("msvc") && self.config.cc != "" { // We need to pass a path to `lib.exe`, so assume that `cc` is `cl.exe` // and that `lib.exe` lives next to it. From 0caa251da2d7272fdecb32aae6e0a9e1c3ec0756 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Fri, 10 May 2019 16:12:32 +0200 Subject: [PATCH 159/212] Conditionally provide cc in musl-toolchain.sh --- src/ci/docker/dist-x86_64-musl/Dockerfile | 2 +- src/ci/docker/scripts/musl-toolchain.sh | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/ci/docker/dist-x86_64-musl/Dockerfile b/src/ci/docker/dist-x86_64-musl/Dockerfile index bc3a3bd6fbc68..385eefde846c2 100644 --- a/src/ci/docker/dist-x86_64-musl/Dockerfile +++ b/src/ci/docker/dist-x86_64-musl/Dockerfile @@ -23,7 +23,7 @@ COPY scripts/musl-toolchain.sh /build/ # We need to mitigate rust-lang/rust#34978 when compiling musl itself as well RUN CFLAGS="-Wa,-mrelax-relocations=no -Wa,--compress-debug-sections=none -Wl,--compress-debug-sections=none" \ CXXFLAGS="-Wa,-mrelax-relocations=no -Wa,--compress-debug-sections=none -Wl,--compress-debug-sections=none" \ - bash musl-toolchain.sh x86_64 && rm -rf build + REPLACE_CC=1 bash musl-toolchain.sh x86_64 && rm -rf build COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/scripts/musl-toolchain.sh b/src/ci/docker/scripts/musl-toolchain.sh index e132615738bac..d5988a25671a2 100644 --- a/src/ci/docker/scripts/musl-toolchain.sh +++ b/src/ci/docker/scripts/musl-toolchain.sh @@ -46,12 +46,14 @@ ln -s $OUTPUT/$TARGET/lib/libc.so /lib/ld-musl-$ARCH.so.1 echo $OUTPUT/$TARGET/lib >> /etc/ld-musl-$ARCH.path # Now when musl bootstraps itself create proper toolchain symlinks to make build and tests easier -for exec in cc gcc; do - ln -s $TARGET-gcc /usr/local/bin/$exec -done -for exec in cpp c++ g++; do - ln -s $TARGET-g++ /usr/local/bin/$exec -done +if [ "$REPLACE_CC" = "1" ]; then + for exec in cc gcc; do + ln -s $TARGET-gcc /usr/local/bin/$exec + done + for exec in cpp c++ g++; do + ln -s $TARGET-g++ /usr/local/bin/$exec + done +fi export CC=$TARGET-gcc export CXX=$TARGET-g++ From 8fbe1ed6c79b630b366848cf979e724c27ba6510 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Fri, 10 May 2019 16:47:25 +0200 Subject: [PATCH 160/212] Update mailmap for mati865 --- .mailmap | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.mailmap b/.mailmap index 679e9d79847c2..63a49cd413287 100644 --- a/.mailmap +++ b/.mailmap @@ -155,6 +155,8 @@ Mark Sinclair =Mark Sinclair <=125axel125@gmail.com> Markus Westerlind Markus Martin Hafskjold Thoresen Matej Lach Matej Ľach +Mateusz Mikuła +Mateusz Mikuła Matt Brubeck Matthew Auld Matthew McPherrin From 5b6bda33543a8db601690350c585515a5273975d Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Tue, 7 May 2019 17:58:58 -0500 Subject: [PATCH 161/212] turn a couple of fixmes into span_bugs --- src/libsyntax/ext/tt/transcribe.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 0cefcf1ce034b..e3586c1854c17 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -170,10 +170,9 @@ pub fn transcribe( } LockstepIterSize::Contradiction(ref msg) => { - // FIXME: this should be impossible. I (mark-i-m) believe it would - // represent a bug in the macro_parser. - // FIXME #2887 blame macro invoker instead - cx.span_fatal(seq.span(), &msg[..]); + // This should never happen because the macro parser should generate + // properly-sized matches for all meta-vars. + cx.span_bug(seq.span(), &msg[..]); } LockstepIterSize::Constraint(len, _) => { @@ -188,14 +187,13 @@ pub fn transcribe( // Is the repetition empty? if len == 0 { if seq.op == quoted::KleeneOp::OneOrMore { - // FIXME: this should be impossible because we check for this in - // macro_parser.rs - // FIXME #2887 blame invoker - cx.span_fatal(sp.entire(), "this must repeat at least once"); + // This should be impossible because the macro parser would not + // match the given macro arm. + cx.span_bug(sp.entire(), "this must repeat at least once"); } } else { // 0 is the initial counter (we have done 0 repretitions so far). `len` - // is the total number of reptitions we should generate. + // is the total number of reptitions we should generate. repeats.push((0, len)); // The first time we encounter the sequence we push it to the stack. It From 0db087e6840cc865bcf8be09ff940f2ac13341ac Mon Sep 17 00:00:00 2001 From: David Wood Date: Sat, 4 May 2019 01:15:26 +0100 Subject: [PATCH 162/212] Add uninhabitedness tests w/ `#[non_exhaustive]`. This commit adds tests checking that uninhabited non-exhaustive types are considered inhabited when used in another crate. --- .../auxiliary/uninhabited.rs | 25 +++++++ .../ui/rfc-2008-non-exhaustive/uninhabited.rs | 59 +++++++++++++++ .../uninhabited_same_crate.rs | 71 +++++++++++++++++++ .../uninhabited_same_crate.stderr | 38 ++++++++++ 4 files changed, 193 insertions(+) create mode 100644 src/test/ui/rfc-2008-non-exhaustive/auxiliary/uninhabited.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.stderr diff --git a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/uninhabited.rs b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/uninhabited.rs new file mode 100644 index 0000000000000..a4b936e376d82 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/uninhabited.rs @@ -0,0 +1,25 @@ +#![crate_type = "rlib"] +#![feature(never_type)] +#![feature(non_exhaustive)] + +#[non_exhaustive] +pub enum UninhabitedEnum { +} + +#[non_exhaustive] +pub struct UninhabitedStruct { + _priv: !, +} + +#[non_exhaustive] +pub struct UninhabitedTupleStruct(!); + +pub enum UninhabitedVariants { + #[non_exhaustive] Tuple(!), + #[non_exhaustive] Struct { x: ! } +} + +pub enum PartiallyInhabitedVariants { + Tuple(u8), + #[non_exhaustive] Struct { x: ! } +} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited.rs new file mode 100644 index 0000000000000..97061310d19e2 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited.rs @@ -0,0 +1,59 @@ +// aux-build:uninhabited.rs +// compile-pass +#![deny(unreachable_patterns)] +#![feature(exhaustive_patterns)] + +extern crate uninhabited; + +use uninhabited::{ + PartiallyInhabitedVariants, + UninhabitedEnum, + UninhabitedStruct, + UninhabitedTupleStruct, + UninhabitedVariants, +}; + +fn uninhabited_enum() -> Option { + None +} + +fn uninhabited_variant() -> Option { + None +} + +fn partially_inhabited_variant() -> PartiallyInhabitedVariants { + PartiallyInhabitedVariants::Tuple(3) +} + +fn uninhabited_struct() -> Option { + None +} + +fn uninhabited_tuple_struct() -> Option { + None +} + +// This test checks that non-exhaustive types that would normally be considered uninhabited within +// the defining crate are not considered uninhabited from extern crates. + +fn main() { + match uninhabited_enum() { + Some(_x) => (), // This line would normally error. + None => (), + } + + match uninhabited_variant() { + Some(_x) => (), // This line would normally error. + None => (), + } + + // This line would normally error. + while let PartiallyInhabitedVariants::Struct { x, .. } = partially_inhabited_variant() { + } + + while let Some(_x) = uninhabited_struct() { // This line would normally error. + } + + while let Some(_x) = uninhabited_tuple_struct() { // This line would normally error. + } +} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.rs new file mode 100644 index 0000000000000..302a35cab5f90 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.rs @@ -0,0 +1,71 @@ +#![deny(unreachable_patterns)] +#![feature(exhaustive_patterns)] +#![feature(never_type)] +#![feature(non_exhaustive)] + +#[non_exhaustive] +pub enum UninhabitedEnum { +} + +#[non_exhaustive] +pub struct UninhabitedTupleStruct(!); + +#[non_exhaustive] +pub struct UninhabitedStruct { + _priv: !, +} + +pub enum UninhabitedVariants { + #[non_exhaustive] Tuple(!), + #[non_exhaustive] Struct { x: ! } +} + +pub enum PartiallyInhabitedVariants { + Tuple(u8), + #[non_exhaustive] Struct { x: ! } +} + +fn uninhabited_enum() -> Option { + None +} + +fn uninhabited_variant() -> Option { + None +} + +fn partially_inhabited_variant() -> PartiallyInhabitedVariants { + PartiallyInhabitedVariants::Tuple(3) +} + +fn uninhabited_struct() -> Option { + None +} + +fn uninhabited_tuple_struct() -> Option { + None +} + +// This test checks that non-exhaustive types that would normally be considered uninhabited within +// the defining crate are still considered uninhabited. + +fn main() { + match uninhabited_enum() { + Some(_x) => (), //~ ERROR unreachable pattern + None => (), + } + + match uninhabited_variant() { + Some(_x) => (), //~ ERROR unreachable pattern + None => (), + } + + while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() { + //~^ ERROR unreachable pattern + } + + while let Some(_x) = uninhabited_struct() { //~ ERROR unreachable pattern + } + + while let Some(_x) = uninhabited_tuple_struct() { //~ ERROR unreachable pattern + } +} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.stderr new file mode 100644 index 0000000000000..942f004c3cfd6 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.stderr @@ -0,0 +1,38 @@ +error: unreachable pattern + --> $DIR/uninhabited_same_crate.rs:53:9 + | +LL | Some(_x) => (), + | ^^^^^^^^ + | +note: lint level defined here + --> $DIR/uninhabited_same_crate.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/uninhabited_same_crate.rs:58:9 + | +LL | Some(_x) => (), + | ^^^^^^^^ + +error: unreachable pattern + --> $DIR/uninhabited_same_crate.rs:62:15 + | +LL | while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/uninhabited_same_crate.rs:66:15 + | +LL | while let Some(_x) = uninhabited_struct() { + | ^^^^^^^^ + +error: unreachable pattern + --> $DIR/uninhabited_same_crate.rs:69:15 + | +LL | while let Some(_x) = uninhabited_tuple_struct() { + | ^^^^^^^^ + +error: aborting due to 5 previous errors + From 0d034a2e4dd9418fa41aba4ebdd1ebc31a08c9e9 Mon Sep 17 00:00:00 2001 From: David Wood Date: Sat, 4 May 2019 01:17:26 +0100 Subject: [PATCH 163/212] Fix inhabitedness of non-exhaustive variants. This commit ensures that non-exhaustive variants are considered inhabited when used in extern crates. --- src/librustc/ty/inhabitedness/mod.rs | 11 +++++++--- src/librustc_mir/hair/pattern/_match.rs | 27 ++++++++++++++++++++---- src/test/ui/pattern/const-pat-ice.stderr | 2 +- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs index 197d3325f51cf..2fc07fb20bf16 100644 --- a/src/librustc/ty/inhabitedness/mod.rs +++ b/src/librustc/ty/inhabitedness/mod.rs @@ -134,9 +134,14 @@ impl<'a, 'gcx, 'tcx> VariantDef { AdtKind::Enum => true, AdtKind::Struct => false, }; - DefIdForest::union(tcx, self.fields.iter().map(|f| { - f.uninhabited_from(tcx, substs, is_enum) - })) + // Non-exhaustive variants from other crates are always considered inhabited. + if self.is_field_list_non_exhaustive() && !self.def_id.is_local() { + DefIdForest::empty() + } else { + DefIdForest::union(tcx, self.fields.iter().map(|f| { + f.uninhabited_from(tcx, substs, is_enum) + })) + } } } diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index edd36abc0b8a4..fd4416fc2b763 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -388,6 +388,18 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> { } } + fn is_non_exhaustive_variant<'p>(&self, pattern: &'p Pattern<'tcx>) -> bool + where 'a: 'p + { + match *pattern.kind { + PatternKind::Variant { adt_def, variant_index, .. } => { + let ref variant = adt_def.variants[variant_index]; + variant.is_field_list_non_exhaustive() + } + _ => false, + } + } + fn is_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool { match ty.sty { ty::Adt(adt_def, ..) => adt_def.is_variant_list_non_exhaustive(), @@ -1097,10 +1109,17 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, debug!("is_useful_expand_first_col: pcx={:#?}, expanding {:#?}", pcx, v[0]); if let Some(constructors) = pat_constructors(cx, v[0], pcx) { - debug!("is_useful - expanding constructors: {:#?}", constructors); - split_grouped_constructors(cx.tcx, constructors, matrix, pcx.ty).into_iter().map(|c| - is_useful_specialized(cx, matrix, v, c, pcx.ty, witness) - ).find(|result| result.is_useful()).unwrap_or(NotUseful) + let is_declared_nonexhaustive = cx.is_non_exhaustive_variant(v[0]) && !cx.is_local(pcx.ty); + debug!("is_useful - expanding constructors: {:#?}, is_declared_nonexhaustive: {:?}", + constructors, is_declared_nonexhaustive); + + if is_declared_nonexhaustive { + Useful + } else { + split_grouped_constructors(cx.tcx, constructors, matrix, pcx.ty).into_iter().map(|c| + is_useful_specialized(cx, matrix, v, c, pcx.ty, witness) + ).find(|result| result.is_useful()).unwrap_or(NotUseful) + } } else { debug!("is_useful - expanding wildcard"); diff --git a/src/test/ui/pattern/const-pat-ice.stderr b/src/test/ui/pattern/const-pat-ice.stderr index 261e95229a76e..260c2e04d74f7 100644 --- a/src/test/ui/pattern/const-pat-ice.stderr +++ b/src/test/ui/pattern/const-pat-ice.stderr @@ -1,4 +1,4 @@ -thread 'rustc' panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())', src/librustc_mir/hair/pattern/_match.rs:1071:5 +thread 'rustc' panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())', src/librustc_mir/hair/pattern/_match.rs:1083:5 note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace. error: internal compiler error: unexpected panic From 8838b9130e2f6551077f432dddd5a8077ae4d2e1 Mon Sep 17 00:00:00 2001 From: David Wood Date: Sat, 4 May 2019 11:03:06 +0100 Subject: [PATCH 164/212] Fix uninhabitedness of non-exhaustive enums. This commit ensures that non-exhaustive enums are considered inhabited when used in extern crates. --- src/librustc/ty/inhabitedness/mod.rs | 11 ++- src/librustc_mir/hair/pattern/check_match.rs | 6 +- .../ui/rfc-2008-non-exhaustive/uninhabited.rs | 55 +++++--------- .../uninhabited.stderr | 47 ++++++++++++ .../uninhabited_match.rs | 19 +++++ .../uninhabited_match.stderr | 11 +++ .../uninhabited_match_same_crate.rs | 18 +++++ ...nhabited_match_with_exhaustive_patterns.rs | 22 ++++++ ...ited_match_with_exhaustive_patterns.stderr | 11 +++ ...tch_with_exhaustive_patterns_same_crate.rs | 21 ++++++ .../uninhabited_patterns.rs | 59 +++++++++++++++ .../uninhabited_patterns_same_crate.rs | 71 +++++++++++++++++++ .../uninhabited_patterns_same_crate.stderr | 38 ++++++++++ .../uninhabited_same_crate.rs | 55 ++++---------- .../uninhabited_same_crate.stderr | 63 +++++++++------- 15 files changed, 398 insertions(+), 109 deletions(-) create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited.stderr create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited_match.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited_match.stderr create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_same_crate.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns.stderr create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns_same_crate.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns_same_crate.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns_same_crate.stderr diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs index 2fc07fb20bf16..be1d973c2cdd5 100644 --- a/src/librustc/ty/inhabitedness/mod.rs +++ b/src/librustc/ty/inhabitedness/mod.rs @@ -113,9 +113,14 @@ impl<'a, 'gcx, 'tcx> AdtDef { tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: SubstsRef<'tcx>) -> DefIdForest { - DefIdForest::intersection(tcx, self.variants.iter().map(|v| { - v.uninhabited_from(tcx, substs, self.adt_kind()) - })) + // Non-exhaustive ADTs from other crates are always considered inhabited. + if self.is_variant_list_non_exhaustive() && !self.did.is_local() { + DefIdForest::empty() + } else { + DefIdForest::intersection(tcx, self.variants.iter().map(|v| { + v.uninhabited_from(tcx, substs, self.adt_kind()) + })) + } } } diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index 1a7266859ad9f..8c7155e1df351 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -208,7 +208,11 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { .map(|variant| variant.ident) .collect(); } - def.variants.is_empty() + + let is_non_exhaustive_and_non_local = + def.is_variant_list_non_exhaustive() && !def.did.is_local(); + + !(is_non_exhaustive_and_non_local) && def.variants.is_empty() }, _ => false } diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited.rs index 97061310d19e2..80b9dc4c1c338 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited.rs @@ -1,59 +1,38 @@ // aux-build:uninhabited.rs -// compile-pass -#![deny(unreachable_patterns)] -#![feature(exhaustive_patterns)] +#![feature(never_type)] extern crate uninhabited; use uninhabited::{ - PartiallyInhabitedVariants, UninhabitedEnum, UninhabitedStruct, UninhabitedTupleStruct, UninhabitedVariants, }; -fn uninhabited_enum() -> Option { - None -} +// This test checks that uninhabited non-exhaustive types cannot coerce to any type, as the never +// type can. -fn uninhabited_variant() -> Option { - None -} +struct A; -fn partially_inhabited_variant() -> PartiallyInhabitedVariants { - PartiallyInhabitedVariants::Tuple(3) +fn can_coerce_never_type_to_anything(x: !) -> A { + x } -fn uninhabited_struct() -> Option { - None +fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A { + x //~ ERROR mismatched types } -fn uninhabited_tuple_struct() -> Option { - None +fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { + x //~ ERROR mismatched types } -// This test checks that non-exhaustive types that would normally be considered uninhabited within -// the defining crate are not considered uninhabited from extern crates. - -fn main() { - match uninhabited_enum() { - Some(_x) => (), // This line would normally error. - None => (), - } - - match uninhabited_variant() { - Some(_x) => (), // This line would normally error. - None => (), - } - - // This line would normally error. - while let PartiallyInhabitedVariants::Struct { x, .. } = partially_inhabited_variant() { - } - - while let Some(_x) = uninhabited_struct() { // This line would normally error. - } +fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A { + x //~ ERROR mismatched types +} - while let Some(_x) = uninhabited_tuple_struct() { // This line would normally error. - } +fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A { + x //~ ERROR mismatched types } + +fn main() {} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited.stderr new file mode 100644 index 0000000000000..490a6c101179c --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited.stderr @@ -0,0 +1,47 @@ +error[E0308]: mismatched types + --> $DIR/uninhabited.rs:23:5 + | +LL | fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A { + | - expected `A` because of return type +LL | x + | ^ expected struct `A`, found enum `uninhabited::UninhabitedEnum` + | + = note: expected type `A` + found type `uninhabited::UninhabitedEnum` + +error[E0308]: mismatched types + --> $DIR/uninhabited.rs:27:5 + | +LL | fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { + | - expected `A` because of return type +LL | x + | ^ expected struct `A`, found struct `uninhabited::UninhabitedTupleStruct` + | + = note: expected type `A` + found type `uninhabited::UninhabitedTupleStruct` + +error[E0308]: mismatched types + --> $DIR/uninhabited.rs:31:5 + | +LL | fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A { + | - expected `A` because of return type +LL | x + | ^ expected struct `A`, found struct `uninhabited::UninhabitedStruct` + | + = note: expected type `A` + found type `uninhabited::UninhabitedStruct` + +error[E0308]: mismatched types + --> $DIR/uninhabited.rs:35:5 + | +LL | fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A { + | - expected `A` because of return type +LL | x + | ^ expected struct `A`, found enum `uninhabited::UninhabitedVariants` + | + = note: expected type `A` + found type `uninhabited::UninhabitedVariants` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match.rs new file mode 100644 index 0000000000000..0166b2e46cbf5 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match.rs @@ -0,0 +1,19 @@ +// aux-build:uninhabited.rs +#![feature(never_type)] + +extern crate uninhabited; + +use uninhabited::{ + UninhabitedEnum, +}; + +struct A; + +// This test checks that an empty match on a non-exhaustive uninhabited type from an extern crate +// will not compile. + +fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn main() {} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match.stderr new file mode 100644 index 0000000000000..3000e1b093068 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match.stderr @@ -0,0 +1,11 @@ +error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedEnum` is non-empty + --> $DIR/uninhabited_match.rs:16:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_same_crate.rs new file mode 100644 index 0000000000000..d8b1c3810f338 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_same_crate.rs @@ -0,0 +1,18 @@ +// compile-pass +#![feature(never_type)] +#![feature(non_exhaustive)] + +#[non_exhaustive] +pub enum UninhabitedEnum { +} + +struct A; + +// This test checks that an empty match on a non-exhaustive uninhabited type from the defining crate +// will compile. + +fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A { + match x {} +} + +fn main() {} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns.rs new file mode 100644 index 0000000000000..d82010158ccc3 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns.rs @@ -0,0 +1,22 @@ +// aux-build:uninhabited.rs +#![deny(unreachable_patterns)] +#![feature(exhaustive_patterns)] +#![feature(never_type)] + +extern crate uninhabited; + +use uninhabited::{ + UninhabitedEnum, +}; + +struct A; + +// This test checks that an empty match on a non-exhaustive uninhabited type from an extern crate +// will not compile. In particular, this enables the `exhaustive_patterns` feature as this can +// change the branch used in the compiler to determine this. + +fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn main() {} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns.stderr new file mode 100644 index 0000000000000..73d9e689b55fc --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns.stderr @@ -0,0 +1,11 @@ +error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedEnum` is non-empty + --> $DIR/uninhabited_match_with_exhaustive_patterns.rs:19:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns_same_crate.rs new file mode 100644 index 0000000000000..da814a70a75ca --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns_same_crate.rs @@ -0,0 +1,21 @@ +// compile-pass +#![deny(unreachable_patterns)] +#![feature(exhaustive_patterns)] +#![feature(never_type)] +#![feature(non_exhaustive)] + +#[non_exhaustive] +pub enum UninhabitedEnum { +} + +struct A; + +// This test checks that an empty match on a non-exhaustive uninhabited type from the defining crate +// will compile. In particular, this enables the `exhaustive_patterns` feature as this can +// change the branch used in the compiler to determine this. + +fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A { + match x {} +} + +fn main() {} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns.rs new file mode 100644 index 0000000000000..97061310d19e2 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns.rs @@ -0,0 +1,59 @@ +// aux-build:uninhabited.rs +// compile-pass +#![deny(unreachable_patterns)] +#![feature(exhaustive_patterns)] + +extern crate uninhabited; + +use uninhabited::{ + PartiallyInhabitedVariants, + UninhabitedEnum, + UninhabitedStruct, + UninhabitedTupleStruct, + UninhabitedVariants, +}; + +fn uninhabited_enum() -> Option { + None +} + +fn uninhabited_variant() -> Option { + None +} + +fn partially_inhabited_variant() -> PartiallyInhabitedVariants { + PartiallyInhabitedVariants::Tuple(3) +} + +fn uninhabited_struct() -> Option { + None +} + +fn uninhabited_tuple_struct() -> Option { + None +} + +// This test checks that non-exhaustive types that would normally be considered uninhabited within +// the defining crate are not considered uninhabited from extern crates. + +fn main() { + match uninhabited_enum() { + Some(_x) => (), // This line would normally error. + None => (), + } + + match uninhabited_variant() { + Some(_x) => (), // This line would normally error. + None => (), + } + + // This line would normally error. + while let PartiallyInhabitedVariants::Struct { x, .. } = partially_inhabited_variant() { + } + + while let Some(_x) = uninhabited_struct() { // This line would normally error. + } + + while let Some(_x) = uninhabited_tuple_struct() { // This line would normally error. + } +} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns_same_crate.rs new file mode 100644 index 0000000000000..302a35cab5f90 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns_same_crate.rs @@ -0,0 +1,71 @@ +#![deny(unreachable_patterns)] +#![feature(exhaustive_patterns)] +#![feature(never_type)] +#![feature(non_exhaustive)] + +#[non_exhaustive] +pub enum UninhabitedEnum { +} + +#[non_exhaustive] +pub struct UninhabitedTupleStruct(!); + +#[non_exhaustive] +pub struct UninhabitedStruct { + _priv: !, +} + +pub enum UninhabitedVariants { + #[non_exhaustive] Tuple(!), + #[non_exhaustive] Struct { x: ! } +} + +pub enum PartiallyInhabitedVariants { + Tuple(u8), + #[non_exhaustive] Struct { x: ! } +} + +fn uninhabited_enum() -> Option { + None +} + +fn uninhabited_variant() -> Option { + None +} + +fn partially_inhabited_variant() -> PartiallyInhabitedVariants { + PartiallyInhabitedVariants::Tuple(3) +} + +fn uninhabited_struct() -> Option { + None +} + +fn uninhabited_tuple_struct() -> Option { + None +} + +// This test checks that non-exhaustive types that would normally be considered uninhabited within +// the defining crate are still considered uninhabited. + +fn main() { + match uninhabited_enum() { + Some(_x) => (), //~ ERROR unreachable pattern + None => (), + } + + match uninhabited_variant() { + Some(_x) => (), //~ ERROR unreachable pattern + None => (), + } + + while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() { + //~^ ERROR unreachable pattern + } + + while let Some(_x) = uninhabited_struct() { //~ ERROR unreachable pattern + } + + while let Some(_x) = uninhabited_tuple_struct() { //~ ERROR unreachable pattern + } +} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns_same_crate.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns_same_crate.stderr new file mode 100644 index 0000000000000..8e995632b2ff7 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns_same_crate.stderr @@ -0,0 +1,38 @@ +error: unreachable pattern + --> $DIR/uninhabited_patterns_same_crate.rs:53:9 + | +LL | Some(_x) => (), + | ^^^^^^^^ + | +note: lint level defined here + --> $DIR/uninhabited_patterns_same_crate.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/uninhabited_patterns_same_crate.rs:58:9 + | +LL | Some(_x) => (), + | ^^^^^^^^ + +error: unreachable pattern + --> $DIR/uninhabited_patterns_same_crate.rs:62:15 + | +LL | while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/uninhabited_patterns_same_crate.rs:66:15 + | +LL | while let Some(_x) = uninhabited_struct() { + | ^^^^^^^^ + +error: unreachable pattern + --> $DIR/uninhabited_patterns_same_crate.rs:69:15 + | +LL | while let Some(_x) = uninhabited_tuple_struct() { + | ^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.rs index 302a35cab5f90..803a542f8aa4b 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.rs @@ -1,5 +1,3 @@ -#![deny(unreachable_patterns)] -#![feature(exhaustive_patterns)] #![feature(never_type)] #![feature(non_exhaustive)] @@ -20,52 +18,29 @@ pub enum UninhabitedVariants { #[non_exhaustive] Struct { x: ! } } -pub enum PartiallyInhabitedVariants { - Tuple(u8), - #[non_exhaustive] Struct { x: ! } -} +struct A; -fn uninhabited_enum() -> Option { - None -} +// This test checks that uninhabited non-exhaustive types defined in the same crate cannot coerce +// to any type, as the never type can. -fn uninhabited_variant() -> Option { - None +fn can_coerce_never_type_to_anything(x: !) -> A { + x } -fn partially_inhabited_variant() -> PartiallyInhabitedVariants { - PartiallyInhabitedVariants::Tuple(3) +fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A { + x //~ ERROR mismatched types } -fn uninhabited_struct() -> Option { - None +fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { + x //~ ERROR mismatched types } -fn uninhabited_tuple_struct() -> Option { - None +fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A { + x //~ ERROR mismatched types } -// This test checks that non-exhaustive types that would normally be considered uninhabited within -// the defining crate are still considered uninhabited. - -fn main() { - match uninhabited_enum() { - Some(_x) => (), //~ ERROR unreachable pattern - None => (), - } - - match uninhabited_variant() { - Some(_x) => (), //~ ERROR unreachable pattern - None => (), - } - - while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() { - //~^ ERROR unreachable pattern - } - - while let Some(_x) = uninhabited_struct() { //~ ERROR unreachable pattern - } - - while let Some(_x) = uninhabited_tuple_struct() { //~ ERROR unreachable pattern - } +fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A { + x //~ ERROR mismatched types } + +fn main() {} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.stderr index 942f004c3cfd6..ea79e7105d546 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.stderr @@ -1,38 +1,47 @@ -error: unreachable pattern - --> $DIR/uninhabited_same_crate.rs:53:9 +error[E0308]: mismatched types + --> $DIR/uninhabited_same_crate.rs:31:5 | -LL | Some(_x) => (), - | ^^^^^^^^ +LL | fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A { + | - expected `A` because of return type +LL | x + | ^ expected struct `A`, found enum `UninhabitedEnum` | -note: lint level defined here - --> $DIR/uninhabited_same_crate.rs:1:9 - | -LL | #![deny(unreachable_patterns)] - | ^^^^^^^^^^^^^^^^^^^^ + = note: expected type `A` + found type `UninhabitedEnum` -error: unreachable pattern - --> $DIR/uninhabited_same_crate.rs:58:9 +error[E0308]: mismatched types + --> $DIR/uninhabited_same_crate.rs:35:5 | -LL | Some(_x) => (), - | ^^^^^^^^ - -error: unreachable pattern - --> $DIR/uninhabited_same_crate.rs:62:15 +LL | fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { + | - expected `A` because of return type +LL | x + | ^ expected struct `A`, found struct `UninhabitedTupleStruct` | -LL | while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: expected type `A` + found type `UninhabitedTupleStruct` -error: unreachable pattern - --> $DIR/uninhabited_same_crate.rs:66:15 +error[E0308]: mismatched types + --> $DIR/uninhabited_same_crate.rs:39:5 | -LL | while let Some(_x) = uninhabited_struct() { - | ^^^^^^^^ +LL | fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A { + | - expected `A` because of return type +LL | x + | ^ expected struct `A`, found struct `UninhabitedStruct` + | + = note: expected type `A` + found type `UninhabitedStruct` -error: unreachable pattern - --> $DIR/uninhabited_same_crate.rs:69:15 +error[E0308]: mismatched types + --> $DIR/uninhabited_same_crate.rs:43:5 + | +LL | fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A { + | - expected `A` because of return type +LL | x + | ^ expected struct `A`, found enum `UninhabitedVariants` | -LL | while let Some(_x) = uninhabited_tuple_struct() { - | ^^^^^^^^ + = note: expected type `A` + found type `UninhabitedVariants` -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0308`. From 214f977fee19aeeb4f5ab4df8e0b5d37e611cb48 Mon Sep 17 00:00:00 2001 From: David Wood Date: Sat, 4 May 2019 11:08:57 +0100 Subject: [PATCH 165/212] Move uninhabited tests into subdirectory. This commit just tries to tidy up a little. --- .../{ => uninhabited}/auxiliary/uninhabited.rs | 0 .../{uninhabited.rs => uninhabited/coercions.rs} | 0 .../coercions.stderr} | 8 ++++---- .../coercions_same_crate.rs} | 0 .../coercions_same_crate.stderr} | 8 ++++---- .../{uninhabited_match.rs => uninhabited/match.rs} | 0 .../match.stderr} | 2 +- .../match_same_crate.rs} | 0 .../match_with_exhaustive_patterns.rs} | 0 .../match_with_exhaustive_patterns.stderr} | 2 +- .../match_with_exhaustive_patterns_same_crate.rs} | 0 .../patterns.rs} | 0 .../patterns_same_crate.rs} | 0 .../patterns_same_crate.stderr} | 12 ++++++------ 14 files changed, 16 insertions(+), 16 deletions(-) rename src/test/ui/rfc-2008-non-exhaustive/{ => uninhabited}/auxiliary/uninhabited.rs (100%) rename src/test/ui/rfc-2008-non-exhaustive/{uninhabited.rs => uninhabited/coercions.rs} (100%) rename src/test/ui/rfc-2008-non-exhaustive/{uninhabited.stderr => uninhabited/coercions.stderr} (93%) rename src/test/ui/rfc-2008-non-exhaustive/{uninhabited_same_crate.rs => uninhabited/coercions_same_crate.rs} (100%) rename src/test/ui/rfc-2008-non-exhaustive/{uninhabited_same_crate.stderr => uninhabited/coercions_same_crate.stderr} (90%) rename src/test/ui/rfc-2008-non-exhaustive/{uninhabited_match.rs => uninhabited/match.rs} (100%) rename src/test/ui/rfc-2008-non-exhaustive/{uninhabited_match.stderr => uninhabited/match.stderr} (90%) rename src/test/ui/rfc-2008-non-exhaustive/{uninhabited_match_same_crate.rs => uninhabited/match_same_crate.rs} (100%) rename src/test/ui/rfc-2008-non-exhaustive/{uninhabited_match_with_exhaustive_patterns.rs => uninhabited/match_with_exhaustive_patterns.rs} (100%) rename src/test/ui/rfc-2008-non-exhaustive/{uninhabited_match_with_exhaustive_patterns.stderr => uninhabited/match_with_exhaustive_patterns.stderr} (84%) rename src/test/ui/rfc-2008-non-exhaustive/{uninhabited_match_with_exhaustive_patterns_same_crate.rs => uninhabited/match_with_exhaustive_patterns_same_crate.rs} (100%) rename src/test/ui/rfc-2008-non-exhaustive/{uninhabited_patterns.rs => uninhabited/patterns.rs} (100%) rename src/test/ui/rfc-2008-non-exhaustive/{uninhabited_patterns_same_crate.rs => uninhabited/patterns_same_crate.rs} (100%) rename src/test/ui/rfc-2008-non-exhaustive/{uninhabited_patterns_same_crate.stderr => uninhabited/patterns_same_crate.stderr} (70%) diff --git a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/uninhabited.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs similarity index 100% rename from src/test/ui/rfc-2008-non-exhaustive/auxiliary/uninhabited.rs rename to src/test/ui/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/coercions.rs similarity index 100% rename from src/test/ui/rfc-2008-non-exhaustive/uninhabited.rs rename to src/test/ui/rfc-2008-non-exhaustive/uninhabited/coercions.rs diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/coercions.stderr similarity index 93% rename from src/test/ui/rfc-2008-non-exhaustive/uninhabited.stderr rename to src/test/ui/rfc-2008-non-exhaustive/uninhabited/coercions.stderr index 490a6c101179c..d05ee1d39ec35 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/coercions.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/uninhabited.rs:23:5 + --> $DIR/coercions.rs:23:5 | LL | fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A { | - expected `A` because of return type @@ -10,7 +10,7 @@ LL | x found type `uninhabited::UninhabitedEnum` error[E0308]: mismatched types - --> $DIR/uninhabited.rs:27:5 + --> $DIR/coercions.rs:27:5 | LL | fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { | - expected `A` because of return type @@ -21,7 +21,7 @@ LL | x found type `uninhabited::UninhabitedTupleStruct` error[E0308]: mismatched types - --> $DIR/uninhabited.rs:31:5 + --> $DIR/coercions.rs:31:5 | LL | fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A { | - expected `A` because of return type @@ -32,7 +32,7 @@ LL | x found type `uninhabited::UninhabitedStruct` error[E0308]: mismatched types - --> $DIR/uninhabited.rs:35:5 + --> $DIR/coercions.rs:35:5 | LL | fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A { | - expected `A` because of return type diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.rs similarity index 100% rename from src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.rs rename to src/test/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.rs diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.stderr similarity index 90% rename from src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.stderr rename to src/test/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.stderr index ea79e7105d546..8f6b709bb1f34 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/uninhabited_same_crate.rs:31:5 + --> $DIR/coercions_same_crate.rs:31:5 | LL | fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A { | - expected `A` because of return type @@ -10,7 +10,7 @@ LL | x found type `UninhabitedEnum` error[E0308]: mismatched types - --> $DIR/uninhabited_same_crate.rs:35:5 + --> $DIR/coercions_same_crate.rs:35:5 | LL | fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { | - expected `A` because of return type @@ -21,7 +21,7 @@ LL | x found type `UninhabitedTupleStruct` error[E0308]: mismatched types - --> $DIR/uninhabited_same_crate.rs:39:5 + --> $DIR/coercions_same_crate.rs:39:5 | LL | fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A { | - expected `A` because of return type @@ -32,7 +32,7 @@ LL | x found type `UninhabitedStruct` error[E0308]: mismatched types - --> $DIR/uninhabited_same_crate.rs:43:5 + --> $DIR/coercions_same_crate.rs:43:5 | LL | fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A { | - expected `A` because of return type diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.rs similarity index 100% rename from src/test/ui/rfc-2008-non-exhaustive/uninhabited_match.rs rename to src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.rs diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr similarity index 90% rename from src/test/ui/rfc-2008-non-exhaustive/uninhabited_match.stderr rename to src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr index 3000e1b093068..356c6fba32d51 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedEnum` is non-empty - --> $DIR/uninhabited_match.rs:16:11 + --> $DIR/match.rs:16:11 | LL | match x {} | ^ diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs similarity index 100% rename from src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_same_crate.rs rename to src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs similarity index 100% rename from src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns.rs rename to src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr similarity index 84% rename from src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns.stderr rename to src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr index 73d9e689b55fc..ec2e9d0995b1f 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedEnum` is non-empty - --> $DIR/uninhabited_match_with_exhaustive_patterns.rs:19:11 + --> $DIR/match_with_exhaustive_patterns.rs:19:11 | LL | match x {} | ^ diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs similarity index 100% rename from src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns_same_crate.rs rename to src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/patterns.rs similarity index 100% rename from src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns.rs rename to src/test/ui/rfc-2008-non-exhaustive/uninhabited/patterns.rs diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs similarity index 100% rename from src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns_same_crate.rs rename to src/test/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns_same_crate.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr similarity index 70% rename from src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns_same_crate.stderr rename to src/test/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr index 8e995632b2ff7..72f37d9a60ba8 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns_same_crate.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr @@ -1,35 +1,35 @@ error: unreachable pattern - --> $DIR/uninhabited_patterns_same_crate.rs:53:9 + --> $DIR/patterns_same_crate.rs:53:9 | LL | Some(_x) => (), | ^^^^^^^^ | note: lint level defined here - --> $DIR/uninhabited_patterns_same_crate.rs:1:9 + --> $DIR/patterns_same_crate.rs:1:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/uninhabited_patterns_same_crate.rs:58:9 + --> $DIR/patterns_same_crate.rs:58:9 | LL | Some(_x) => (), | ^^^^^^^^ error: unreachable pattern - --> $DIR/uninhabited_patterns_same_crate.rs:62:15 + --> $DIR/patterns_same_crate.rs:62:15 | LL | while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/uninhabited_patterns_same_crate.rs:66:15 + --> $DIR/patterns_same_crate.rs:66:15 | LL | while let Some(_x) = uninhabited_struct() { | ^^^^^^^^ error: unreachable pattern - --> $DIR/uninhabited_patterns_same_crate.rs:69:15 + --> $DIR/patterns_same_crate.rs:69:15 | LL | while let Some(_x) = uninhabited_tuple_struct() { | ^^^^^^^^ From 1f0fb0391caf232dacabdf73fbbb84f2452b25c1 Mon Sep 17 00:00:00 2001 From: David Wood Date: Sat, 4 May 2019 12:07:04 +0100 Subject: [PATCH 166/212] Add a bunch more tests. --- .../uninhabited/auxiliary/uninhabited.rs | 8 +++ .../uninhabited/indirect_match.rs | 36 +++++++++++ .../uninhabited/indirect_match.stderr | 35 +++++++++++ .../uninhabited/indirect_match_same_crate.rs | 52 ++++++++++++++++ .../indirect_match_same_crate.stderr | 59 +++++++++++++++++++ ...indirect_match_with_exhaustive_patterns.rs | 40 +++++++++++++ ...rect_match_with_exhaustive_patterns.stderr | 35 +++++++++++ ...tch_with_exhaustive_patterns_same_crate.rs | 58 ++++++++++++++++++ .../uninhabited/match.rs | 15 +++++ .../uninhabited/match.stderr | 28 ++++++++- .../uninhabited/match_same_crate.rs | 26 +++++++- .../uninhabited/match_same_crate.stderr | 49 +++++++++++++++ .../match_with_exhaustive_patterns.rs | 15 +++++ .../match_with_exhaustive_patterns.stderr | 28 ++++++++- ...tch_with_exhaustive_patterns_same_crate.rs | 27 +++++++++ 15 files changed, 506 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns_same_crate.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs index a4b936e376d82..8cb9a8cf1f613 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs @@ -23,3 +23,11 @@ pub enum PartiallyInhabitedVariants { Tuple(u8), #[non_exhaustive] Struct { x: ! } } + +pub struct IndirectUninhabitedEnum(UninhabitedEnum); + +pub struct IndirectUninhabitedStruct(UninhabitedStruct); + +pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct); + +pub struct IndirectUninhabitedVariants(UninhabitedVariants); diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.rs new file mode 100644 index 0000000000000..98a7fdbc5049a --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.rs @@ -0,0 +1,36 @@ +// aux-build:uninhabited.rs +#![feature(never_type)] + +extern crate uninhabited; + +use uninhabited::{ + IndirectUninhabitedEnum, + IndirectUninhabitedStruct, + IndirectUninhabitedTupleStruct, + IndirectUninhabitedVariants, +}; + +struct A; + +// This test checks that an empty match on a non-exhaustive uninhabited type through a level of +// indirection from an extern crate will not compile. + +fn cannot_empty_match_on_empty_enum_to_anything(x: IndirectUninhabitedEnum) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_empty_struct_to_anything(x: IndirectUninhabitedStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: IndirectUninhabitedTupleStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything( + x: IndirectUninhabitedVariants, +) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn main() {} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr new file mode 100644 index 0000000000000..af82022e1da99 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr @@ -0,0 +1,35 @@ +error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedEnum` of type `uninhabited::IndirectUninhabitedEnum` is not handled + --> $DIR/indirect_match.rs:19:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedStruct` of type `uninhabited::IndirectUninhabitedStruct` is not handled + --> $DIR/indirect_match.rs:23:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedTupleStruct` of type `uninhabited::IndirectUninhabitedTupleStruct` is not handled + --> $DIR/indirect_match.rs:27:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedVariants` of type `uninhabited::IndirectUninhabitedVariants` is not handled + --> $DIR/indirect_match.rs:33:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.rs new file mode 100644 index 0000000000000..3c8d495e12cb6 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.rs @@ -0,0 +1,52 @@ +#![feature(never_type)] +#![feature(non_exhaustive)] + +#[non_exhaustive] +pub enum UninhabitedEnum { +} + +#[non_exhaustive] +pub struct UninhabitedStruct { + _priv: !, +} + +#[non_exhaustive] +pub struct UninhabitedTupleStruct(!); + +pub enum UninhabitedVariants { + #[non_exhaustive] Tuple(!), + #[non_exhaustive] Struct { x: ! } +} + +pub struct IndirectUninhabitedEnum(UninhabitedEnum); + +pub struct IndirectUninhabitedStruct(UninhabitedStruct); + +pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct); + +pub struct IndirectUninhabitedVariants(UninhabitedVariants); + +struct A; + +// This test checks that an empty match on a non-exhaustive uninhabited type through a level of +// indirection from the defining crate will not compile without `#![feature(exhaustive_patterns)]`. + +fn cannot_empty_match_on_empty_enum_to_anything(x: IndirectUninhabitedEnum) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_empty_struct_to_anything(x: IndirectUninhabitedStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: IndirectUninhabitedTupleStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything( + x: IndirectUninhabitedVariants, +) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn main() {} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr new file mode 100644 index 0000000000000..27b120792d6d1 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr @@ -0,0 +1,59 @@ +error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedEnum` of type `IndirectUninhabitedEnum` is not handled + --> $DIR/indirect_match_same_crate.rs:35:11 + | +LL | pub struct IndirectUninhabitedEnum(UninhabitedEnum); + | ---------------------------------------------------- + | | | + | | variant not covered + | `IndirectUninhabitedEnum` defined here +... +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedStruct` of type `IndirectUninhabitedStruct` is not handled + --> $DIR/indirect_match_same_crate.rs:39:11 + | +LL | pub struct IndirectUninhabitedStruct(UninhabitedStruct); + | -------------------------------------------------------- + | | | + | | variant not covered + | `IndirectUninhabitedStruct` defined here +... +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedTupleStruct` of type `IndirectUninhabitedTupleStruct` is not handled + --> $DIR/indirect_match_same_crate.rs:43:11 + | +LL | pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct); + | ------------------------------------------------------------------ + | | | + | | variant not covered + | `IndirectUninhabitedTupleStruct` defined here +... +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedVariants` of type `IndirectUninhabitedVariants` is not handled + --> $DIR/indirect_match_same_crate.rs:49:11 + | +LL | pub struct IndirectUninhabitedVariants(UninhabitedVariants); + | ------------------------------------------------------------ + | | | + | | variant not covered + | `IndirectUninhabitedVariants` defined here +... +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.rs new file mode 100644 index 0000000000000..be86519ecb159 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.rs @@ -0,0 +1,40 @@ +// aux-build:uninhabited.rs +#![deny(unreachable_patterns)] +#![feature(exhaustive_patterns)] +#![feature(never_type)] + +extern crate uninhabited; + +use uninhabited::{ + IndirectUninhabitedEnum, + IndirectUninhabitedStruct, + IndirectUninhabitedTupleStruct, + IndirectUninhabitedVariants, +}; + +struct A; + +// This test checks that an empty match on a non-exhaustive uninhabited type through a level of +// indirection from an extern crate will not compile. In particular, this enables the +// `exhaustive_patterns` feature as this can change the branch used in the compiler to determine +// this. + +fn cannot_empty_match_on_empty_enum_to_anything(x: IndirectUninhabitedEnum) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_empty_struct_to_anything(x: IndirectUninhabitedStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: IndirectUninhabitedTupleStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything( + x: IndirectUninhabitedVariants, +) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn main() {} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr new file mode 100644 index 0000000000000..17a8d01007205 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr @@ -0,0 +1,35 @@ +error[E0004]: non-exhaustive patterns: type `uninhabited::IndirectUninhabitedEnum` is non-empty + --> $DIR/indirect_match_with_exhaustive_patterns.rs:23:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: type `uninhabited::IndirectUninhabitedStruct` is non-empty + --> $DIR/indirect_match_with_exhaustive_patterns.rs:27:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: type `uninhabited::IndirectUninhabitedTupleStruct` is non-empty + --> $DIR/indirect_match_with_exhaustive_patterns.rs:31:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: type `uninhabited::IndirectUninhabitedVariants` is non-empty + --> $DIR/indirect_match_with_exhaustive_patterns.rs:37:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns_same_crate.rs new file mode 100644 index 0000000000000..5dbd38e07df02 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns_same_crate.rs @@ -0,0 +1,58 @@ +// compile-pass +// skip-codegen +#![deny(unreachable_patterns)] +#![feature(exhaustive_patterns)] +#![feature(never_type)] +#![feature(non_exhaustive)] + +#[non_exhaustive] +pub enum UninhabitedEnum { +} + +#[non_exhaustive] +pub struct UninhabitedStruct { + _priv: !, +} + +#[non_exhaustive] +pub struct UninhabitedTupleStruct(!); + +pub enum UninhabitedVariants { + #[non_exhaustive] Tuple(!), + #[non_exhaustive] Struct { x: ! } +} + +pub struct IndirectUninhabitedEnum(UninhabitedEnum); + +pub struct IndirectUninhabitedStruct(UninhabitedStruct); + +pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct); + +pub struct IndirectUninhabitedVariants(UninhabitedVariants); + +struct A; + +// This test checks that an empty match on a non-exhaustive uninhabited type from the defining crate +// will compile. In particular, this enables the `exhaustive_patterns` feature as this can +// change the branch used in the compiler to determine this. +// Codegen is skipped because tests with long names can cause issues on Windows CI, see #60648. + +fn cannot_empty_match_on_empty_enum_to_anything(x: IndirectUninhabitedEnum) -> A { + match x {} +} + +fn cannot_empty_match_on_empty_struct_to_anything(x: IndirectUninhabitedStruct) -> A { + match x {} +} + +fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: IndirectUninhabitedTupleStruct) -> A { + match x {} +} + +fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything( + x: IndirectUninhabitedVariants, +) -> A { + match x {} +} + +fn main() {} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.rs index 0166b2e46cbf5..e54098d4d48b9 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.rs @@ -5,6 +5,9 @@ extern crate uninhabited; use uninhabited::{ UninhabitedEnum, + UninhabitedStruct, + UninhabitedTupleStruct, + UninhabitedVariants, }; struct A; @@ -16,4 +19,16 @@ fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A { match x {} //~ ERROR non-exhaustive patterns } +fn cannot_empty_match_on_empty_struct_to_anything(x: UninhabitedStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + fn main() {} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr index 356c6fba32d51..de39688f45a4d 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr @@ -1,11 +1,35 @@ error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedEnum` is non-empty - --> $DIR/match.rs:16:11 + --> $DIR/match.rs:19:11 | LL | match x {} | ^ | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error: aborting due to previous error +error[E0004]: non-exhaustive patterns: pattern `UninhabitedStruct` of type `uninhabited::UninhabitedStruct` is not handled + --> $DIR/match.rs:23:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: pattern `UninhabitedTupleStruct` of type `uninhabited::UninhabitedTupleStruct` is not handled + --> $DIR/match.rs:27:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: multiple patterns of type `uninhabited::UninhabitedVariants` are not handled + --> $DIR/match.rs:31:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs index d8b1c3810f338..6405dd3bd65b7 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs @@ -1,4 +1,3 @@ -// compile-pass #![feature(never_type)] #![feature(non_exhaustive)] @@ -6,6 +5,19 @@ pub enum UninhabitedEnum { } +#[non_exhaustive] +pub struct UninhabitedStruct { + _priv: !, +} + +#[non_exhaustive] +pub struct UninhabitedTupleStruct(!); + +pub enum UninhabitedVariants { + #[non_exhaustive] Tuple(!), + #[non_exhaustive] Struct { x: ! } +} + struct A; // This test checks that an empty match on a non-exhaustive uninhabited type from the defining crate @@ -15,4 +27,16 @@ fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A { match x {} } +fn cannot_empty_match_on_empty_struct_to_anything(x: UninhabitedStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + fn main() {} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr new file mode 100644 index 0000000000000..410285a39a945 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr @@ -0,0 +1,49 @@ +error[E0004]: non-exhaustive patterns: pattern `UninhabitedStruct` of type `UninhabitedStruct` is not handled + --> $DIR/match_same_crate.rs:31:11 + | +LL | pub struct UninhabitedStruct { + | - ----------------- variant not covered + | _| + | | +LL | | _priv: !, +LL | | } + | |_- `UninhabitedStruct` defined here +... +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: pattern `UninhabitedTupleStruct` of type `UninhabitedTupleStruct` is not handled + --> $DIR/match_same_crate.rs:35:11 + | +LL | pub struct UninhabitedTupleStruct(!); + | ------------------------------------- + | | | + | | variant not covered + | `UninhabitedTupleStruct` defined here +... +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: multiple patterns of type `UninhabitedVariants` are not handled + --> $DIR/match_same_crate.rs:39:11 + | +LL | / pub enum UninhabitedVariants { +LL | | #[non_exhaustive] Tuple(!), + | | ----- variant not covered +LL | | #[non_exhaustive] Struct { x: ! } + | | ------ variant not covered +LL | | } + | |_- `UninhabitedVariants` defined here +... +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs index d82010158ccc3..900dfff652ea6 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs @@ -7,6 +7,9 @@ extern crate uninhabited; use uninhabited::{ UninhabitedEnum, + UninhabitedStruct, + UninhabitedTupleStruct, + UninhabitedVariants, }; struct A; @@ -19,4 +22,16 @@ fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A { match x {} //~ ERROR non-exhaustive patterns } +fn cannot_empty_match_on_empty_struct_to_anything(x: UninhabitedStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + fn main() {} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr index ec2e9d0995b1f..48a888bc50be0 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr @@ -1,11 +1,35 @@ error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedEnum` is non-empty - --> $DIR/match_with_exhaustive_patterns.rs:19:11 + --> $DIR/match_with_exhaustive_patterns.rs:22:11 | LL | match x {} | ^ | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error: aborting due to previous error +error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedStruct` is non-empty + --> $DIR/match_with_exhaustive_patterns.rs:26:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedTupleStruct` is non-empty + --> $DIR/match_with_exhaustive_patterns.rs:30:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedVariants` is non-empty + --> $DIR/match_with_exhaustive_patterns.rs:34:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs index da814a70a75ca..74922d4bcb5d5 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs @@ -1,4 +1,5 @@ // compile-pass +// skip-codegen #![deny(unreachable_patterns)] #![feature(exhaustive_patterns)] #![feature(never_type)] @@ -8,14 +9,40 @@ pub enum UninhabitedEnum { } +#[non_exhaustive] +pub struct UninhabitedStruct { + _priv: !, +} + +#[non_exhaustive] +pub struct UninhabitedTupleStruct(!); + +pub enum UninhabitedVariants { + #[non_exhaustive] Tuple(!), + #[non_exhaustive] Struct { x: ! } +} + struct A; // This test checks that an empty match on a non-exhaustive uninhabited type from the defining crate // will compile. In particular, this enables the `exhaustive_patterns` feature as this can // change the branch used in the compiler to determine this. +// Codegen is skipped because tests with long names can cause issues on Windows CI, see #60648. fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A { match x {} } +fn cannot_empty_match_on_empty_struct_to_anything(x: UninhabitedStruct) -> A { + match x {} +} + +fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { + match x {} +} + +fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A { + match x {} +} + fn main() {} From 5cccda1770f76b8184ea55e4735ce88f824f7fd8 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 11 Mar 2019 16:43:27 +0100 Subject: [PATCH 167/212] Remove hir::ExprKind::If and replace it with lowering to hir::ExprKind::Match. --- src/librustc/cfg/construct.rs | 41 -- src/librustc/hir/intravisit.rs | 5 - src/librustc/hir/lowering.rs | 124 ++--- src/librustc/hir/mod.rs | 10 +- src/librustc/hir/print.rs | 63 --- src/librustc/ich/impls_syntax.rs | 1 + src/librustc/middle/expr_use_visitor.rs | 8 - src/librustc/middle/liveness.rs | 25 +- src/librustc/middle/mem_categorization.rs | 2 +- src/librustc/middle/region.rs | 11 - src/librustc_errors/diagnostic_builder.rs | 12 + src/librustc_mir/build/expr/as_place.rs | 1 - src/librustc_mir/build/expr/as_rvalue.rs | 1 - src/librustc_mir/build/expr/category.rs | 1 - src/librustc_mir/build/expr/into.rs | 37 -- src/librustc_mir/hair/cx/expr.rs | 7 - src/librustc_mir/hair/mod.rs | 5 - src/librustc_mir/hair/pattern/check_match.rs | 1 + src/librustc_passes/rvalue_promotion.rs | 9 - src/librustc_typeck/check/_match.rs | 465 +++++++++++++------ src/librustc_typeck/check/coercion.rs | 8 +- src/librustc_typeck/check/mod.rs | 229 +-------- src/libsyntax_pos/hygiene.rs | 5 + 23 files changed, 436 insertions(+), 635 deletions(-) diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index 2592af7d4ad5a..2e54165be1f1b 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -166,47 +166,6 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { self.add_ast_node(expr.hir_id.local_id, &[blk_exit]) } - hir::ExprKind::If(ref cond, ref then, None) => { - // - // [pred] - // | - // v 1 - // [cond] - // | - // / \ - // / \ - // v 2 * - // [then] | - // | | - // v 3 v 4 - // [..expr..] - // - let cond_exit = self.expr(&cond, pred); // 1 - let then_exit = self.expr(&then, cond_exit); // 2 - self.add_ast_node(expr.hir_id.local_id, &[cond_exit, then_exit]) // 3,4 - } - - hir::ExprKind::If(ref cond, ref then, Some(ref otherwise)) => { - // - // [pred] - // | - // v 1 - // [cond] - // | - // / \ - // / \ - // v 2 v 3 - // [then][otherwise] - // | | - // v 4 v 5 - // [..expr..] - // - let cond_exit = self.expr(&cond, pred); // 1 - let then_exit = self.expr(&then, cond_exit); // 2 - let else_exit = self.expr(&otherwise, cond_exit); // 3 - self.add_ast_node(expr.hir_id.local_id, &[then_exit, else_exit]) // 4, 5 - } - hir::ExprKind::While(ref cond, ref body, _) => { // // [pred] diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 0c73d97394fda..38d6d710868c0 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -1032,11 +1032,6 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { ExprKind::DropTemps(ref subexpression) => { visitor.visit_expr(subexpression); } - ExprKind::If(ref head_expression, ref if_block, ref optional_else) => { - visitor.visit_expr(head_expression); - visitor.visit_expr(if_block); - walk_list!(visitor, visit_expr, optional_else); - } ExprKind::While(ref subexpression, ref block, ref opt_label) => { walk_list!(visitor, visit_label, opt_label); visitor.visit_expr(subexpression); diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 4d5707560b048..7ccfb826e37b7 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -62,6 +62,7 @@ use syntax::ext::hygiene::Mark; use syntax::print::pprust; use syntax::ptr::P; use syntax::source_map::{respan, CompilerDesugaringKind, Spanned}; +use syntax::source_map::CompilerDesugaringKind::IfTemporary; use syntax::std_inject; use syntax::symbol::{keywords, Symbol}; use syntax::tokenstream::{TokenStream, TokenTree}; @@ -4115,31 +4116,46 @@ impl<'a> LoweringContext<'a> { } // More complicated than you might expect because the else branch // might be `if let`. - ExprKind::If(ref cond, ref blk, ref else_opt) => { - let else_opt = else_opt.as_ref().map(|els| { - match els.node { + ExprKind::If(ref cond, ref then, ref else_opt) => { + // `true => then`: + let then_pat = self.pat_bool(e.span, true); + let then_blk = self.lower_block(then, false); + let then_expr = self.expr_block(then_blk, ThinVec::new()); + let then_arm = self.arm(hir_vec![then_pat], P(then_expr)); + + // `_ => else_block` where `else_block` is `{}` if there's `None`: + let else_pat = self.pat_wild(e.span); + let else_expr = match else_opt { + None => self.expr_block_empty(e.span), + Some(els) => match els.node { ExprKind::IfLet(..) => { // Wrap the `if let` expr in a block. - let span = els.span; - let els = P(self.lower_expr(els)); - let blk = P(hir::Block { - stmts: hir_vec![], - expr: Some(els), - hir_id: self.next_id(), - rules: hir::DefaultBlock, - span, - targeted_by_break: false, - }); - P(self.expr_block(blk, ThinVec::new())) + let els = self.lower_expr(els); + let blk = self.block_all(els.span, hir_vec![], Some(P(els))); + self.expr_block(P(blk), ThinVec::new()) } - _ => P(self.lower_expr(els)), + _ => self.lower_expr(els), } - }); - - let then_blk = self.lower_block(blk, false); - let then_expr = self.expr_block(then_blk, ThinVec::new()); + }; + let else_arm = self.arm(hir_vec![else_pat], P(else_expr)); + + // Lower condition: + let span_block = self + .sess + .source_map() + .mark_span_with_reason(IfTemporary, cond.span, None); + let cond = self.lower_expr(cond); + // Wrap in a construct equivalent to `{ let _t = $cond; _t }` to preserve drop + // semantics since `if cond { ... }` don't let temporaries live outside of `cond`. + let cond = self.expr_drop_temps(span_block, P(cond), ThinVec::new()); - hir::ExprKind::If(P(self.lower_expr(cond)), P(then_expr), else_opt) + hir::ExprKind::Match( + P(cond), + vec![then_arm, else_arm].into(), + hir::MatchSource::IfDesugar { + contains_else_clause: else_opt.is_some() + }, + ) } ExprKind::While(ref cond, ref body, opt_label) => self.with_loop_scope(e.id, |this| { hir::ExprKind::While( @@ -4486,16 +4502,16 @@ impl<'a> LoweringContext<'a> { arms.push(self.arm(pats, body_expr)); } - // _ => [|()] + // _ => [|{}] { let wildcard_arm: Option<&Expr> = else_opt.as_ref().map(|p| &**p); let wildcard_pattern = self.pat_wild(e.span); let body = if let Some(else_expr) = wildcard_arm { - P(self.lower_expr(else_expr)) + self.lower_expr(else_expr) } else { - P(self.expr_tuple(e.span, hir_vec![])) + self.expr_block_empty(e.span) }; - arms.push(self.arm(hir_vec![wildcard_pattern], body)); + arms.push(self.arm(hir_vec![wildcard_pattern], P(body))); } let contains_else_clause = else_opt.is_some(); @@ -4658,11 +4674,7 @@ impl<'a> LoweringContext<'a> { ThinVec::new(), )) }; - let match_stmt = hir::Stmt { - hir_id: self.next_id(), - node: hir::StmtKind::Expr(match_expr), - span: head_sp, - }; + let match_stmt = self.stmt(head_sp, hir::StmtKind::Expr(match_expr)); let next_expr = P(self.expr_ident(head_sp, next_ident, next_pat_hid)); @@ -4685,11 +4697,7 @@ impl<'a> LoweringContext<'a> { let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false)); let body_expr = P(self.expr_block(body_block, ThinVec::new())); - let body_stmt = hir::Stmt { - hir_id: self.next_id(), - node: hir::StmtKind::Expr(body_expr), - span: body.span, - }; + let body_stmt = self.stmt(body.span, hir::StmtKind::Expr(body_expr)); let loop_block = P(self.block_all( e.span, @@ -4869,12 +4877,7 @@ impl<'a> LoweringContext<'a> { .into_iter() .map(|item_id| { let item_id = hir::ItemId { id: self.lower_node_id(item_id) }; - - hir::Stmt { - hir_id: self.next_id(), - node: hir::StmtKind::Item(item_id), - span: s.span, - } + self.stmt(s.span, hir::StmtKind::Item(item_id)) }) .collect(); ids.push({ @@ -5174,28 +5177,32 @@ impl<'a> LoweringContext<'a> { } } + fn stmt(&mut self, span: Span, node: hir::StmtKind) -> hir::Stmt { + hir::Stmt { span, node, hir_id: self.next_id() } + } + fn stmt_let_pat( &mut self, - sp: Span, - ex: Option>, + span: Span, + init: Option>, pat: P, source: hir::LocalSource, ) -> hir::Stmt { let local = hir::Local { pat, ty: None, - init: ex, + init, hir_id: self.next_id(), - span: sp, - attrs: ThinVec::new(), + span, source, + attrs: ThinVec::new() }; + self.stmt(span, hir::StmtKind::Local(P(local))) + } - hir::Stmt { - hir_id: self.next_id(), - node: hir::StmtKind::Local(P(local)), - span: sp - } + fn expr_block_empty(&mut self, span: Span) -> hir::Expr { + let blk = self.block_all(span, hir_vec![], None); + self.expr_block(P(blk), ThinVec::new()) } fn block_expr(&mut self, expr: P) -> hir::Block { @@ -5235,6 +5242,13 @@ impl<'a> LoweringContext<'a> { ) } + /// Constructs a `true` or `false` literal pattern. + fn pat_bool(&mut self, span: Span, val: bool) -> P { + let lit = Spanned { span, node: LitKind::Bool(val) }; + let expr = self.expr(span, hir::ExprKind::Lit(lit), ThinVec::new()); + self.pat(span, hir::PatKind::Lit(P(expr))) + } + fn pat_ok(&mut self, span: Span, pat: P) -> P { self.pat_std_enum(span, &["result", "Result", "Ok"], hir_vec![pat]) } @@ -5622,15 +5636,7 @@ impl<'a> LoweringContext<'a> { &["task", "Poll", "Pending"], hir_vec![], ); - let empty_block = P(hir::Block { - stmts: hir_vec![], - expr: None, - hir_id: self.next_id(), - rules: hir::DefaultBlock, - span, - targeted_by_break: false, - }); - let empty_block = P(self.expr_block(empty_block, ThinVec::new())); + let empty_block = P(self.expr_block_empty(span)); self.arm(hir_vec![pending_pat], empty_block) }; diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 01de7917e6e23..9f7fa6c5557ef 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1368,7 +1368,6 @@ impl Expr { ExprKind::Lit(_) => ExprPrecedence::Lit, ExprKind::Type(..) | ExprKind::Cast(..) => ExprPrecedence::Cast, ExprKind::DropTemps(ref expr, ..) => expr.precedence(), - ExprKind::If(..) => ExprPrecedence::If, ExprKind::While(..) => ExprPrecedence::While, ExprKind::Loop(..) => ExprPrecedence::Loop, ExprKind::Match(..) => ExprPrecedence::Match, @@ -1421,7 +1420,6 @@ impl Expr { ExprKind::MethodCall(..) | ExprKind::Struct(..) | ExprKind::Tup(..) | - ExprKind::If(..) | ExprKind::Match(..) | ExprKind::Closure(..) | ExprKind::Block(..) | @@ -1498,10 +1496,6 @@ pub enum ExprKind { /// This construct only exists to tweak the drop order in HIR lowering. /// An example of that is the desugaring of `for` loops. DropTemps(P), - /// An `if` block, with an optional else block. - /// - /// I.e., `if { } else { }`. - If(P, P, Option>), /// A while loop, with an optional label /// /// I.e., `'label: while expr { }`. @@ -1615,6 +1609,10 @@ pub enum LocalSource { pub enum MatchSource { /// A `match _ { .. }`. Normal, + /// An `if _ { .. }` (optionally with `else { .. }`). + IfDesugar { + contains_else_clause: bool, + }, /// An `if let _ = _ { .. }` (optionally with `else { .. }`). IfLetDesugar { contains_else_clause: bool, diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 54816316f0bf5..c42d8f3cb3c36 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1093,65 +1093,6 @@ impl<'a> State<'a> { self.ann.post(self, AnnNode::Block(blk)) } - fn print_else(&mut self, els: Option<&hir::Expr>) -> io::Result<()> { - match els { - Some(_else) => { - match _else.node { - // "another else-if" - hir::ExprKind::If(ref i, ref then, ref e) => { - self.cbox(indent_unit - 1)?; - self.ibox(0)?; - self.s.word(" else if ")?; - self.print_expr_as_cond(&i)?; - self.s.space()?; - self.print_expr(&then)?; - self.print_else(e.as_ref().map(|e| &**e)) - } - // "final else" - hir::ExprKind::Block(ref b, _) => { - self.cbox(indent_unit - 1)?; - self.ibox(0)?; - self.s.word(" else ")?; - self.print_block(&b) - } - // BLEAH, constraints would be great here - _ => { - panic!("print_if saw if with weird alternative"); - } - } - } - _ => Ok(()), - } - } - - pub fn print_if(&mut self, - test: &hir::Expr, - blk: &hir::Expr, - elseopt: Option<&hir::Expr>) - -> io::Result<()> { - self.head("if")?; - self.print_expr_as_cond(test)?; - self.s.space()?; - self.print_expr(blk)?; - self.print_else(elseopt) - } - - pub fn print_if_let(&mut self, - pat: &hir::Pat, - expr: &hir::Expr, - blk: &hir::Block, - elseopt: Option<&hir::Expr>) - -> io::Result<()> { - self.head("if let")?; - self.print_pat(pat)?; - self.s.space()?; - self.word_space("=")?; - self.print_expr_as_cond(expr)?; - self.s.space()?; - self.print_block(blk)?; - self.print_else(elseopt) - } - pub fn print_anon_const(&mut self, constant: &hir::AnonConst) -> io::Result<()> { self.ann.nested(self, Nested::Body(constant.body)) } @@ -1406,9 +1347,6 @@ impl<'a> State<'a> { // Print `}`: self.bclose_maybe_open(expr.span, indent_unit, true)?; } - hir::ExprKind::If(ref test, ref blk, ref elseopt) => { - self.print_if(&test, &blk, elseopt.as_ref().map(|e| &**e))?; - } hir::ExprKind::While(ref test, ref blk, opt_label) => { if let Some(label) = opt_label { self.print_ident(label.ident)?; @@ -2414,7 +2352,6 @@ impl<'a> State<'a> { /// isn't parsed as (if true {...} else {...} | x) | 5 fn expr_requires_semi_to_be_stmt(e: &hir::Expr) -> bool { match e.node { - hir::ExprKind::If(..) | hir::ExprKind::Match(..) | hir::ExprKind::Block(..) | hir::ExprKind::While(..) | diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index 90dd5099cbfd6..35df43ef25efa 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -395,6 +395,7 @@ impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnFormat { }); impl_stable_hash_for!(enum ::syntax_pos::hygiene::CompilerDesugaringKind { + IfTemporary, Async, Await, QuestionMark, diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 93ba4241c4725..d46bba92f3fc9 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -424,14 +424,6 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { self.consume_exprs(exprs); } - hir::ExprKind::If(ref cond_expr, ref then_expr, ref opt_else_expr) => { - self.consume_expr(&cond_expr); - self.walk_expr(&then_expr); - if let Some(ref else_expr) = *opt_else_expr { - self.consume_expr(&else_expr); - } - } - hir::ExprKind::Match(ref discr, ref arms, _) => { let discr_cmt = Rc::new(return_if_err!(self.mc.cat_expr(&discr))); let r = self.tcx().lifetimes.re_empty; diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 4b458e474b299..a142b220f31af 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -500,7 +500,6 @@ fn visit_expr<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, expr: &'tcx Expr) { } // live nodes required for interesting control flow: - hir::ExprKind::If(..) | hir::ExprKind::Match(..) | hir::ExprKind::While(..) | hir::ExprKind::Loop(..) => { @@ -1040,28 +1039,6 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { }) } - hir::ExprKind::If(ref cond, ref then, ref els) => { - // - // (cond) - // | - // v - // (expr) - // / \ - // | | - // v v - // (then)(els) - // | | - // v v - // ( succ ) - // - let else_ln = self.propagate_through_opt_expr(els.as_ref().map(|e| &**e), succ); - let then_ln = self.propagate_through_expr(&then, succ); - let ln = self.live_node(expr.hir_id, expr.span); - self.init_from_succ(ln, else_ln); - self.merge_from_succ(ln, then_ln, false); - self.propagate_through_expr(&cond, ln) - } - hir::ExprKind::While(ref cond, ref blk, _) => { self.propagate_through_loop(expr, WhileLoop(&cond), &blk, succ) } @@ -1523,7 +1500,7 @@ fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) { } // no correctness conditions related to liveness - hir::ExprKind::Call(..) | hir::ExprKind::MethodCall(..) | hir::ExprKind::If(..) | + hir::ExprKind::Call(..) | hir::ExprKind::MethodCall(..) | hir::ExprKind::Match(..) | hir::ExprKind::While(..) | hir::ExprKind::Loop(..) | hir::ExprKind::Index(..) | hir::ExprKind::Field(..) | hir::ExprKind::Array(..) | hir::ExprKind::Tup(..) | hir::ExprKind::Binary(..) | diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 7edd5c5a9de1b..85c7f43790336 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -678,7 +678,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { hir::ExprKind::Closure(..) | hir::ExprKind::Ret(..) | hir::ExprKind::Unary(..) | hir::ExprKind::Yield(..) | hir::ExprKind::MethodCall(..) | hir::ExprKind::Cast(..) | hir::ExprKind::DropTemps(..) | - hir::ExprKind::Array(..) | hir::ExprKind::Tup(..) | hir::ExprKind::If(..) | + hir::ExprKind::Array(..) | hir::ExprKind::Tup(..) | hir::ExprKind::Binary(..) | hir::ExprKind::While(..) | hir::ExprKind::Block(..) | hir::ExprKind::Loop(..) | hir::ExprKind::Match(..) | hir::ExprKind::Lit(..) | hir::ExprKind::Break(..) | diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 2b88f273adce4..8ef4e9ac8f45f 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -884,17 +884,6 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr: terminating(r.hir_id.local_id); } - hir::ExprKind::If(ref expr, ref then, Some(ref otherwise)) => { - terminating(expr.hir_id.local_id); - terminating(then.hir_id.local_id); - terminating(otherwise.hir_id.local_id); - } - - hir::ExprKind::If(ref expr, ref then, None) => { - terminating(expr.hir_id.local_id); - terminating(then.hir_id.local_id); - } - hir::ExprKind::Loop(ref body, _, _) => { terminating(body.hir_id.local_id); } diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index f74dcd6070c70..31f697a724a03 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -100,6 +100,18 @@ impl<'a> DiagnosticBuilder<'a> { self.cancel(); } + /// Emit the diagnostic unless `delay` is true, + /// in which case the emission will be delayed as a bug. + /// + /// See `emit` and `delay_as_bug` for details. + pub fn emit_unless(&mut self, delay: bool) { + if delay { + self.delay_as_bug() + } else { + self.emit() + } + } + /// Buffers the diagnostic for later emission, unless handler /// has disabled such buffering. pub fn buffer(mut self, buffered_diagnostics: &mut Vec) { diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs index 713e3fe0218ba..5f444d4ceeb88 100644 --- a/src/librustc_mir/build/expr/as_place.rs +++ b/src/librustc_mir/build/expr/as_place.rs @@ -192,7 +192,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { | ExprKind::Pointer { .. } | ExprKind::Repeat { .. } | ExprKind::Borrow { .. } - | ExprKind::If { .. } | ExprKind::Match { .. } | ExprKind::Loop { .. } | ExprKind::Block { .. } diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index e745ee0f190dd..fbc4835a6557b 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -345,7 +345,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ExprKind::Literal { .. } | ExprKind::Block { .. } | ExprKind::Match { .. } - | ExprKind::If { .. } | ExprKind::NeverToAny { .. } | ExprKind::Use { .. } | ExprKind::Loop { .. } diff --git a/src/librustc_mir/build/expr/category.rs b/src/librustc_mir/build/expr/category.rs index 4e24b6853d6eb..222ce6d1c968e 100644 --- a/src/librustc_mir/build/expr/category.rs +++ b/src/librustc_mir/build/expr/category.rs @@ -45,7 +45,6 @@ impl Category { | ExprKind::ValueTypeAscription { .. } => Some(Category::Place), ExprKind::LogicalOp { .. } - | ExprKind::If { .. } | ExprKind::Match { .. } | ExprKind::NeverToAny { .. } | ExprKind::Use { .. } diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 30ed9cef36f7b..15795a64e3b7d 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -76,43 +76,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { end_block.unit() } } - ExprKind::If { - condition: cond_expr, - then: then_expr, - otherwise: else_expr, - } => { - let operand = unpack!(block = this.as_local_operand(block, cond_expr)); - - let mut then_block = this.cfg.start_new_block(); - let mut else_block = this.cfg.start_new_block(); - let term = TerminatorKind::if_(this.hir.tcx(), operand, then_block, else_block); - this.cfg.terminate(block, source_info, term); - - unpack!(then_block = this.into(destination, then_block, then_expr)); - else_block = if let Some(else_expr) = else_expr { - unpack!(this.into(destination, else_block, else_expr)) - } else { - // Body of the `if` expression without an `else` clause must return `()`, thus - // we implicitly generate a `else {}` if it is not specified. - this.cfg - .push_assign_unit(else_block, source_info, destination); - else_block - }; - - let join_block = this.cfg.start_new_block(); - this.cfg.terminate( - then_block, - source_info, - TerminatorKind::Goto { target: join_block }, - ); - this.cfg.terminate( - else_block, - source_info, - TerminatorKind::Goto { target: join_block }, - ); - - join_block.unit() - } ExprKind::LogicalOp { op, lhs, rhs } => { // And: // diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 5e646a49e0e42..50140880a368d 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -601,13 +601,6 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, arms: arms.iter().map(|a| convert_arm(cx, a)).collect(), } } - hir::ExprKind::If(ref cond, ref then, ref otherwise) => { - ExprKind::If { - condition: cond.to_ref(), - then: then.to_ref(), - otherwise: otherwise.to_ref(), - } - } hir::ExprKind::While(ref cond, ref body, _) => { ExprKind::Loop { condition: Some(cond.to_ref()), diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index 2e53bee3f3d7f..d4f139e103a64 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -185,11 +185,6 @@ pub enum ExprKind<'tcx> { cast: PointerCast, source: ExprRef<'tcx>, }, - If { - condition: ExprRef<'tcx>, - then: ExprRef<'tcx>, - otherwise: Option>, - }, Loop { condition: Option>, body: ExprRef<'tcx>, diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index 1a7266859ad9f..b58f8dd492424 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -365,6 +365,7 @@ fn check_arms<'a, 'tcx>( match is_useful(cx, &seen, &v, LeaveOutWitness) { NotUseful => { match source { + hir::MatchSource::IfDesugar { .. } => bug!(), hir::MatchSource::IfLetDesugar { .. } => { cx.tcx.lint_hir( lint::builtin::IRREFUTABLE_LET_PATTERNS, diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index 0f651fafcd2ac..2d35a0de7953f 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -518,15 +518,6 @@ fn check_expr_kind<'a, 'tcx>( NotPromotable } - hir::ExprKind::If(ref lhs, ref rhs, ref option_expr) => { - let _ = v.check_expr(lhs); - let _ = v.check_expr(rhs); - if let Some(ref expr) = option_expr { - let _ = v.check_expr(&expr); - } - NotPromotable - } - // Loops (not very meaningful in constants). hir::ExprKind::While(ref expr, ref box_block, ref _option_label) => { let _ = v.check_expr(expr); diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index e9e202ce37996..e8af2f40b87a7 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -2,12 +2,12 @@ use crate::check::{FnCtxt, Expectation, Diverges, Needs}; use crate::check::coercion::CoerceMany; use crate::util::nodemap::FxHashMap; use errors::{Applicability, DiagnosticBuilder}; -use rustc::hir::{self, PatKind, Pat}; +use rustc::hir::{self, PatKind, Pat, ExprKind}; use rustc::hir::def::{Res, DefKind, CtorKind}; use rustc::hir::pat_util::EnumerateAndAdjustIterator; use rustc::infer; use rustc::infer::type_variable::TypeVariableOrigin; -use rustc::traits::ObligationCauseCode; +use rustc::traits::{ObligationCause, ObligationCauseCode}; use rustc::ty::{self, Ty, TypeFoldable}; use rustc::ty::subst::Kind; use syntax::ast; @@ -15,6 +15,7 @@ use syntax::source_map::Spanned; use syntax::ptr::P; use syntax::util::lev_distance::find_best_match_for_name; use syntax_pos::Span; +use syntax_pos::hygiene::CompilerDesugaringKind; use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::cmp; @@ -22,10 +23,9 @@ use std::cmp; use super::report_unexpected_variant_res; impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { - /// `match_discrim_span` argument having a `Span` indicates that this pattern is part of - /// a match expression arm guard, and it points to the match discriminant to add context - /// in type errors. In the folloowing example, `match_discrim_span` corresponds to the - /// `a + b` expression: + /// `discrim_span` argument having a `Span` indicates that this pattern is part of a match + /// expression arm guard, and it points to the match discriminant to add context in type errors. + /// In the following example, `discrim_span` corresponds to the `a + b` expression: /// /// ```text /// error[E0308]: mismatched types @@ -44,7 +44,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pat: &'gcx hir::Pat, mut expected: Ty<'tcx>, mut def_bm: ty::BindingMode, - match_discrim_span: Option, + discrim_span: Option, ) { let tcx = self.tcx; @@ -176,7 +176,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // &'static str <: expected // // that's equivalent to there existing a LUB. - self.demand_suptype(pat.span, expected, pat_ty); + if let Some(mut err) = self.demand_suptype_diag(pat.span, expected, pat_ty) { + err.emit_unless(discrim_span + .filter(|&s| s.is_compiler_desugaring(CompilerDesugaringKind::IfTemporary)) + .is_some()); + } + pat_ty } PatKind::Range(ref begin, ref end, _) => { @@ -224,8 +229,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let common_type = self.resolve_type_vars_if_possible(&lhs_ty); // subtyping doesn't matter here, as the value is some kind of scalar - self.demand_eqtype_pat(pat.span, expected, lhs_ty, match_discrim_span); - self.demand_eqtype_pat(pat.span, expected, rhs_ty, match_discrim_span); + self.demand_eqtype_pat(pat.span, expected, lhs_ty, discrim_span); + self.demand_eqtype_pat(pat.span, expected, rhs_ty, discrim_span); common_type } PatKind::Binding(ba, var_id, _, ref sub) => { @@ -254,13 +259,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is // required. However, we use equality, which is stronger. See (*) for // an explanation. - self.demand_eqtype_pat(pat.span, region_ty, local_ty, match_discrim_span); + self.demand_eqtype_pat(pat.span, region_ty, local_ty, discrim_span); } // otherwise the type of x is the expected type T ty::BindByValue(_) => { // As above, `T <: typeof(x)` is required but we // use equality, see (*) below. - self.demand_eqtype_pat(pat.span, expected, local_ty, match_discrim_span); + self.demand_eqtype_pat(pat.span, expected, local_ty, discrim_span); } } @@ -268,11 +273,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // what the type of the binding `x` ought to be if var_id != pat.hir_id { let vt = self.local_ty(pat.span, var_id).decl_ty; - self.demand_eqtype_pat(pat.span, vt, local_ty, match_discrim_span); + self.demand_eqtype_pat(pat.span, vt, local_ty, discrim_span); } if let Some(ref p) = *sub { - self.check_pat_walk(&p, expected, def_bm, match_discrim_span); + self.check_pat_walk(&p, expected, def_bm, discrim_span); } local_ty @@ -285,14 +290,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ddpos, expected, def_bm, - match_discrim_span, + discrim_span, ) } PatKind::Path(ref qpath) => { self.check_pat_path(pat, qpath, expected) } PatKind::Struct(ref qpath, ref fields, etc) => { - self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm, match_discrim_span) + self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm, discrim_span) } PatKind::Tuple(ref elements, ddpos) => { let mut expected_len = elements.len(); @@ -318,7 +323,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // further errors being emitted when using the bindings. #50333 let element_tys_iter = (0..max_len).map(|_| tcx.types.err); for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { - self.check_pat_walk(elem, &tcx.types.err, def_bm, match_discrim_span); + self.check_pat_walk(elem, &tcx.types.err, def_bm, discrim_span); } tcx.mk_tup(element_tys_iter) } else { @@ -327,7 +332,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { elem, &element_tys[i].expect_ty(), def_bm, - match_discrim_span, + discrim_span, ); } pat_ty @@ -341,11 +346,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Here, `demand::subtype` is good enough, but I don't // think any errors can be introduced by using // `demand::eqtype`. - self.demand_eqtype_pat(pat.span, expected, uniq_ty, match_discrim_span); - self.check_pat_walk(&inner, inner_ty, def_bm, match_discrim_span); + self.demand_eqtype_pat(pat.span, expected, uniq_ty, discrim_span); + self.check_pat_walk(&inner, inner_ty, def_bm, discrim_span); uniq_ty } else { - self.check_pat_walk(&inner, tcx.types.err, def_bm, match_discrim_span); + self.check_pat_walk(&inner, tcx.types.err, def_bm, discrim_span); tcx.types.err } } @@ -384,10 +389,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } }; - self.check_pat_walk(&inner, inner_ty, def_bm, match_discrim_span); + self.check_pat_walk(&inner, inner_ty, def_bm, discrim_span); rptr_ty } else { - self.check_pat_walk(&inner, tcx.types.err, def_bm, match_discrim_span); + self.check_pat_walk(&inner, tcx.types.err, def_bm, discrim_span); tcx.types.err } } @@ -445,13 +450,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; for elt in before { - self.check_pat_walk(&elt, inner_ty, def_bm, match_discrim_span); + self.check_pat_walk(&elt, inner_ty, def_bm, discrim_span); } if let Some(ref slice) = *slice { - self.check_pat_walk(&slice, slice_ty, def_bm, match_discrim_span); + self.check_pat_walk(&slice, slice_ty, def_bm, discrim_span); } for elt in after { - self.check_pat_walk(&elt, inner_ty, def_bm, match_discrim_span); + self.check_pat_walk(&elt, inner_ty, def_bm, discrim_span); } expected_ty } @@ -595,73 +600,24 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); ) -> Ty<'tcx> { let tcx = self.tcx; - // Not entirely obvious: if matches may create ref bindings, we want to - // use the *precise* type of the discriminant, *not* some supertype, as - // the "discriminant type" (issue #23116). - // - // arielb1 [writes here in this comment thread][c] that there - // is certainly *some* potential danger, e.g., for an example - // like: - // - // [c]: https://github.com/rust-lang/rust/pull/43399#discussion_r130223956 - // - // ``` - // let Foo(x) = f()[0]; - // ``` - // - // Then if the pattern matches by reference, we want to match - // `f()[0]` as a lexpr, so we can't allow it to be - // coerced. But if the pattern matches by value, `f()[0]` is - // still syntactically a lexpr, but we *do* want to allow - // coercions. - // - // However, *likely* we are ok with allowing coercions to - // happen if there are no explicit ref mut patterns - all - // implicit ref mut patterns must occur behind a reference, so - // they will have the "correct" variance and lifetime. - // - // This does mean that the following pattern would be legal: - // - // ``` - // struct Foo(Bar); - // struct Bar(u32); - // impl Deref for Foo { - // type Target = Bar; - // fn deref(&self) -> &Bar { &self.0 } - // } - // impl DerefMut for Foo { - // fn deref_mut(&mut self) -> &mut Bar { &mut self.0 } - // } - // fn foo(x: &mut Foo) { - // { - // let Bar(z): &mut Bar = x; - // *z = 42; - // } - // assert_eq!(foo.0.0, 42); - // } - // ``` - // - // FIXME(tschottdorf): don't call contains_explicit_ref_binding, which - // is problematic as the HIR is being scraped, but ref bindings may be - // implicit after #42640. We need to make sure that pat_adjustments - // (once introduced) is populated by the time we get here. - // - // See #44848. - let contains_ref_bindings = arms.iter() - .filter_map(|a| a.contains_explicit_ref_binding()) - .max_by_key(|m| match *m { - hir::MutMutable => 1, - hir::MutImmutable => 0, - }); - let discrim_ty; - if let Some(m) = contains_ref_bindings { - discrim_ty = self.check_expr_with_needs(discrim, Needs::maybe_mut_place(m)); + use hir::MatchSource::*; + let (source_if, if_no_else, if_desugar) = match match_src { + IfDesugar { contains_else_clause } => (true, !contains_else_clause, true), + IfLetDesugar { contains_else_clause } => (true, !contains_else_clause, false), + _ => (false, false, false), + }; + + // Type check the descriminant and get its type. + let discrim_ty = if if_desugar { + // Here we want to ensure: + // + // 1. That default match bindings are *not* accepted in the condition of an + // `if` expression. E.g. given `fn foo() -> &bool;` we reject `if foo() { .. }`. + // + // 2. By expecting `bool` for `expr` we get nice diagnostics for e.g. `if x = y { .. }`. + self.check_expr_has_type_or_error(discrim, self.tcx.types.bool) } else { - // ...but otherwise we want to use any supertype of the - // discriminant. This is sort of a workaround, see note (*) in - // `check_pat` for some details. - discrim_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(discrim.span)); - self.check_expr_has_type_or_error(discrim, discrim_ty); + self.demand_discriminant_type(arms, discrim) }; // If there are no arms, that is a diverging match; a special case. @@ -670,11 +626,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); return tcx.types.never; } - if self.diverges.get().always() { - for arm in arms { - self.warn_if_unreachable(arm.body.hir_id, arm.body.span, "arm"); - } - } + self.warn_arms_when_scrutinee_diverges(arms, source_if); // Otherwise, we have to union together the types that the // arms produce and so forth. @@ -687,12 +639,8 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); let mut all_pats_diverge = Diverges::WarnedAlways; for p in &arm.pats { self.diverges.set(Diverges::Maybe); - self.check_pat_walk( - &p, - discrim_ty, - ty::BindingMode::BindByValue(hir::Mutability::MutImmutable), - Some(discrim.span), - ); + let binding_mode = ty::BindingMode::BindByValue(hir::Mutability::MutImmutable); + self.check_pat_walk(&p, discrim_ty, binding_mode, Some(discrim.span)); all_pats_diverge &= self.diverges.get(); } @@ -734,7 +682,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); let mut other_arms = vec![]; // used only for diagnostics let mut prior_arm_ty = None; for (i, (arm, pats_diverge)) in arms.iter().zip(all_arm_pats_diverge).enumerate() { - if let Some(ref g) = arm.guard { + if let Some(g) = &arm.guard { self.diverges.set(pats_diverge); match g { hir::Guard::If(e) => self.check_expr_has_type_or_error(e, tcx.types.bool), @@ -745,43 +693,44 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); let arm_ty = self.check_expr_with_expectation(&arm.body, expected); all_arms_diverge &= self.diverges.get(); - // Handle the fallback arm of a desugared if-let like a missing else. - let is_if_let_fallback = match match_src { - hir::MatchSource::IfLetDesugar { contains_else_clause: false } => { - i == arms.len() - 1 && arm_ty.is_unit() + let span = expr.span; + + if source_if { + let then_expr = &arms[0].body; + match (i, if_no_else) { + (0, _) => coercion.coerce(self, &self.misc(span), then_expr, arm_ty), + (_, true) => self.if_fallback_coercion(span, then_expr, &mut coercion), + (_, _) => { + let then_ty = prior_arm_ty.unwrap(); + let cause = self.if_cause(span, then_expr, &arm.body, then_ty, arm_ty); + coercion.coerce(self, &cause, &arm.body, arm_ty); + } } - _ => false - }; - - let arm_span = if let hir::ExprKind::Block(ref blk, _) = arm.body.node { - // Point at the block expr instead of the entire block - blk.expr.as_ref().map(|e| e.span).unwrap_or(arm.body.span) } else { - arm.body.span - }; - if is_if_let_fallback { - let cause = self.cause(expr.span, ObligationCauseCode::IfExpressionWithNoElse); - assert!(arm_ty.is_unit()); - coercion.coerce_forced_unit(self, &cause, &mut |_| (), true); - } else { - let cause = if i == 0 { + let arm_span = if let hir::ExprKind::Block(blk, _) = &arm.body.node { + // Point at the block expr instead of the entire block + blk.expr.as_ref().map(|e| e.span).unwrap_or(arm.body.span) + } else { + arm.body.span + }; + let (span, code) = match i { // The reason for the first arm to fail is not that the match arms diverge, // but rather that there's a prior obligation that doesn't hold. - self.cause(arm_span, ObligationCauseCode::BlockTailExpression(arm.body.hir_id)) - } else { - self.cause(expr.span, ObligationCauseCode::MatchExpressionArm { + 0 => (arm_span, ObligationCauseCode::BlockTailExpression(arm.body.hir_id)), + _ => (span, ObligationCauseCode::MatchExpressionArm { arm_span, source: match_src, prior_arms: other_arms.clone(), last_ty: prior_arm_ty.unwrap(), discrim_hir_id: discrim.hir_id, - }) + }), }; + let cause = self.cause(span, code); coercion.coerce(self, &cause, &arm.body, arm_ty); - } - other_arms.push(arm_span); - if other_arms.len() > 5 { - other_arms.remove(0); + other_arms.push(arm_span); + if other_arms.len() > 5 { + other_arms.remove(0); + } } prior_arm_ty = Some(arm_ty); } @@ -792,6 +741,251 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); coercion.complete(self) } + /// When the previously checked expression (the scrutinee) diverges, + /// warn the user about the match arms being unreachable. + fn warn_arms_when_scrutinee_diverges(&self, arms: &'gcx [hir::Arm], source_if: bool) { + if self.diverges.get().always() { + let msg = if source_if { "block in `if` expression" } else { "arm" }; + for arm in arms { + self.warn_if_unreachable(arm.body.hir_id, arm.body.span, msg); + } + } + } + + /// Handle the fallback arm of a desugared if(-let) like a missing else. + fn if_fallback_coercion( + &self, + span: Span, + then_expr: &'gcx hir::Expr, + coercion: &mut CoerceMany<'gcx, 'tcx, '_, rustc::hir::Arm>, + ) { + // If this `if` expr is the parent's function return expr, + // the cause of the type coercion is the return type, point at it. (#25228) + let ret_reason = self.maybe_get_coercion_reason(then_expr.hir_id, span); + let cause = self.cause(span, ObligationCauseCode::IfExpressionWithNoElse); + coercion.coerce_forced_unit(self, &cause, &mut |err| { + if let Some((span, msg)) = &ret_reason { + err.span_label(*span, msg.as_str()); + } else if let ExprKind::Block(block, _) = &then_expr.node { + if let Some(expr) = &block.expr { + err.span_label(expr.span, "found here".to_string()); + } + } + err.note("`if` expressions without `else` evaluate to `()`"); + err.help("consider adding an `else` block that evaluates to the expected type"); + }, ret_reason.is_none()); + } + + fn maybe_get_coercion_reason(&self, hir_id: hir::HirId, span: Span) -> Option<(Span, String)> { + use hir::Node::{Block, Item, Local}; + + let node = self.tcx.hir().get_by_hir_id(self.tcx.hir().get_parent_node_by_hir_id( + self.tcx.hir().get_parent_node_by_hir_id(hir_id), + )); + if let Block(block) = node { + // check that the body's parent is an fn + let parent = self.tcx.hir().get_by_hir_id( + self.tcx.hir().get_parent_node_by_hir_id( + self.tcx.hir().get_parent_node_by_hir_id(block.hir_id), + ), + ); + if let (Some(expr), Item(hir::Item { + node: hir::ItemKind::Fn(..), .. + })) = (&block.expr, parent) { + // check that the `if` expr without `else` is the fn body's expr + if expr.span == span { + return self.get_fn_decl(hir_id).map(|(fn_decl, _)| ( + fn_decl.output.span(), + format!("expected `{}` because of this return type", fn_decl.output), + )); + } + } + } + if let Local(hir::Local { ty: Some(_), pat, .. }) = node { + return Some((pat.span, "expected because of this assignment".to_string())); + } + None + } + + fn if_cause( + &self, + span: Span, + then_expr: &'gcx hir::Expr, + else_expr: &'gcx hir::Expr, + then_ty: Ty<'tcx>, + else_ty: Ty<'tcx>, + ) -> ObligationCause<'tcx> { + let mut outer_sp = if self.tcx.sess.source_map().is_multiline(span) { + // The `if`/`else` isn't in one line in the output, include some context to make it + // clear it is an if/else expression: + // ``` + // LL | let x = if true { + // | _____________- + // LL || 10i32 + // || ----- expected because of this + // LL || } else { + // LL || 10u32 + // || ^^^^^ expected i32, found u32 + // LL || }; + // ||_____- if and else have incompatible types + // ``` + Some(span) + } else { + // The entire expression is in one line, only point at the arms + // ``` + // LL | let x = if true { 10i32 } else { 10u32 }; + // | ----- ^^^^^ expected i32, found u32 + // | | + // | expected because of this + // ``` + None + }; + + let mut remove_semicolon = None; + let error_sp = if let ExprKind::Block(block, _) = &else_expr.node { + if let Some(expr) = &block.expr { + expr.span + } else if let Some(stmt) = block.stmts.last() { + // possibly incorrect trailing `;` in the else arm + remove_semicolon = self.could_remove_semicolon(block, then_ty); + stmt.span + } else { // empty block, point at its entirety + // Avoid overlapping spans that aren't as readable: + // ``` + // 2 | let x = if true { + // | _____________- + // 3 | | 3 + // | | - expected because of this + // 4 | | } else { + // | |____________^ + // 5 | || + // 6 | || }; + // | || ^ + // | ||_____| + // | |______if and else have incompatible types + // | expected integer, found () + // ``` + // by not pointing at the entire expression: + // ``` + // 2 | let x = if true { + // | ------- if and else have incompatible types + // 3 | 3 + // | - expected because of this + // 4 | } else { + // | ____________^ + // 5 | | + // 6 | | }; + // | |_____^ expected integer, found () + // ``` + if outer_sp.is_some() { + outer_sp = Some(self.tcx.sess.source_map().def_span(span)); + } + else_expr.span + } + } else { // shouldn't happen unless the parser has done something weird + else_expr.span + }; + + // Compute `Span` of `then` part of `if`-expression: + let then_sp = if let ExprKind::Block(block, _) = &then_expr.node { + if let Some(expr) = &block.expr { + expr.span + } else if let Some(stmt) = block.stmts.last() { + // possibly incorrect trailing `;` in the else arm + remove_semicolon = remove_semicolon.or(self.could_remove_semicolon(block, else_ty)); + stmt.span + } else { // empty block, point at its entirety + outer_sp = None; // same as in `error_sp`, cleanup output + then_expr.span + } + } else { // shouldn't happen unless the parser has done something weird + then_expr.span + }; + + // Finally construct the cause: + self.cause(error_sp, ObligationCauseCode::IfExpression { + then: then_sp, + outer: outer_sp, + semicolon: remove_semicolon, + }) + } + + fn demand_discriminant_type( + &self, + arms: &'gcx [hir::Arm], + discrim: &'gcx hir::Expr, + ) -> Ty<'tcx> { + // Not entirely obvious: if matches may create ref bindings, we want to + // use the *precise* type of the discriminant, *not* some supertype, as + // the "discriminant type" (issue #23116). + // + // arielb1 [writes here in this comment thread][c] that there + // is certainly *some* potential danger, e.g., for an example + // like: + // + // [c]: https://github.com/rust-lang/rust/pull/43399#discussion_r130223956 + // + // ``` + // let Foo(x) = f()[0]; + // ``` + // + // Then if the pattern matches by reference, we want to match + // `f()[0]` as a lexpr, so we can't allow it to be + // coerced. But if the pattern matches by value, `f()[0]` is + // still syntactically a lexpr, but we *do* want to allow + // coercions. + // + // However, *likely* we are ok with allowing coercions to + // happen if there are no explicit ref mut patterns - all + // implicit ref mut patterns must occur behind a reference, so + // they will have the "correct" variance and lifetime. + // + // This does mean that the following pattern would be legal: + // + // ``` + // struct Foo(Bar); + // struct Bar(u32); + // impl Deref for Foo { + // type Target = Bar; + // fn deref(&self) -> &Bar { &self.0 } + // } + // impl DerefMut for Foo { + // fn deref_mut(&mut self) -> &mut Bar { &mut self.0 } + // } + // fn foo(x: &mut Foo) { + // { + // let Bar(z): &mut Bar = x; + // *z = 42; + // } + // assert_eq!(foo.0.0, 42); + // } + // ``` + // + // FIXME(tschottdorf): don't call contains_explicit_ref_binding, which + // is problematic as the HIR is being scraped, but ref bindings may be + // implicit after #42640. We need to make sure that pat_adjustments + // (once introduced) is populated by the time we get here. + // + // See #44848. + let contains_ref_bindings = arms.iter() + .filter_map(|a| a.contains_explicit_ref_binding()) + .max_by_key(|m| match *m { + hir::MutMutable => 1, + hir::MutImmutable => 0, + }); + + if let Some(m) = contains_ref_bindings { + self.check_expr_with_needs(discrim, Needs::maybe_mut_place(m)) + } else { + // ...but otherwise we want to use any supertype of the + // discriminant. This is sort of a workaround, see note (*) in + // `check_pat` for some details. + let discrim_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(discrim.span)); + self.check_expr_has_type_or_error(discrim, discrim_ty); + discrim_ty + } + } + fn check_pat_struct( &self, pat: &'gcx hir::Pat, @@ -800,7 +994,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); etc: bool, expected: Ty<'tcx>, def_bm: ty::BindingMode, - match_discrim_span: Option, + discrim_span: Option, ) -> Ty<'tcx> { // Resolve the path and check the definition for errors. @@ -809,18 +1003,13 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); variant_ty } else { for field in fields { - self.check_pat_walk( - &field.node.pat, - self.tcx.types.err, - def_bm, - match_discrim_span, - ); + self.check_pat_walk(&field.node.pat, self.tcx.types.err, def_bm, discrim_span); } return self.tcx.types.err; }; // Type-check the path. - self.demand_eqtype_pat(pat.span, expected, pat_ty, match_discrim_span); + self.demand_eqtype_pat(pat.span, expected, pat_ty, discrim_span); // Type-check subpatterns. if self.check_struct_pat_fields(pat_ty, pat.hir_id, pat.span, variant, fields, etc, def_bm) diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index d21ceb983f8f4..008975068e581 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -1248,12 +1248,8 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E> augment_error(&mut db); } - if expression.filter(|e| fcx.is_assign_to_bool(e, expected)).is_some() { - // Error reported in `check_assign` so avoid emitting error again. - db.delay_as_bug(); - } else { - db.emit(); - } + // Error possibly reported in `check_assign` so avoid emitting error again. + db.emit_unless(expression.filter(|e| fcx.is_assign_to_bool(e, expected)).is_some()); self.final_ty = Some(fcx.tcx.types.err); } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 965f52be31cde..2b519731eeedb 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -117,6 +117,7 @@ use rustc::ty::subst::{UnpackedKind, Subst, InternalSubsts, SubstsRef, UserSelfT use rustc::ty::util::{Representability, IntTypeExt, Discr}; use rustc::ty::layout::VariantIdx; use syntax_pos::{self, BytePos, Span, MultiSpan}; +use syntax_pos::hygiene::CompilerDesugaringKind; use syntax::ast; use syntax::attr; use syntax::feature_gate::{GateIssue, emit_feature_err}; @@ -1086,12 +1087,8 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, // Add formal parameters. for (arg_ty, arg) in fn_sig.inputs().iter().zip(&body.arguments) { // Check the pattern. - fcx.check_pat_walk( - &arg.pat, - arg_ty, - ty::BindingMode::BindByValue(hir::Mutability::MutImmutable), - None, - ); + let binding_mode = ty::BindingMode::BindByValue(hir::Mutability::MutImmutable); + fcx.check_pat_walk(&arg.pat, arg_ty, binding_mode, None); // Check that argument is Sized. // The check for a non-trivial pattern is a hack to avoid duplicate warnings @@ -2045,15 +2042,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// Produces warning on the given node, if the current point in the /// function is unreachable, and there hasn't been another warning. fn warn_if_unreachable(&self, id: hir::HirId, span: Span, kind: &str) { - if self.diverges.get() == Diverges::Always { + if self.diverges.get() == Diverges::Always && + // If span arose from a desugaring of `if` then it is the condition itself, + // which diverges, that we are about to lint on. This gives suboptimal diagnostics + // and so we stop here and allow the block of the `if`-expression to be linted instead. + !span.is_compiler_desugaring(CompilerDesugaringKind::IfTemporary) { self.diverges.set(Diverges::WarnedAlways); debug!("warn_if_unreachable: id={:?} span={:?} kind={}", id, span, kind); - self.tcx().lint_hir( - lint::builtin::UNREACHABLE_CODE, - id, span, - &format!("unreachable {}", kind)); + let msg = format!("unreachable {}", kind); + self.tcx().lint_hir(lint::builtin::UNREACHABLE_CODE, id, span, &msg); } } @@ -3161,13 +3160,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) { - if self.is_assign_to_bool(expr, expected_ty) { - // Error reported in `check_assign` so avoid emitting error again. - // FIXME(centril): Consider removing if/when `if` desugars to `match`. - err.delay_as_bug(); - } else { - err.emit(); - } + let expr = match &expr.node { + ExprKind::DropTemps(expr) => expr, + _ => expr, + }; + // Error possibly reported in `check_assign` so avoid emitting error again. + err.emit_unless(self.is_assign_to_bool(expr, expected_ty)); } ty } @@ -3330,194 +3328,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { return_expr_ty); } - // A generic function for checking the 'then' and 'else' clauses in an 'if' - // or 'if-else' expression. - fn check_then_else(&self, - cond_expr: &'gcx hir::Expr, - then_expr: &'gcx hir::Expr, - opt_else_expr: Option<&'gcx hir::Expr>, - sp: Span, - expected: Expectation<'tcx>) -> Ty<'tcx> { - let cond_ty = self.check_expr_has_type_or_error(cond_expr, self.tcx.types.bool); - let cond_diverges = self.diverges.get(); - self.diverges.set(Diverges::Maybe); - - let expected = expected.adjust_for_branches(self); - let then_ty = self.check_expr_with_expectation(then_expr, expected); - let then_diverges = self.diverges.get(); - self.diverges.set(Diverges::Maybe); - - // We've already taken the expected type's preferences - // into account when typing the `then` branch. To figure - // out the initial shot at a LUB, we thus only consider - // `expected` if it represents a *hard* constraint - // (`only_has_type`); otherwise, we just go with a - // fresh type variable. - let coerce_to_ty = expected.coercion_target_type(self, sp); - let mut coerce: DynamicCoerceMany<'_, '_> = CoerceMany::new(coerce_to_ty); - - coerce.coerce(self, &self.misc(sp), then_expr, then_ty); - - if let Some(else_expr) = opt_else_expr { - let else_ty = self.check_expr_with_expectation(else_expr, expected); - let else_diverges = self.diverges.get(); - - let mut outer_sp = if self.tcx.sess.source_map().is_multiline(sp) { - // The `if`/`else` isn't in one line in the output, include some context to make it - // clear it is an if/else expression: - // ``` - // LL | let x = if true { - // | _____________- - // LL || 10i32 - // || ----- expected because of this - // LL || } else { - // LL || 10u32 - // || ^^^^^ expected i32, found u32 - // LL || }; - // ||_____- if and else have incompatible types - // ``` - Some(sp) - } else { - // The entire expression is in one line, only point at the arms - // ``` - // LL | let x = if true { 10i32 } else { 10u32 }; - // | ----- ^^^^^ expected i32, found u32 - // | | - // | expected because of this - // ``` - None - }; - let mut remove_semicolon = None; - let error_sp = if let ExprKind::Block(block, _) = &else_expr.node { - if let Some(expr) = &block.expr { - expr.span - } else if let Some(stmt) = block.stmts.last() { - // possibly incorrect trailing `;` in the else arm - remove_semicolon = self.could_remove_semicolon(block, then_ty); - stmt.span - } else { // empty block, point at its entirety - // Avoid overlapping spans that aren't as readable: - // ``` - // 2 | let x = if true { - // | _____________- - // 3 | | 3 - // | | - expected because of this - // 4 | | } else { - // | |____________^ - // 5 | || - // 6 | || }; - // | || ^ - // | ||_____| - // | |______if and else have incompatible types - // | expected integer, found () - // ``` - // by not pointing at the entire expression: - // ``` - // 2 | let x = if true { - // | ------- if and else have incompatible types - // 3 | 3 - // | - expected because of this - // 4 | } else { - // | ____________^ - // 5 | | - // 6 | | }; - // | |_____^ expected integer, found () - // ``` - if outer_sp.is_some() { - outer_sp = Some(self.tcx.sess.source_map().def_span(sp)); - } - else_expr.span - } - } else { // shouldn't happen unless the parser has done something weird - else_expr.span - }; - let then_sp = if let ExprKind::Block(block, _) = &then_expr.node { - if let Some(expr) = &block.expr { - expr.span - } else if let Some(stmt) = block.stmts.last() { - // possibly incorrect trailing `;` in the else arm - remove_semicolon = remove_semicolon.or( - self.could_remove_semicolon(block, else_ty)); - stmt.span - } else { // empty block, point at its entirety - outer_sp = None; // same as in `error_sp`, cleanup output - then_expr.span - } - } else { // shouldn't happen unless the parser has done something weird - then_expr.span - }; - - let if_cause = self.cause(error_sp, ObligationCauseCode::IfExpression { - then: then_sp, - outer: outer_sp, - semicolon: remove_semicolon, - }); - - coerce.coerce(self, &if_cause, else_expr, else_ty); - - // We won't diverge unless both branches do (or the condition does). - self.diverges.set(cond_diverges | then_diverges & else_diverges); - } else { - // If this `if` expr is the parent's function return expr, the cause of the type - // coercion is the return type, point at it. (#25228) - let ret_reason = self.maybe_get_coercion_reason(then_expr.hir_id, sp); - - let else_cause = self.cause(sp, ObligationCauseCode::IfExpressionWithNoElse); - coerce.coerce_forced_unit(self, &else_cause, &mut |err| { - if let Some((sp, msg)) = &ret_reason { - err.span_label(*sp, msg.as_str()); - } else if let ExprKind::Block(block, _) = &then_expr.node { - if let Some(expr) = &block.expr { - err.span_label(expr.span, "found here".to_string()); - } - } - err.note("`if` expressions without `else` evaluate to `()`"); - err.help("consider adding an `else` block that evaluates to the expected type"); - }, ret_reason.is_none()); - - // If the condition is false we can't diverge. - self.diverges.set(cond_diverges); - } - - let result_ty = coerce.complete(self); - if cond_ty.references_error() { - self.tcx.types.err - } else { - result_ty - } - } - - fn maybe_get_coercion_reason(&self, hir_id: hir::HirId, sp: Span) -> Option<(Span, String)> { - let node = self.tcx.hir().get_by_hir_id(self.tcx.hir().get_parent_node_by_hir_id( - self.tcx.hir().get_parent_node_by_hir_id(hir_id), - )); - if let Node::Block(block) = node { - // check that the body's parent is an fn - let parent = self.tcx.hir().get_by_hir_id( - self.tcx.hir().get_parent_node_by_hir_id( - self.tcx.hir().get_parent_node_by_hir_id(block.hir_id), - ), - ); - if let (Some(expr), Node::Item(hir::Item { - node: hir::ItemKind::Fn(..), .. - })) = (&block.expr, parent) { - // check that the `if` expr without `else` is the fn body's expr - if expr.span == sp { - return self.get_fn_decl(hir_id).map(|(fn_decl, _)| ( - fn_decl.output.span(), - format!("expected `{}` because of this return type", fn_decl.output), - )); - } - } - } - if let Node::Local(hir::Local { - ty: Some(_), pat, .. - }) = node { - return Some((pat.span, "expected because of this assignment".to_string())); - } - None - } - // Check field access expressions fn check_field(&self, expr: &'gcx hir::Expr, @@ -4062,7 +3872,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { match expr.node { ExprKind::Block(..) | ExprKind::Loop(..) | ExprKind::While(..) | - ExprKind::If(..) | ExprKind::Match(..) => {} + ExprKind::Match(..) => {} _ => self.warn_if_unreachable(expr.hir_id, expr.span, "expression") } @@ -4444,10 +4254,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ExprKind::Assign(ref lhs, ref rhs) => { self.check_assign(expr, expected, lhs, rhs) } - ExprKind::If(ref cond, ref then_expr, ref opt_else_expr) => { - self.check_then_else(&cond, then_expr, opt_else_expr.as_ref().map(|e| &**e), - expr.span, expected) - } ExprKind::While(ref cond, ref body, _) => { let ctxt = BreakableCtxt { // cannot use break with a value from a while loop @@ -5261,7 +5067,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { match expression.node { ExprKind::Call(..) | ExprKind::MethodCall(..) | - ExprKind::If(..) | ExprKind::While(..) | ExprKind::Loop(..) | ExprKind::Match(..) | diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index a901afdff43e6..1d9dc26bf6092 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -591,6 +591,10 @@ impl ExpnFormat { /// The kind of compiler desugaring. #[derive(Clone, Copy, Hash, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] pub enum CompilerDesugaringKind { + /// We desugar `if c { i } else { e }` to `match $ExprKind::Use(c) { true => i, _ => e }`. + /// However, we do not want to blame `c` for unreachability but rather say that `i` + /// is unreachable. This desugaring kind allows us to avoid blaming `c`. + IfTemporary, QuestionMark, TryBlock, /// Desugaring of an `impl Trait` in return type position @@ -605,6 +609,7 @@ pub enum CompilerDesugaringKind { impl CompilerDesugaringKind { pub fn name(self) -> Symbol { Symbol::intern(match self { + CompilerDesugaringKind::IfTemporary => "if", CompilerDesugaringKind::Async => "async", CompilerDesugaringKind::Await => "await", CompilerDesugaringKind::QuestionMark => "?", From 99039689f0c097703c7258c339b05d1c88e54ff8 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 24 Apr 2019 12:50:05 +0200 Subject: [PATCH 168/212] Adjust mir-opt tests for new HIR without If --- src/test/mir-opt/issue-38669.rs | 8 ++++--- src/test/mir-opt/loop_test.rs | 21 ++++++++++--------- .../mir-opt/nll/region-subtyping-basic.rs | 6 +++--- src/test/mir-opt/simplify_if.rs | 12 ++++++----- 4 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/test/mir-opt/issue-38669.rs b/src/test/mir-opt/issue-38669.rs index 047e623941b71..e8ab690bb4648 100644 --- a/src/test/mir-opt/issue-38669.rs +++ b/src/test/mir-opt/issue-38669.rs @@ -27,15 +27,17 @@ fn main() { // bb3: { // StorageLive(_4); // _4 = _1; -// switchInt(move _4) -> [false: bb5, otherwise: bb4]; +// FakeRead(ForMatchedPlace, _4); +// switchInt(_4) -> [false: bb5, otherwise: bb4]; // } -// bb4: { +// ... +// bb7: { // _0 = (); // StorageDead(_4); // StorageDead(_1); // return; // } -// bb5: { +// bb8: { // _3 = (); // StorageDead(_4); // _1 = const true; diff --git a/src/test/mir-opt/loop_test.rs b/src/test/mir-opt/loop_test.rs index 34891ee70b5c6..e75955b9b2440 100644 --- a/src/test/mir-opt/loop_test.rs +++ b/src/test/mir-opt/loop_test.rs @@ -22,19 +22,20 @@ fn main() { // resume; // } // ... -// bb3: { // Entry into the loop +// bb6: { // Entry into the loop // _1 = (); -// goto -> bb4; +// StorageDead(_2); +// goto -> bb7; // } -// bb4: { // The loop_block -// falseUnwind -> [real: bb5, cleanup: bb1]; +// bb7: { // The loop_block +// falseUnwind -> [real: bb8, cleanup: bb1]; // } -// bb5: { // The loop body (body_block) -// StorageLive(_5); -// _5 = const 1i32; -// FakeRead(ForLet, _5); -// StorageDead(_5); -// goto -> bb4; +// bb8: { // The loop body (body_block) +// StorageLive(_6); +// _6 = const 1i32; +// FakeRead(ForLet, _6); +// StorageDead(_6); +// goto -> bb7; // } // ... // END rustc.main.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/nll/region-subtyping-basic.rs b/src/test/mir-opt/nll/region-subtyping-basic.rs index bb27461bb1e0f..622cc99983002 100644 --- a/src/test/mir-opt/nll/region-subtyping-basic.rs +++ b/src/test/mir-opt/nll/region-subtyping-basic.rs @@ -22,9 +22,9 @@ fn main() { // END RUST SOURCE // START rustc.main.nll.0.mir -// | '_#2r | U0 | {bb2[0..=5], bb3[0..=1]} -// | '_#3r | U0 | {bb2[1..=5], bb3[0..=1]} -// | '_#4r | U0 | {bb2[4..=5], bb3[0..=1]} +// | '_#2r | U0 | {bb2[0..=8], bb3[0], bb6[0..=1]} +// | '_#3r | U0 | {bb2[1..=8], bb3[0], bb6[0..=1]} +// | '_#4r | U0 | {bb2[4..=8], bb3[0], bb6[0..=1]} // END rustc.main.nll.0.mir // START rustc.main.nll.0.mir // let _2: &'_#3r usize; diff --git a/src/test/mir-opt/simplify_if.rs b/src/test/mir-opt/simplify_if.rs index f6e6c6baf7a46..b2a99a6d446bb 100644 --- a/src/test/mir-opt/simplify_if.rs +++ b/src/test/mir-opt/simplify_if.rs @@ -5,13 +5,15 @@ fn main() { } // END RUST SOURCE -// START rustc.main.SimplifyBranches-initial.before.mir +// START rustc.main.SimplifyBranches-after-copy-prop.before.mir // bb0: { -// switchInt(const false) -> [false: bb3, otherwise: bb2]; +// ... +// switchInt(const false) -> [false: bb3, otherwise: bb1]; // } -// END rustc.main.SimplifyBranches-initial.before.mir -// START rustc.main.SimplifyBranches-initial.after.mir +// END rustc.main.SimplifyBranches-after-copy-prop.before.mir +// START rustc.main.SimplifyBranches-after-copy-prop.after.mir // bb0: { +// ... // goto -> bb3; // } -// END rustc.main.SimplifyBranches-initial.after.mir +// END rustc.main.SimplifyBranches-after-copy-prop.after.mir From 8d1e5b8b396e06778583ad62177430d2b95015f5 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 19 Mar 2019 04:47:07 +0100 Subject: [PATCH 169/212] Various test changes --- src/test/incremental/hashes/if_expressions.rs | 4 +- src/test/run-pass/if-ret.stderr | 8 ++ src/test/ui/if/if-let-arm-types.rs | 5 +- src/test/ui/if/if-let-arm-types.stderr | 8 +- src/test/ui/if/if-without-else-as-fn-expr.rs | 30 +++++ .../ui/if/if-without-else-as-fn-expr.stderr | 123 +++++++++++++++++- src/test/ui/issues/issue-19991.stderr | 3 + src/test/ui/issues/issue-50577.rs | 1 + src/test/ui/issues/issue-50577.stderr | 15 ++- src/test/ui/reachable/expr_if.rs | 2 +- src/test/ui/reachable/expr_if.stderr | 20 ++- 11 files changed, 200 insertions(+), 19 deletions(-) create mode 100644 src/test/run-pass/if-ret.stderr diff --git a/src/test/incremental/hashes/if_expressions.rs b/src/test/incremental/hashes/if_expressions.rs index fba7869af42f2..6bc7d286e3adb 100644 --- a/src/test/incremental/hashes/if_expressions.rs +++ b/src/test/incremental/hashes/if_expressions.rs @@ -94,7 +94,7 @@ pub fn add_else_branch(x: bool) -> u32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="HirBody")] #[rustc_clean(cfg="cfail3")] pub fn add_else_branch(x: bool) -> u32 { let mut ret = 1; @@ -191,7 +191,7 @@ pub fn add_else_branch_if_let(x: Option) -> u32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="HirBody")] #[rustc_clean(cfg="cfail3")] pub fn add_else_branch_if_let(x: Option) -> u32 { let mut ret = 1; diff --git a/src/test/run-pass/if-ret.stderr b/src/test/run-pass/if-ret.stderr new file mode 100644 index 0000000000000..a64281833e5cb --- /dev/null +++ b/src/test/run-pass/if-ret.stderr @@ -0,0 +1,8 @@ +warning: unreachable block in `if` expression + --> $DIR/if-ret.rs:4:24 + | +LL | fn foo() { if (return) { } } + | ^^^ + | + = note: #[warn(unreachable_code)] on by default + diff --git a/src/test/ui/if/if-let-arm-types.rs b/src/test/ui/if/if-let-arm-types.rs index 819f5dd1cfc35..0f8815f0479f5 100644 --- a/src/test/ui/if/if-let-arm-types.rs +++ b/src/test/ui/if/if-let-arm-types.rs @@ -1,11 +1,12 @@ fn main() { if let Some(b) = None { - //~^ NOTE if let` arms have incompatible types + //~^ NOTE if and else have incompatible types () + //~^ NOTE expected because of this } else { 1 }; - //~^^ ERROR: `if let` arms have incompatible types + //~^^ ERROR: if and else have incompatible types //~| NOTE expected (), found integer //~| NOTE expected type `()` } diff --git a/src/test/ui/if/if-let-arm-types.stderr b/src/test/ui/if/if-let-arm-types.stderr index b986973fe91f4..ff88de20f76cc 100644 --- a/src/test/ui/if/if-let-arm-types.stderr +++ b/src/test/ui/if/if-let-arm-types.stderr @@ -1,14 +1,16 @@ -error[E0308]: `if let` arms have incompatible types - --> $DIR/if-let-arm-types.rs:6:9 +error[E0308]: if and else have incompatible types + --> $DIR/if-let-arm-types.rs:7:9 | LL | / if let Some(b) = None { LL | | LL | | () + | | -- expected because of this +LL | | LL | | } else { LL | | 1 | | ^ expected (), found integer LL | | }; - | |_____- `if let` arms have incompatible types + | |_____- if and else have incompatible types | = note: expected type `()` found type `{integer}` diff --git a/src/test/ui/if/if-without-else-as-fn-expr.rs b/src/test/ui/if/if-without-else-as-fn-expr.rs index 67e4445629f8c..15892de83854c 100644 --- a/src/test/ui/if/if-without-else-as-fn-expr.rs +++ b/src/test/ui/if/if-without-else-as-fn-expr.rs @@ -3,6 +3,7 @@ fn foo(bar: usize) -> usize { return 3; } //~^^^ ERROR if may be missing an else clause + //~| ERROR mismatched types [E0308] } fn foo2(bar: usize) -> usize { @@ -10,6 +11,7 @@ fn foo2(bar: usize) -> usize { return 3; }; //~^^^ ERROR if may be missing an else clause + //~| ERROR mismatched types [E0308] x } @@ -18,8 +20,36 @@ fn foo3(bar: usize) -> usize { 3 } //~^^^ ERROR if may be missing an else clause + //~| ERROR mismatched types [E0308] } +fn foo_let(bar: usize) -> usize { + if let 0 = 1 { + return 3; + } + //~^^^ ERROR if may be missing an else clause + //~| ERROR mismatched types [E0308] +} + +fn foo2_let(bar: usize) -> usize { + let x: usize = if let 0 = 1 { + return 3; + }; + //~^^^ ERROR if may be missing an else clause + //~| ERROR mismatched types [E0308] + x +} + +fn foo3_let(bar: usize) -> usize { + if let 0 = 1 { + 3 + } + //~^^^ ERROR if may be missing an else clause + //~| ERROR mismatched types [E0308] +} + +// FIXME(60254): deduplicate first error in favor of second. + fn main() { let _ = foo(1); } diff --git a/src/test/ui/if/if-without-else-as-fn-expr.stderr b/src/test/ui/if/if-without-else-as-fn-expr.stderr index 0ba72726ca787..06600b1cb9aea 100644 --- a/src/test/ui/if/if-without-else-as-fn-expr.stderr +++ b/src/test/ui/if/if-without-else-as-fn-expr.stderr @@ -1,3 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/if-without-else-as-fn-expr.rs:2:5 + | +LL | / if bar % 5 == 0 { +LL | | return 3; +LL | | } + | |_____^ expected usize, found () + | + = note: expected type `usize` + found type `()` + error[E0317]: if may be missing an else clause --> $DIR/if-without-else-as-fn-expr.rs:2:5 | @@ -13,8 +24,20 @@ LL | | } = note: `if` expressions without `else` evaluate to `()` = help: consider adding an `else` block that evaluates to the expected type +error[E0308]: mismatched types + --> $DIR/if-without-else-as-fn-expr.rs:10:20 + | +LL | let x: usize = if bar % 5 == 0 { + | ____________________^ +LL | | return 3; +LL | | }; + | |_____^ expected usize, found () + | + = note: expected type `usize` + found type `()` + error[E0317]: if may be missing an else clause - --> $DIR/if-without-else-as-fn-expr.rs:9:20 + --> $DIR/if-without-else-as-fn-expr.rs:10:20 | LL | let x: usize = if bar % 5 == 0 { | _________-__________^ @@ -29,8 +52,19 @@ LL | | }; = note: `if` expressions without `else` evaluate to `()` = help: consider adding an `else` block that evaluates to the expected type +error[E0308]: mismatched types + --> $DIR/if-without-else-as-fn-expr.rs:19:5 + | +LL | / if bar % 5 == 0 { +LL | | 3 +LL | | } + | |_____^ expected usize, found () + | + = note: expected type `usize` + found type `()` + error[E0317]: if may be missing an else clause - --> $DIR/if-without-else-as-fn-expr.rs:17:5 + --> $DIR/if-without-else-as-fn-expr.rs:19:5 | LL | fn foo3(bar: usize) -> usize { | ----- expected `usize` because of this return type @@ -44,6 +78,87 @@ LL | | } = note: `if` expressions without `else` evaluate to `()` = help: consider adding an `else` block that evaluates to the expected type -error: aborting due to 3 previous errors +error[E0308]: mismatched types + --> $DIR/if-without-else-as-fn-expr.rs:27:5 + | +LL | / if let 0 = 1 { +LL | | return 3; +LL | | } + | |_____^ expected usize, found () + | + = note: expected type `usize` + found type `()` + +error[E0317]: if may be missing an else clause + --> $DIR/if-without-else-as-fn-expr.rs:27:5 + | +LL | fn foo_let(bar: usize) -> usize { + | ----- expected `usize` because of this return type +LL | / if let 0 = 1 { +LL | | return 3; +LL | | } + | |_____^ expected usize, found () + | + = note: expected type `usize` + found type `()` + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type + +error[E0308]: mismatched types + --> $DIR/if-without-else-as-fn-expr.rs:35:20 + | +LL | let x: usize = if let 0 = 1 { + | ____________________^ +LL | | return 3; +LL | | }; + | |_____^ expected usize, found () + | + = note: expected type `usize` + found type `()` + +error[E0317]: if may be missing an else clause + --> $DIR/if-without-else-as-fn-expr.rs:35:20 + | +LL | let x: usize = if let 0 = 1 { + | _________-__________^ + | | | + | | expected because of this assignment +LL | | return 3; +LL | | }; + | |_____^ expected usize, found () + | + = note: expected type `usize` + found type `()` + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type + +error[E0308]: mismatched types + --> $DIR/if-without-else-as-fn-expr.rs:44:5 + | +LL | / if let 0 = 1 { +LL | | 3 +LL | | } + | |_____^ expected usize, found () + | + = note: expected type `usize` + found type `()` + +error[E0317]: if may be missing an else clause + --> $DIR/if-without-else-as-fn-expr.rs:44:5 + | +LL | fn foo3_let(bar: usize) -> usize { + | ----- expected `usize` because of this return type +LL | / if let 0 = 1 { +LL | | 3 +LL | | } + | |_____^ expected usize, found () + | + = note: expected type `usize` + found type `()` + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type + +error: aborting due to 12 previous errors -For more information about this error, try `rustc --explain E0317`. +Some errors have detailed explanations: E0308, E0317. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/issues/issue-19991.stderr b/src/test/ui/issues/issue-19991.stderr index 4c6d150229a3e..d9ea910adef50 100644 --- a/src/test/ui/issues/issue-19991.stderr +++ b/src/test/ui/issues/issue-19991.stderr @@ -6,11 +6,14 @@ LL | | LL | | LL | | LL | | 765 + | | --- found here LL | | }; | |_____^ expected (), found integer | = note: expected type `()` found type `{integer}` + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50577.rs b/src/test/ui/issues/issue-50577.rs index f0f1dc6c28667..bf892a8daa27f 100644 --- a/src/test/ui/issues/issue-50577.rs +++ b/src/test/ui/issues/issue-50577.rs @@ -2,5 +2,6 @@ fn main() { enum Foo { Drop = assert_eq!(1, 1) //~^ ERROR if may be missing an else clause + //~| ERROR mismatched types [E0308] } } diff --git a/src/test/ui/issues/issue-50577.stderr b/src/test/ui/issues/issue-50577.stderr index 0c3ba2ea4f94d..413c8c5c80b52 100644 --- a/src/test/ui/issues/issue-50577.stderr +++ b/src/test/ui/issues/issue-50577.stderr @@ -1,3 +1,13 @@ +error[E0308]: mismatched types + --> $DIR/issue-50577.rs:3:16 + | +LL | Drop = assert_eq!(1, 1) + | ^^^^^^^^^^^^^^^^ expected isize, found () + | + = note: expected type `isize` + found type `()` + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + error[E0317]: if may be missing an else clause --> $DIR/issue-50577.rs:3:16 | @@ -13,6 +23,7 @@ LL | Drop = assert_eq!(1, 1) = help: consider adding an `else` block that evaluates to the expected type = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0317`. +Some errors have detailed explanations: E0308, E0317. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/reachable/expr_if.rs b/src/test/ui/reachable/expr_if.rs index ed43bd8c6895e..a3d54892de5bb 100644 --- a/src/test/ui/reachable/expr_if.rs +++ b/src/test/ui/reachable/expr_if.rs @@ -4,7 +4,7 @@ #![deny(unreachable_code)] fn foo() { - if {return} { + if {return} { //~ ERROR unreachable block in `if` expression println!("Hello, world!"); } } diff --git a/src/test/ui/reachable/expr_if.stderr b/src/test/ui/reachable/expr_if.stderr index d11471da1a6a3..f1690e595e5d1 100644 --- a/src/test/ui/reachable/expr_if.stderr +++ b/src/test/ui/reachable/expr_if.stderr @@ -1,15 +1,25 @@ -error: unreachable statement - --> $DIR/expr_if.rs:27:5 +error: unreachable block in `if` expression + --> $DIR/expr_if.rs:7:17 | -LL | println!("But I am."); - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | if {return} { + | _________________^ +LL | | println!("Hello, world!"); +LL | | } + | |_____^ | note: lint level defined here --> $DIR/expr_if.rs:4:9 | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ + +error: unreachable statement + --> $DIR/expr_if.rs:27:5 + | +LL | println!("But I am."); + | ^^^^^^^^^^^^^^^^^^^^^^ + | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 2 previous errors From efd3733f9d33e814629c6d14ddee92d44f62205c Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 25 Apr 2019 05:48:26 +0200 Subject: [PATCH 170/212] add test checking that 'if cond { .. }' where 'cond: &mut? bool' isn't accepted. --- src/test/ui/if/if-no-match-bindings.rs | 22 ++++++++++++ src/test/ui/if/if-no-match-bindings.stderr | 39 ++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 src/test/ui/if/if-no-match-bindings.rs create mode 100644 src/test/ui/if/if-no-match-bindings.stderr diff --git a/src/test/ui/if/if-no-match-bindings.rs b/src/test/ui/if/if-no-match-bindings.rs new file mode 100644 index 0000000000000..581ce18c1d614 --- /dev/null +++ b/src/test/ui/if/if-no-match-bindings.rs @@ -0,0 +1,22 @@ +// Checks for `if` expressions with respect to default match bindings. +// Specifically, we do not accept `if cond { ... }` where `cond: &mut? bool`. +// Meanwhile, `match cond { true => ..., _ => ... }` does accept that. + +// FIXME(@rust-lang/lang-team): consider relaxing this? + +fn b_ref<'a>() -> &'a bool { &true } +fn b_mut_ref<'a>() -> &'a mut bool { &mut true } + +fn main() { + // This is OK: + match b_ref() { true => {}, _ => {} } + match b_mut_ref() { true => {}, _ => {} } + match &true { true => {}, _ => {} } + match &mut true { true => {}, _ => {} } + + // This is NOT: + if b_ref() {} //~ ERROR mismatched types [E0308] + if b_mut_ref() {} //~ ERROR mismatched types [E0308] + if &true {} //~ ERROR mismatched types [E0308] + if &mut true {} //~ ERROR mismatched types [E0308] +} diff --git a/src/test/ui/if/if-no-match-bindings.stderr b/src/test/ui/if/if-no-match-bindings.stderr new file mode 100644 index 0000000000000..7b0b472121fce --- /dev/null +++ b/src/test/ui/if/if-no-match-bindings.stderr @@ -0,0 +1,39 @@ +error[E0308]: mismatched types + --> $DIR/if-no-match-bindings.rs:18:8 + | +LL | if b_ref() {} + | ^^^^^^^ expected bool, found &bool + | + = note: expected type `bool` + found type `&bool` + +error[E0308]: mismatched types + --> $DIR/if-no-match-bindings.rs:19:8 + | +LL | if b_mut_ref() {} + | ^^^^^^^^^^^ expected bool, found &mut bool + | + = note: expected type `bool` + found type `&mut bool` + +error[E0308]: mismatched types + --> $DIR/if-no-match-bindings.rs:20:8 + | +LL | if &true {} + | ^^^^^ expected bool, found &bool + | + = note: expected type `bool` + found type `&bool` + +error[E0308]: mismatched types + --> $DIR/if-no-match-bindings.rs:21:8 + | +LL | if &mut true {} + | ^^^^^^^^^ expected bool, found &mut bool + | + = note: expected type `bool` + found type `&mut bool` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. From f9cc5a65d24270fac44a7ccf709d7a7efd7b525d Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 10 May 2019 19:55:52 +0200 Subject: [PATCH 171/212] check_match: add FIXME for removing of hack. --- src/librustc_typeck/check/_match.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index e8af2f40b87a7..a69f639e8941f 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -615,6 +615,8 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); // `if` expression. E.g. given `fn foo() -> &bool;` we reject `if foo() { .. }`. // // 2. By expecting `bool` for `expr` we get nice diagnostics for e.g. `if x = y { .. }`. + // + // FIXME(60707): Consider removing hack with principled solution. self.check_expr_has_type_or_error(discrim, self.tcx.types.bool) } else { self.demand_discriminant_type(arms, discrim) From 385d012d9e3479397482558e1750205f70b62ffc Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 10 May 2019 20:53:21 +0100 Subject: [PATCH 172/212] Make const parent errors delay_span_bugs --- src/librustc_typeck/collect.rs | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 4185999fdd6d7..c3b6a74bb8243 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1404,7 +1404,13 @@ pub fn checked_type_of<'a, 'tcx>( if !fail { return None; } - bug!("unexpected const parent path def {:?}", x); + tcx.sess.delay_span_bug( + DUMMY_SP, + &format!( + "unexpected const parent path def {:?}", x + ), + ); + tcx.types.err } } } @@ -1412,7 +1418,13 @@ pub fn checked_type_of<'a, 'tcx>( if !fail { return None; } - bug!("unexpected const parent path {:?}", x); + tcx.sess.delay_span_bug( + DUMMY_SP, + &format!( + "unexpected const parent path {:?}", x + ), + ); + tcx.types.err } } } @@ -1421,7 +1433,13 @@ pub fn checked_type_of<'a, 'tcx>( if !fail { return None; } - bug!("unexpected const parent in type_of_def_id(): {:?}", x); + tcx.sess.delay_span_bug( + DUMMY_SP, + &format!( + "unexpected const parent in type_of_def_id(): {:?}", x + ), + ); + tcx.types.err } } } From 531080106235515c3a21e9771f39b8b2733a972b Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 10 May 2019 20:53:35 +0100 Subject: [PATCH 173/212] Add a test for invalid const arguments --- .../invalid-const-arg-for-type-param.rs | 9 +++++++ .../invalid-const-arg-for-type-param.stderr | 25 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 src/test/ui/const-generics/invalid-const-arg-for-type-param.rs create mode 100644 src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr diff --git a/src/test/ui/const-generics/invalid-const-arg-for-type-param.rs b/src/test/ui/const-generics/invalid-const-arg-for-type-param.rs new file mode 100644 index 0000000000000..b069cd89680c1 --- /dev/null +++ b/src/test/ui/const-generics/invalid-const-arg-for-type-param.rs @@ -0,0 +1,9 @@ +use std::convert::TryInto; + +struct S; + +fn main() { + let _: u32 = 5i32.try_into::<32>().unwrap(); //~ ERROR wrong number of const arguments + S.f::<0>(); //~ ERROR no method named `f` + S::<0>; //~ ERROR wrong number of const arguments +} diff --git a/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr b/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr new file mode 100644 index 0000000000000..8f3f91651edfb --- /dev/null +++ b/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr @@ -0,0 +1,25 @@ +error[E0107]: wrong number of const arguments: expected 0, found 1 + --> $DIR/invalid-const-arg-for-type-param.rs:6:34 + | +LL | let _: u32 = 5i32.try_into::<32>().unwrap(); + | ^^ unexpected const argument + +error[E0599]: no method named `f` found for type `S` in the current scope + --> $DIR/invalid-const-arg-for-type-param.rs:7:7 + | +LL | struct S; + | --------- method `f` not found for this +... +LL | S.f::<0>(); + | ^ + +error[E0107]: wrong number of const arguments: expected 0, found 1 + --> $DIR/invalid-const-arg-for-type-param.rs:8:9 + | +LL | S::<0>; + | ^ unexpected const argument + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0107, E0599. +For more information about an error, try `rustc --explain E0107`. From 0f792abf00490066a8743e9b9686fecaad5dcac8 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 10 May 2019 20:53:46 +0100 Subject: [PATCH 174/212] Add a test for failed inference of const types --- .../cannot-infer-type-for-const-param.rs | 11 +++++++++++ .../cannot-infer-type-for-const-param.stderr | 15 +++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 src/test/ui/const-generics/cannot-infer-type-for-const-param.rs create mode 100644 src/test/ui/const-generics/cannot-infer-type-for-const-param.stderr diff --git a/src/test/ui/const-generics/cannot-infer-type-for-const-param.rs b/src/test/ui/const-generics/cannot-infer-type-for-const-param.rs new file mode 100644 index 0000000000000..c3f5e360fe280 --- /dev/null +++ b/src/test/ui/const-generics/cannot-infer-type-for-const-param.rs @@ -0,0 +1,11 @@ +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +// We should probably be able to infer the types here. However, this test is checking that we don't +// get an ICE in this case. It may be modified later to not be an error. + +struct Foo(pub [u8; NUM_BYTES]); + +fn main() { + let _ = Foo::<3>([1, 2, 3]); //~ ERROR type annotations needed +} diff --git a/src/test/ui/const-generics/cannot-infer-type-for-const-param.stderr b/src/test/ui/const-generics/cannot-infer-type-for-const-param.stderr new file mode 100644 index 0000000000000..a0641bd2fdc96 --- /dev/null +++ b/src/test/ui/const-generics/cannot-infer-type-for-const-param.stderr @@ -0,0 +1,15 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/cannot-infer-type-for-const-param.rs:1:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + +error[E0282]: type annotations needed + --> $DIR/cannot-infer-type-for-const-param.rs:10:19 + | +LL | let _ = Foo::<3>([1, 2, 3]); + | ^ cannot infer type for `{integer}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. From 26afc4fb91827a174b044ab210cbb2fef1792b5b Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 10 May 2019 22:06:03 +0100 Subject: [PATCH 175/212] Allow fallible `lift_to_global` in existential type writeback --- src/librustc_typeck/check/writeback.rs | 45 +++++++++++++++----------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index f9d83146e30c3..bf978352faee9 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -611,26 +611,33 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { } } - let new = ty::ResolvedOpaqueTy { - concrete_type: definition_ty, - substs: self.tcx().lift_to_global(&opaque_defn.substs).unwrap(), - }; - - let old = self.tables - .concrete_existential_types - .insert(def_id, new); - if let Some(old) = old { - if old.concrete_type != definition_ty || old.substs != opaque_defn.substs { - span_bug!( - span, - "visit_opaque_types tried to write \ - different types for the same existential type: {:?}, {:?}, {:?}, {:?}", - def_id, - definition_ty, - opaque_defn, - old, - ); + if let Some(substs) = self.tcx().lift_to_global(&opaque_defn.substs) { + let new = ty::ResolvedOpaqueTy { + concrete_type: definition_ty, + substs, + }; + + let old = self.tables + .concrete_existential_types + .insert(def_id, new); + if let Some(old) = old { + if old.concrete_type != definition_ty || old.substs != opaque_defn.substs { + span_bug!( + span, + "visit_opaque_types tried to write \ + different types for the same existential type: {:?}, {:?}, {:?}, {:?}", + def_id, + definition_ty, + opaque_defn, + old, + ); + } } + } else { + self.tcx().sess.delay_span_bug( + span, + "cannot lift `opaque_defn` substs to global type context", + ); } } } From aa9369c7a4f463ea9e2d1f5ceecccbeb026baa41 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 10 May 2019 22:11:19 +0100 Subject: [PATCH 176/212] Add test --- src/test/ui/existential-type/issue-60371.rs | 15 ++++++++++ .../ui/existential-type/issue-60371.stderr | 29 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 src/test/ui/existential-type/issue-60371.rs create mode 100644 src/test/ui/existential-type/issue-60371.stderr diff --git a/src/test/ui/existential-type/issue-60371.rs b/src/test/ui/existential-type/issue-60371.rs new file mode 100644 index 0000000000000..f9def11d1932d --- /dev/null +++ b/src/test/ui/existential-type/issue-60371.rs @@ -0,0 +1,15 @@ +trait Bug { + type Item: Bug; + + const FUN: fn() -> Self::Item; +} + +impl Bug for &() { + existential type Item: Bug; //~ ERROR existential types are unstable + //~^ ERROR the trait bound `(): Bug` is not satisfied + //~^^ ERROR could not find defining uses + + const FUN: fn() -> Self::Item = || (); +} + +fn main() {} diff --git a/src/test/ui/existential-type/issue-60371.stderr b/src/test/ui/existential-type/issue-60371.stderr new file mode 100644 index 0000000000000..2560e01047aad --- /dev/null +++ b/src/test/ui/existential-type/issue-60371.stderr @@ -0,0 +1,29 @@ +error[E0658]: existential types are unstable + --> $DIR/issue-60371.rs:8:5 + | +LL | existential type Item: Bug; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/34511 + = help: add #![feature(existential_type)] to the crate attributes to enable + +error[E0277]: the trait bound `(): Bug` is not satisfied + --> $DIR/issue-60371.rs:8:5 + | +LL | existential type Item: Bug; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bug` is not implemented for `()` + | + = help: the following implementations were found: + <&() as Bug> + = note: the return type of a function must have a statically known size + +error: could not find defining uses + --> $DIR/issue-60371.rs:8:5 + | +LL | existential type Item: Bug; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0658. +For more information about an error, try `rustc --explain E0277`. From 0686daab4ec82a4127d317c01324d46c58ef47b3 Mon Sep 17 00:00:00 2001 From: varkor Date: Sat, 11 May 2019 00:08:19 +0100 Subject: [PATCH 177/212] Unwrap singleton block expressions in const arguments --- src/librustc_typeck/astconv.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 16033c6c50fd0..da47ccf38a026 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1902,7 +1902,18 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { ty, }; - let expr = &tcx.hir().body(ast_const.body).value; + let mut expr = &tcx.hir().body(ast_const.body).value; + + // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments + // currently have to be wrapped in curly brackets, so it's necessary to special-case. + if let ExprKind::Block(block, _) = &expr.node { + if block.stmts.is_empty() { + if let Some(trailing) = &block.expr { + expr = &trailing; + } + } + } + if let ExprKind::Path(ref qpath) = expr.node { if let hir::QPath::Resolved(_, ref path) = qpath { if let Res::Def(DefKind::ConstParam, def_id) = path.res { From b3207d531d01c1dc6c1f3d4e7b1c20a1546fe108 Mon Sep 17 00:00:00 2001 From: varkor Date: Sat, 11 May 2019 00:08:40 +0100 Subject: [PATCH 178/212] Add test for const impl --- .../const-generics/impl-const-generic-struct.rs | 16 ++++++++++++++++ .../impl-const-generic-struct.stderr | 6 ++++++ 2 files changed, 22 insertions(+) create mode 100644 src/test/ui/const-generics/impl-const-generic-struct.rs create mode 100644 src/test/ui/const-generics/impl-const-generic-struct.stderr diff --git a/src/test/ui/const-generics/impl-const-generic-struct.rs b/src/test/ui/const-generics/impl-const-generic-struct.rs new file mode 100644 index 0000000000000..7a0c0f2be5d7a --- /dev/null +++ b/src/test/ui/const-generics/impl-const-generic-struct.rs @@ -0,0 +1,16 @@ +// run-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +struct S; + +impl S<{X}> { + fn x() -> u32 { + X + } +} + +fn main() { + assert_eq!(S::<19>::x(), 19); +} diff --git a/src/test/ui/const-generics/impl-const-generic-struct.stderr b/src/test/ui/const-generics/impl-const-generic-struct.stderr new file mode 100644 index 0000000000000..d443e060a9747 --- /dev/null +++ b/src/test/ui/const-generics/impl-const-generic-struct.stderr @@ -0,0 +1,6 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/impl-const-generic-struct.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + From c158a0f59270297a66058b9abac36d3e6e21ac37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 10 May 2019 16:57:03 -0700 Subject: [PATCH 179/212] Remove unnecessary unwraps --- src/librustc_typeck/check/method/suggest.rs | 57 ++++++++++++--------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index b57ae361eb69e..77d2ffab8efb4 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -91,14 +91,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { CandidateSource::ImplSource(impl_did) => { // Provide the best span we can. Use the item, if local to crate, else // the impl, if local to crate (item may be defaulted), else nothing. - let item = self.associated_item(impl_did, item_name, Namespace::Value) - .or_else(|| { - self.associated_item( - self.tcx.impl_trait_ref(impl_did).unwrap().def_id, - item_name, - Namespace::Value, - ) - }).unwrap(); + let item = match self.associated_item( + impl_did, + item_name, + Namespace::Value, + ).or_else(|| { + let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?; + self.associated_item( + impl_trait_ref.def_id, + item_name, + Namespace::Value, + ) + }) { + Some(item) => item, + None => continue, + }; let note_span = self.tcx.hir().span_if_local(item.def_id).or_else(|| { self.tcx.hir().span_if_local(impl_did) }); @@ -132,9 +139,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } CandidateSource::TraitSource(trait_did) => { - let item = self - .associated_item(trait_did, item_name, Namespace::Value) - .unwrap(); + let item = match self.associated_item( + trait_did, + item_name, + Namespace::Value) + { + Some(item) => item, + None => continue, + }; let item_span = self.tcx.sess.source_map() .def_span(self.tcx.def_span(item.def_id)); if sources.len() > 1 { @@ -251,8 +263,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let &QPath::Resolved(_, ref path) = &qpath { if let hir::def::Res::Local(hir_id) = path.res { let span = tcx.hir().span_by_hir_id(hir_id); - let snippet = tcx.sess.source_map().span_to_snippet(span) - .unwrap(); + let snippet = tcx.sess.source_map().span_to_snippet(span); let filename = tcx.sess.source_map().span_to_filename(span); let parent_node = self.tcx.hir().get_by_hir_id( @@ -263,12 +274,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { concrete_type, ); - match (filename, parent_node) { + match (filename, parent_node, snippet) { (FileName::Real(_), Node::Local(hir::Local { source: hir::LocalSource::Normal, ty, .. - })) => { + }), Ok(ref snippet)) => { err.span_suggestion( // account for `let x: _ = 42;` // ^^^^ @@ -375,14 +386,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.tcx.hir().get_parent_node_by_hir_id(expr.hir_id), ); - let span = call_expr.span.trim_start(item_name.span).unwrap(); - - err.span_suggestion( - span, - "remove the arguments", - String::new(), - Applicability::MaybeIncorrect, - ); + if let Some(span) = call_expr.span.trim_start(item_name.span) { + err.span_suggestion( + span, + "remove the arguments", + String::new(), + Applicability::MaybeIncorrect, + ); + } } } From 0545375ca6822b4b140cd853f368473d69b76227 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 10 May 2019 18:01:50 -0700 Subject: [PATCH 180/212] Add examples of ordered retain --- src/liballoc/collections/vec_deque.rs | 14 ++++++++++++++ src/liballoc/string.rs | 10 ++++++++++ src/liballoc/vec.rs | 10 ++++++++++ 3 files changed, 34 insertions(+) diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 82a60f924444a..9a8d48083e67c 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -1848,6 +1848,20 @@ impl VecDeque { /// buf.retain(|&x| x%2 == 0); /// assert_eq!(buf, [2, 4]); /// ``` + /// + /// The exact order may be useful for tracking external state, like an index. + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// buf.extend(1..6); + /// + /// let keep = [false, true, true, false, true]; + /// let mut i = 0; + /// buf.retain(|_| (keep[i], i += 1).0); + /// assert_eq!(buf, [2, 3, 5]); + /// ``` #[stable(feature = "vec_deque_retain", since = "1.4.0")] pub fn retain(&mut self, mut f: F) where F: FnMut(&T) -> bool diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index aaa3814269339..3fdcf95ccaa3f 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -1212,6 +1212,16 @@ impl String { /// /// assert_eq!(s, "foobar"); /// ``` + /// + /// The exact order may be useful for tracking external state, like an index. + /// + /// ``` + /// let mut s = String::from("abcde"); + /// let keep = [false, true, true, false, true]; + /// let mut i = 0; + /// s.retain(|_| (keep[i], i += 1).0); + /// assert_eq!(s, "bce"); + /// ``` #[inline] #[stable(feature = "string_retain", since = "1.26.0")] pub fn retain(&mut self, mut f: F) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index a9bc835010ffb..073d3ab593703 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -947,6 +947,16 @@ impl Vec { /// vec.retain(|&x| x%2 == 0); /// assert_eq!(vec, [2, 4]); /// ``` + /// + /// The exact order may be useful for tracking external state, like an index. + /// + /// ``` + /// let mut vec = vec![1, 2, 3, 4, 5]; + /// let keep = [false, true, true, false, true]; + /// let mut i = 0; + /// vec.retain(|_| (keep[i], i += 1).0); + /// assert_eq!(vec, [2, 3, 5]); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn retain(&mut self, mut f: F) where F: FnMut(&T) -> bool From adc18eb7cfd0315a5bdba54ecc0d926176c4cd80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 10 May 2019 18:22:25 -0700 Subject: [PATCH 181/212] Avoid ICE by using delay_span_bug --- src/librustc_typeck/check/mod.rs | 5 +++-- src/test/ui/issues/issue-53498.rs | 17 +++++++++++++++++ src/test/ui/issues/issue-53498.stderr | 9 +++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/issues/issue-53498.rs create mode 100644 src/test/ui/issues/issue-53498.stderr diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 64c8ff8ff8630..09ce9516fef25 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5653,10 +5653,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { match self.at(&self.misc(span), self.param_env).sup(impl_ty, self_ty) { Ok(ok) => self.register_infer_ok_obligations(ok), Err(_) => { - span_bug!(span, + self.tcx.sess.delay_span_bug(span, &format!( "instantiate_value_path: (UFCS) {:?} was a subtype of {:?} but now is not?", self_ty, - impl_ty); + impl_ty, + )); } } } diff --git a/src/test/ui/issues/issue-53498.rs b/src/test/ui/issues/issue-53498.rs new file mode 100644 index 0000000000000..c87d423649233 --- /dev/null +++ b/src/test/ui/issues/issue-53498.rs @@ -0,0 +1,17 @@ +pub mod test { + pub struct A; + pub struct B; + pub struct Foo(T); + + impl Foo { + fn foo() {} + } + + impl Foo { + fn foo() {} + } +} + +fn main() { + test::Foo::::foo(); //~ ERROR method `foo` is private +} diff --git a/src/test/ui/issues/issue-53498.stderr b/src/test/ui/issues/issue-53498.stderr new file mode 100644 index 0000000000000..3fd48233daeb4 --- /dev/null +++ b/src/test/ui/issues/issue-53498.stderr @@ -0,0 +1,9 @@ +error[E0624]: method `foo` is private + --> $DIR/issue-53498.rs:16:5 + | +LL | test::Foo::::foo(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0624`. From 740a8dabb413abecd88a202f2370252b33e73a7f Mon Sep 17 00:00:00 2001 From: Thomas Heck Date: Sat, 11 May 2019 10:23:07 +0200 Subject: [PATCH 182/212] add comment to `Rc`/`Arc`'s `Eq` specialization --- src/liballoc/rc.rs | 5 +++++ src/liballoc/sync.rs | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 68eecd97ea11a..0dffb19476f3d 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -932,6 +932,11 @@ impl RcEqIdent for Rc { } } +/// We're doing this specialization here, and not as a more general optimization on `&T`, because it +/// would otherwise add a cost to all equality checks on refs. We assume that `Rc`s are used to +/// store large values, that are slow to clone, but also heavy to check for equality, causing this +/// cost to pay off more easily. It's also more likely to have two `Rc` clones, that point to +/// the same value, than two `&T`s. #[stable(feature = "rust1", since = "1.0.0")] impl RcEqIdent for Rc { #[inline] diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 466e806663c7f..90c7859b3db9e 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -1377,6 +1377,11 @@ impl ArcEqIdent for Arc { } } +/// We're doing this specialization here, and not as a more general optimization on `&T`, because it +/// would otherwise add a cost to all equality checks on refs. We assume that `Arc`s are used to +/// store large values, that are slow to clone, but also heavy to check for equality, causing this +/// cost to pay off more easily. It's also more likely to have two `Arc` clones, that point to +/// the same value, than two `&T`s. #[stable(feature = "rust1", since = "1.0.0")] impl ArcEqIdent for Arc { #[inline] From 28b125b83d9db4094a08b512a956c187bd29a51f Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 9 May 2019 02:00:29 +0300 Subject: [PATCH 183/212] Turn `ast::Lit` into a struct --- src/librustc/ich/impls_syntax.rs | 6 +++++- src/libsyntax/ast.rs | 6 +++++- src/libsyntax/attr/mod.rs | 12 ++++++------ src/libsyntax/ext/build.rs | 10 +++++----- src/libsyntax/parse/parser.rs | 7 +++---- 5 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index 35df43ef25efa..88a2c295a6ef6 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -162,7 +162,11 @@ impl_stable_hash_for!(enum ::syntax::ast::LitIntType { Unsuffixed }); -impl_stable_hash_for_spanned!(::syntax::ast::LitKind); +impl_stable_hash_for!(struct ::syntax::ast::Lit { + node, + span +}); + impl_stable_hash_for!(enum ::syntax::ast::LitKind { Str(value, style), Err(value), diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index af2302d24f521..783792cf1977a 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1351,7 +1351,11 @@ pub enum StrStyle { } /// A literal. -pub type Lit = Spanned; +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq)] +pub struct Lit { + pub node: LitKind, + pub span: Span, +} #[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, Hash, PartialEq)] pub enum LitIntType { diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index e00f91e395280..e331a26335443 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -16,7 +16,7 @@ use crate::ast::{AttrId, Attribute, AttrStyle, Name, Ident, Path, PathSegment}; use crate::ast::{MetaItem, MetaItemKind, NestedMetaItem}; use crate::ast::{Lit, LitKind, Expr, ExprKind, Item, Local, Stmt, StmtKind, GenericParam}; use crate::mut_visit::visit_clobber; -use crate::source_map::{BytePos, Spanned, respan, dummy_spanned}; +use crate::source_map::{BytePos, Spanned, dummy_spanned}; use crate::parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration}; use crate::parse::parser::Parser; use crate::parse::{self, ParseSess, PResult}; @@ -350,11 +350,11 @@ impl Attribute { /* Constructors */ pub fn mk_name_value_item_str(ident: Ident, value: Spanned) -> MetaItem { - let value = respan(value.span, LitKind::Str(value.node, ast::StrStyle::Cooked)); + let value = Lit { node: LitKind::Str(value.node, ast::StrStyle::Cooked), span: value.span }; mk_name_value_item(ident.span.to(value.span), ident, value) } -pub fn mk_name_value_item(span: Span, ident: Ident, value: ast::Lit) -> MetaItem { +pub fn mk_name_value_item(span: Span, ident: Ident, value: Lit) -> MetaItem { MetaItem { path: Path::from_ident(ident), span, node: MetaItemKind::NameValue(value) } } @@ -417,7 +417,7 @@ pub fn mk_spanned_attr_outer(sp: Span, id: AttrId, item: MetaItem) -> Attribute pub fn mk_sugared_doc_attr(id: AttrId, text: Symbol, span: Span) -> Attribute { let style = doc_comment_style(&text.as_str()); - let lit = respan(span, LitKind::Str(text, ast::StrStyle::Cooked)); + let lit = Lit { node: LitKind::Str(text, ast::StrStyle::Cooked), span }; Attribute { id, style, @@ -562,7 +562,7 @@ impl MetaItemKind { tokens.next(); return if let Some(TokenTree::Token(span, token)) = tokens.next() { LitKind::from_token(token) - .map(|lit| MetaItemKind::NameValue(Spanned { node: lit, span: span })) + .map(|node| MetaItemKind::NameValue(Lit { node, span })) } else { None }; @@ -609,7 +609,7 @@ impl NestedMetaItem { if let Some(TokenTree::Token(span, token)) = tokens.peek().cloned() { if let Some(node) = LitKind::from_token(token) { tokens.next(); - return Some(NestedMetaItem::Literal(respan(span, node))); + return Some(NestedMetaItem::Literal(Lit { node, span })); } } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 40dd187ed28a7..0fe85361b54b1 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -697,8 +697,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.expr_struct(span, self.path_ident(span, id), fields) } - fn expr_lit(&self, sp: Span, lit: ast::LitKind) -> P { - self.expr(sp, ast::ExprKind::Lit(respan(sp, lit))) + fn expr_lit(&self, span: Span, node: ast::LitKind) -> P { + self.expr(span, ast::ExprKind::Lit(ast::Lit { node, span })) } fn expr_usize(&self, span: Span, i: usize) -> P { self.expr_lit(span, ast::LitKind::Int(i as u128, @@ -1164,10 +1164,10 @@ impl<'a> AstBuilder for ExtCtxt<'a> { attr::mk_list_item(sp, Ident::with_empty_ctxt(name).with_span_pos(sp), mis) } - fn meta_name_value(&self, sp: Span, name: ast::Name, value: ast::LitKind) + fn meta_name_value(&self, span: Span, name: ast::Name, node: ast::LitKind) -> ast::MetaItem { - attr::mk_name_value_item(sp, Ident::with_empty_ctxt(name).with_span_pos(sp), - respan(sp, value)) + attr::mk_name_value_item(span, Ident::with_empty_ctxt(name).with_span_pos(span), + ast::Lit { node, span }) } fn item_use(&self, sp: Span, diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d97d1e2f0f4ee..2b30d2db95e01 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2140,15 +2140,14 @@ impl<'a> Parser<'a> { /// Matches `lit = true | false | token_lit`. crate fn parse_lit(&mut self) -> PResult<'a, Lit> { let lo = self.span; - let lit = if self.eat_keyword(keywords::True) { + let node = if self.eat_keyword(keywords::True) { LitKind::Bool(true) } else if self.eat_keyword(keywords::False) { LitKind::Bool(false) } else { - let lit = self.parse_lit_token()?; - lit + self.parse_lit_token()? }; - Ok(source_map::Spanned { node: lit, span: lo.to(self.prev_span) }) + Ok(Lit { node, span: lo.to(self.prev_span) }) } /// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`). From f2834a403abe78f56d750a302807eab5206bb2c5 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 9 May 2019 02:17:32 +0300 Subject: [PATCH 184/212] Keep the original token in `ast::Lit` --- src/librustc/hir/mod.rs | 2 +- src/librustc/ich/impls_syntax.rs | 33 ++++++++--------- src/librustdoc/html/highlight.rs | 2 ++ src/libsyntax/ast.rs | 3 ++ src/libsyntax/attr/mod.rs | 62 +++++++++++++++++++------------- src/libsyntax/ext/build.rs | 6 ++-- src/libsyntax/parse/mod.rs | 1 + src/libsyntax/parse/parser.rs | 30 ++++++++-------- src/libsyntax/parse/token.rs | 5 +++ src/libsyntax/print/pprust.rs | 1 + 10 files changed, 86 insertions(+), 59 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 9f7fa6c5557ef..a59322bbe4da9 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1353,7 +1353,7 @@ pub struct Expr { // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_arch = "x86_64")] -static_assert!(MEM_SIZE_OF_EXPR: std::mem::size_of::() == 72); +static_assert!(MEM_SIZE_OF_EXPR: std::mem::size_of::() == 80); impl Expr { pub fn precedence(&self) -> ExprPrecedence { diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index 88a2c295a6ef6..7ff546b7467da 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -164,6 +164,8 @@ impl_stable_hash_for!(enum ::syntax::ast::LitIntType { impl_stable_hash_for!(struct ::syntax::ast::Lit { node, + token, + suffix, span }); @@ -284,6 +286,19 @@ for tokenstream::TokenStream { } } +impl_stable_hash_for!(enum token::Lit { + Bool(val), + Byte(val), + Char(val), + Err(val), + Integer(val), + Float(val), + Str_(val), + ByteStr(val), + StrRaw(val, n), + ByteStrRaw(val, n) +}); + fn hash_token<'a, 'gcx, W: StableHasherResult>( token: &token::Token, hcx: &mut StableHashingContext<'a>, @@ -331,22 +346,8 @@ fn hash_token<'a, 'gcx, W: StableHasherResult>( token::Token::CloseDelim(delim_token) => { std_hash::Hash::hash(&delim_token, hasher); } - token::Token::Literal(ref lit, ref opt_name) => { - mem::discriminant(lit).hash_stable(hcx, hasher); - match *lit { - token::Lit::Byte(val) | - token::Lit::Char(val) | - token::Lit::Err(val) | - token::Lit::Integer(val) | - token::Lit::Float(val) | - token::Lit::Str_(val) | - token::Lit::ByteStr(val) => val.hash_stable(hcx, hasher), - token::Lit::StrRaw(val, n) | - token::Lit::ByteStrRaw(val, n) => { - val.hash_stable(hcx, hasher); - n.hash_stable(hcx, hasher); - } - }; + token::Token::Literal(lit, opt_name) => { + lit.hash_stable(hcx, hasher); opt_name.hash_stable(hcx, hasher); } diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index d66455f91ba1a..5bb06516ac49e 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -318,6 +318,8 @@ impl<'a> Classifier<'a> { // Number literals. token::Integer(..) | token::Float(..) => Class::Number, + + token::Bool(..) => panic!("literal token contains `Lit::Bool`"), } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 783792cf1977a..04bc146e145ec 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -6,6 +6,7 @@ pub use crate::symbol::{Ident, Symbol as Name}; pub use crate::util::parser::ExprPrecedence; use crate::ext::hygiene::{Mark, SyntaxContext}; +use crate::parse::token; use crate::print::pprust; use crate::ptr::P; use crate::source_map::{dummy_spanned, respan, Spanned}; @@ -1354,6 +1355,8 @@ pub enum StrStyle { #[derive(Clone, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq)] pub struct Lit { pub node: LitKind, + pub token: token::Lit, + pub suffix: Option, pub span: Span, } diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index e331a26335443..2b87458108336 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -350,7 +350,9 @@ impl Attribute { /* Constructors */ pub fn mk_name_value_item_str(ident: Ident, value: Spanned) -> MetaItem { - let value = Lit { node: LitKind::Str(value.node, ast::StrStyle::Cooked), span: value.span }; + let node = LitKind::Str(value.node, ast::StrStyle::Cooked); + let (token, suffix) = node.lit_token(); + let value = Lit { node, token, suffix, span: value.span }; mk_name_value_item(ident.span.to(value.span), ident, value) } @@ -417,7 +419,9 @@ pub fn mk_spanned_attr_outer(sp: Span, id: AttrId, item: MetaItem) -> Attribute pub fn mk_sugared_doc_attr(id: AttrId, text: Symbol, span: Span) -> Attribute { let style = doc_comment_style(&text.as_str()); - let lit = Lit { node: LitKind::Str(text, ast::StrStyle::Cooked), span }; + let node = LitKind::Str(text, ast::StrStyle::Cooked); + let (token, suffix) = node.lit_token(); + let lit = Lit { node, token, suffix, span }; Attribute { id, style, @@ -562,7 +566,7 @@ impl MetaItemKind { tokens.next(); return if let Some(TokenTree::Token(span, token)) = tokens.next() { LitKind::from_token(token) - .map(|node| MetaItemKind::NameValue(Lit { node, span })) + .map(|(node, token, suffix)| MetaItemKind::NameValue(Lit { node, token, suffix, span })) } else { None }; @@ -607,9 +611,9 @@ impl NestedMetaItem { where I: Iterator, { if let Some(TokenTree::Token(span, token)) = tokens.peek().cloned() { - if let Some(node) = LitKind::from_token(token) { + if let Some((node, token, suffix)) = LitKind::from_token(token) { tokens.next(); - return Some(NestedMetaItem::Literal(Lit { node, span })); + return Some(NestedMetaItem::Literal(Lit { node, token, suffix, span })); } } @@ -625,28 +629,35 @@ impl Lit { impl LitKind { fn token(&self) -> Token { + match self.lit_token() { + (token::Bool(symbol), _) => Token::Ident(Ident::with_empty_ctxt(symbol), false), + (lit, suffix) => Token::Literal(lit, suffix), + } + } + + pub(crate) fn lit_token(&self) -> (token::Lit, Option) { use std::ascii; match *self { LitKind::Str(string, ast::StrStyle::Cooked) => { let escaped = string.as_str().escape_default().to_string(); - Token::Literal(token::Lit::Str_(Symbol::intern(&escaped)), None) + (token::Lit::Str_(Symbol::intern(&escaped)), None) } LitKind::Str(string, ast::StrStyle::Raw(n)) => { - Token::Literal(token::Lit::StrRaw(string, n), None) + (token::Lit::StrRaw(string, n), None) } LitKind::ByteStr(ref bytes) => { let string = bytes.iter().cloned().flat_map(ascii::escape_default) .map(Into::::into).collect::(); - Token::Literal(token::Lit::ByteStr(Symbol::intern(&string)), None) + (token::Lit::ByteStr(Symbol::intern(&string)), None) } LitKind::Byte(byte) => { let string: String = ascii::escape_default(byte).map(Into::::into).collect(); - Token::Literal(token::Lit::Byte(Symbol::intern(&string)), None) + (token::Lit::Byte(Symbol::intern(&string)), None) } LitKind::Char(ch) => { let string: String = ch.escape_default().map(Into::::into).collect(); - Token::Literal(token::Lit::Char(Symbol::intern(&string)), None) + (token::Lit::Char(Symbol::intern(&string)), None) } LitKind::Int(n, ty) => { let suffix = match ty { @@ -654,38 +665,39 @@ impl LitKind { ast::LitIntType::Signed(ty) => Some(Symbol::intern(ty.ty_to_string())), ast::LitIntType::Unsuffixed => None, }; - Token::Literal(token::Lit::Integer(Symbol::intern(&n.to_string())), suffix) + (token::Lit::Integer(Symbol::intern(&n.to_string())), suffix) } LitKind::Float(symbol, ty) => { - Token::Literal(token::Lit::Float(symbol), Some(Symbol::intern(ty.ty_to_string()))) + (token::Lit::Float(symbol), Some(Symbol::intern(ty.ty_to_string()))) } - LitKind::FloatUnsuffixed(symbol) => Token::Literal(token::Lit::Float(symbol), None), - LitKind::Bool(value) => Token::Ident(Ident::with_empty_ctxt(Symbol::intern(if value { - "true" - } else { - "false" - })), false), - LitKind::Err(val) => Token::Literal(token::Lit::Err(val), None), + LitKind::FloatUnsuffixed(symbol) => (token::Lit::Float(symbol), None), + LitKind::Bool(value) => { + let kw = if value { keywords::True } else { keywords::False }; + (token::Lit::Bool(kw.name()), None) + } + LitKind::Err(val) => (token::Lit::Err(val), None), } } - fn from_token(token: Token) -> Option { + fn from_token(token: Token) -> Option<(LitKind, token::Lit, Option)> { match token { - Token::Ident(ident, false) if ident.name == "true" => Some(LitKind::Bool(true)), - Token::Ident(ident, false) if ident.name == "false" => Some(LitKind::Bool(false)), + Token::Ident(ident, false) if ident.name == keywords::True.name() => + Some((LitKind::Bool(true), token::Bool(ident.name), None)), + Token::Ident(ident, false) if ident.name == keywords::False.name() => + Some((LitKind::Bool(false), token::Bool(ident.name), None)), Token::Interpolated(nt) => match *nt { token::NtExpr(ref v) | token::NtLiteral(ref v) => match v.node { - ExprKind::Lit(ref lit) => Some(lit.node.clone()), + ExprKind::Lit(ref lit) => Some((lit.node.clone(), lit.token, lit.suffix)), _ => None, }, _ => None, }, Token::Literal(lit, suf) => { let (suffix_illegal, result) = parse::lit_token(lit, suf, None); - if suffix_illegal && suf.is_some() { + if result.is_none() || suffix_illegal && suf.is_some() { return None; } - result + Some((result.unwrap(), lit, suf)) } _ => None, } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 0fe85361b54b1..0f9977e85038b 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -698,7 +698,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } fn expr_lit(&self, span: Span, node: ast::LitKind) -> P { - self.expr(span, ast::ExprKind::Lit(ast::Lit { node, span })) + let (token, suffix) = node.lit_token(); + self.expr(span, ast::ExprKind::Lit(ast::Lit { node, token, suffix, span })) } fn expr_usize(&self, span: Span, i: usize) -> P { self.expr_lit(span, ast::LitKind::Int(i as u128, @@ -1166,8 +1167,9 @@ impl<'a> AstBuilder for ExtCtxt<'a> { fn meta_name_value(&self, span: Span, name: ast::Name, node: ast::LitKind) -> ast::MetaItem { + let (token, suffix) = node.lit_token(); attr::mk_name_value_item(span, Ident::with_empty_ctxt(name).with_span_pos(span), - ast::Lit { node, span }) + ast::Lit { node, token, suffix, span }) } fn item_use(&self, sp: Span, diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index be44b964ba5a7..4d4e99009a9d2 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -376,6 +376,7 @@ crate fn lit_token(lit: token::Lit, suf: Option, diag: Option<(Span, &Ha use ast::LitKind; match lit { + token::Bool(_) => panic!("literal token contains `Lit::Bool`"), token::Byte(i) => { let lit_kind = match unescape_byte(&i.as_str()) { Ok(c) => LitKind::Byte(c), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 2b30d2db95e01..b988cb1447df7 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2070,11 +2070,11 @@ impl<'a> Parser<'a> { } /// Matches `token_lit = LIT_INTEGER | ...`. - fn parse_lit_token(&mut self) -> PResult<'a, LitKind> { + fn parse_lit_token(&mut self) -> PResult<'a, (LitKind, token::Lit, Option)> { let out = match self.token { token::Interpolated(ref nt) => match **nt { token::NtExpr(ref v) | token::NtLiteral(ref v) => match v.node { - ExprKind::Lit(ref lit) => { lit.node.clone() } + ExprKind::Lit(ref lit) => { (lit.node.clone(), lit.token, lit.suffix) } _ => { return self.unexpected_last(&self.token); } }, _ => { return self.unexpected_last(&self.token); } @@ -2088,19 +2088,19 @@ impl<'a> Parser<'a> { self.expect_no_suffix(sp, &format!("a {}", lit.literal_name()), suf) } - result.unwrap() + (result.unwrap(), lit, suf) } token::Dot if self.look_ahead(1, |t| match t { - token::Literal(parse::token::Lit::Integer(_) , _) => true, + token::Literal(token::Lit::Integer(_) , _) => true, _ => false, }) => { // recover from `let x = .4;` let lo = self.span; self.bump(); if let token::Literal( - parse::token::Lit::Integer(val), + token::Lit::Integer(val), suffix, ) = self.token { - let suffix = suffix.and_then(|s| { + let float_suffix = suffix.and_then(|s| { let s = s.as_str(); if s == "f32" { Some("f32") @@ -2117,14 +2117,14 @@ impl<'a> Parser<'a> { err.span_suggestion( sp, "must have an integer part", - format!("0.{}{}", val, suffix), + format!("0.{}{}", val, float_suffix), Applicability::MachineApplicable, ); err.emit(); - return Ok(match suffix { - "f32" => ast::LitKind::Float(val, ast::FloatTy::F32), - "f64" => ast::LitKind::Float(val, ast::FloatTy::F64), - _ => ast::LitKind::FloatUnsuffixed(val), + return Ok(match float_suffix { + "f32" => (ast::LitKind::Float(val, ast::FloatTy::F32), token::Float(val), suffix), + "f64" => (ast::LitKind::Float(val, ast::FloatTy::F64), token::Float(val), suffix), + _ => (ast::LitKind::FloatUnsuffixed(val), token::Float(val), suffix), }); } else { unreachable!(); @@ -2140,14 +2140,14 @@ impl<'a> Parser<'a> { /// Matches `lit = true | false | token_lit`. crate fn parse_lit(&mut self) -> PResult<'a, Lit> { let lo = self.span; - let node = if self.eat_keyword(keywords::True) { - LitKind::Bool(true) + let (node, token, suffix) = if self.eat_keyword(keywords::True) { + (LitKind::Bool(true), token::Bool(keywords::True.name()), None) } else if self.eat_keyword(keywords::False) { - LitKind::Bool(false) + (LitKind::Bool(false), token::Bool(keywords::False.name()), None) } else { self.parse_lit_token()? }; - Ok(Lit { node, span: lo.to(self.prev_span) }) + Ok(Lit { node, token, suffix, span: lo.to(self.prev_span) }) } /// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`). diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index fd7a39c576daa..48a949257ffb3 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -61,6 +61,7 @@ impl DelimToken { #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] pub enum Lit { + Bool(ast::Name), // AST only, must never appear in a `Token` Byte(ast::Name), Char(ast::Name), Err(ast::Name), @@ -72,9 +73,13 @@ pub enum Lit { ByteStrRaw(ast::Name, u16), /* raw byte str delimited by n hash symbols */ } +#[cfg(target_arch = "x86_64")] +static_assert!(MEM_SIZE_OF_LIT: mem::size_of::() == 8); + impl Lit { crate fn literal_name(&self) -> &'static str { match *self { + Bool(_) => panic!("literal token contains `Lit::Bool`"), Byte(_) => "byte literal", Char(_) => "char literal", Err(_) => "invalid literal", diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 682621d40ab65..0e93b857708f7 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -225,6 +225,7 @@ pub fn token_to_string(tok: &Token) -> String { /* Literals */ token::Literal(lit, suf) => { let mut out = match lit { + token::Bool(_) => panic!("literal token contains `Lit::Bool`"), token::Byte(b) => format!("b'{}'", b), token::Char(c) => format!("'{}'", c), token::Err(c) => format!("'{}'", c), From 751ae5af1a561a93ce61e9971be4b254a57e6576 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 9 May 2019 18:04:24 +0300 Subject: [PATCH 185/212] Introduce `hir::Lit` not keeping the original token --- src/librustc/hir/lowering.rs | 2 +- src/librustc/hir/mod.rs | 7 ++-- src/librustc/hir/print.rs | 59 ++++++++++++++++++++++++++++++++ src/librustc/ich/impls_syntax.rs | 2 ++ src/librustc_lint/types.rs | 10 +++--- src/librustc_typeck/check/mod.rs | 2 +- src/libsyntax/ast.rs | 2 +- 7 files changed, 74 insertions(+), 10 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 7ccfb826e37b7..20a2a1fd49bde 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -4100,7 +4100,7 @@ impl<'a> LoweringContext<'a> { let ohs = P(self.lower_expr(ohs)); hir::ExprKind::Unary(op, ohs) } - ExprKind::Lit(ref l) => hir::ExprKind::Lit((*l).clone()), + ExprKind::Lit(ref l) => hir::ExprKind::Lit(respan(l.span, l.node.clone())), ExprKind::Cast(ref expr, ref ty) => { let expr = P(self.lower_expr(expr)); hir::ExprKind::Cast(expr, self.lower_ty(ty, ImplTraitContext::disallowed())) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index a59322bbe4da9..d645898692806 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -20,7 +20,7 @@ use syntax_pos::{Span, DUMMY_SP, symbol::InternedString}; use syntax::source_map::Spanned; use rustc_target::spec::abi::Abi; use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, AsmDialect}; -use syntax::ast::{Attribute, Label, Lit, StrStyle, FloatTy, IntTy, UintTy}; +use syntax::ast::{Attribute, Label, LitKind, StrStyle, FloatTy, IntTy, UintTy}; use syntax::attr::{InlineAttr, OptimizeAttr}; use syntax::ext::hygiene::SyntaxContext; use syntax::ptr::P; @@ -1331,6 +1331,9 @@ impl BodyOwnerKind { } } +/// A literal. +pub type Lit = Spanned; + /// A constant (expression) that's not an item or associated item, /// but needs its own `DefId` for type-checking, const-eval, etc. /// These are usually found nested inside types (e.g., array lengths) @@ -1353,7 +1356,7 @@ pub struct Expr { // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_arch = "x86_64")] -static_assert!(MEM_SIZE_OF_EXPR: std::mem::size_of::() == 80); +static_assert!(MEM_SIZE_OF_EXPR: std::mem::size_of::() == 72); impl Expr { pub fn precedence(&self) -> ExprPrecedence { diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index c42d8f3cb3c36..b7260abb521ac 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -15,6 +15,7 @@ use crate::hir; use crate::hir::{PatKind, GenericBound, TraitBoundModifier, RangeEnd}; use crate::hir::{GenericParam, GenericParamKind, GenericArg}; +use std::ascii; use std::borrow::Cow; use std::cell::Cell; use std::io::{self, Write, Read}; @@ -1276,6 +1277,64 @@ impl<'a> State<'a> { self.print_expr_maybe_paren(expr, parser::PREC_PREFIX) } + fn print_literal(&mut self, lit: &hir::Lit) -> io::Result<()> { + self.maybe_print_comment(lit.span.lo())?; + if let Some(ltrl) = self.next_lit(lit.span.lo()) { + return self.writer().word(ltrl.lit.clone()); + } + match lit.node { + hir::LitKind::Str(st, style) => self.print_string(&st.as_str(), style), + hir::LitKind::Err(st) => { + let st = st.as_str().escape_debug().to_string(); + let mut res = String::with_capacity(st.len() + 2); + res.push('\''); + res.push_str(&st); + res.push('\''); + self.writer().word(res) + } + hir::LitKind::Byte(byte) => { + let mut res = String::from("b'"); + res.extend(ascii::escape_default(byte).map(|c| c as char)); + res.push('\''); + self.writer().word(res) + } + hir::LitKind::Char(ch) => { + let mut res = String::from("'"); + res.extend(ch.escape_default()); + res.push('\''); + self.writer().word(res) + } + hir::LitKind::Int(i, t) => { + match t { + ast::LitIntType::Signed(st) => { + self.writer().word(st.val_to_string(i as i128)) + } + ast::LitIntType::Unsigned(ut) => { + self.writer().word(ut.val_to_string(i)) + } + ast::LitIntType::Unsuffixed => { + self.writer().word(i.to_string()) + } + } + } + hir::LitKind::Float(ref f, t) => { + self.writer().word(format!("{}{}", &f, t.ty_to_string())) + } + hir::LitKind::FloatUnsuffixed(ref f) => self.writer().word(f.as_str().to_string()), + hir::LitKind::Bool(val) => { + if val { self.writer().word("true") } else { self.writer().word("false") } + } + hir::LitKind::ByteStr(ref v) => { + let mut escaped: String = String::new(); + for &ch in v.iter() { + escaped.extend(ascii::escape_default(ch) + .map(|c| c as char)); + } + self.writer().word(format!("b\"{}\"", escaped)) + } + } + } + pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> { self.maybe_print_comment(expr.span.lo())?; self.print_outer_attributes(&expr.attrs)?; diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index 7ff546b7467da..4e5718cc5ef2a 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -181,6 +181,8 @@ impl_stable_hash_for!(enum ::syntax::ast::LitKind { Bool(value) }); +impl_stable_hash_for_spanned!(::syntax::ast::LitKind); + impl_stable_hash_for!(enum ::syntax::ast::IntTy { Isize, I8, I16, I32, I64, I128 }); impl_stable_hash_for!(enum ::syntax::ast::UintTy { Usize, U8, U16, U32, U64, U128 }); impl_stable_hash_for!(enum ::syntax::ast::FloatTy { F32, F64 }); diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index f4ebfd79fe1db..38b6e2c197939 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -62,7 +62,7 @@ impl TypeLimits { /// Returns `true` iff the lint was overridden. fn lint_overflowing_range_endpoint<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, - lit: &ast::Lit, + lit: &hir::Lit, lit_val: u128, max: u128, expr: &'tcx hir::Expr, @@ -132,7 +132,7 @@ fn uint_ty_range(uint_ty: ast::UintTy) -> (u128, u128) { } } -fn get_bin_hex_repr(cx: &LateContext<'_, '_>, lit: &ast::Lit) -> Option { +fn get_bin_hex_repr(cx: &LateContext<'_, '_>, lit: &hir::Lit) -> Option { let src = cx.sess().source_map().span_to_snippet(lit.span).ok()?; let firstch = src.chars().next()?; @@ -249,7 +249,7 @@ fn lint_int_literal<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, type_limits: &TypeLimits, e: &'tcx hir::Expr, - lit: &ast::Lit, + lit: &hir::Lit, t: ast::IntTy, v: u128, ) { @@ -301,7 +301,7 @@ fn lint_int_literal<'a, 'tcx>( fn lint_uint_literal<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, e: &'tcx hir::Expr, - lit: &ast::Lit, + lit: &hir::Lit, t: ast::UintTy, ) { let uint_type = if let ast::UintTy::Usize = t { @@ -363,7 +363,7 @@ fn lint_literal<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, type_limits: &TypeLimits, e: &'tcx hir::Expr, - lit: &ast::Lit, + lit: &hir::Lit, ) { match cx.tables.node_type(e.hir_id).sty { ty::Int(t) => { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a32745f27e1a0..dc73ada1506c8 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3083,7 +3083,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // AST fragment checking fn check_lit(&self, - lit: &ast::Lit, + lit: &hir::Lit, expected: Expectation<'tcx>) -> Ty<'tcx> { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 04bc146e145ec..a188f1a936890 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1352,7 +1352,7 @@ pub enum StrStyle { } /// A literal. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Lit { pub node: LitKind, pub token: token::Lit, From a5b3f33cb90bf991342afa552bcd993e36f80fa7 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 9 May 2019 19:04:04 +0300 Subject: [PATCH 186/212] Eliminate `comments::Literal` --- src/librustc/hir/print.rs | 45 ++------ src/librustc_driver/pretty.rs | 6 +- src/librustdoc/clean/cfg.rs | 16 +-- src/libsyntax/attr/mod.rs | 7 +- src/libsyntax/parse/lexer/comments.rs | 29 +---- src/libsyntax/parse/parser.rs | 10 +- src/libsyntax/print/pprust.rs | 158 ++++++-------------------- 7 files changed, 61 insertions(+), 210 deletions(-) diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index b7260abb521ac..6d48ad94a6677 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -19,7 +19,6 @@ use std::ascii; use std::borrow::Cow; use std::cell::Cell; use std::io::{self, Write, Read}; -use std::iter::Peekable; use std::vec; pub enum AnnNode<'a> { @@ -77,7 +76,6 @@ pub struct State<'a> { pub s: pp::Printer<'a>, cm: Option<&'a SourceMap>, comments: Option>, - literals: Peekable>, cur_cmnt: usize, boxes: Vec, ann: &'a (dyn PpAnn + 'a), @@ -99,14 +97,6 @@ impl<'a> PrintState<'a> for State<'a> { fn cur_cmnt(&mut self) -> &mut usize { &mut self.cur_cmnt } - - fn cur_lit(&mut self) -> Option<&comments::Literal> { - self.literals.peek() - } - - fn bump_lit(&mut self) -> Option { - self.literals.next() - } } #[allow(non_upper_case_globals)] @@ -117,18 +107,16 @@ pub const default_columns: usize = 78; /// Requires you to pass an input filename and reader so that -/// it can scan the input text for comments and literals to -/// copy forward. +/// it can scan the input text for comments to copy forward. pub fn print_crate<'a>(cm: &'a SourceMap, sess: &ParseSess, krate: &hir::Crate, filename: FileName, input: &mut dyn Read, out: Box, - ann: &'a dyn PpAnn, - is_expanded: bool) + ann: &'a dyn PpAnn) -> io::Result<()> { - let mut s = State::new_from_input(cm, sess, filename, input, out, ann, is_expanded); + let mut s = State::new_from_input(cm, sess, filename, input, out, ann); // When printing the AST, we sometimes need to inject `#[no_std]` here. // Since you can't compile the HIR, it's not necessary. @@ -144,36 +132,21 @@ impl<'a> State<'a> { filename: FileName, input: &mut dyn Read, out: Box, - ann: &'a dyn PpAnn, - is_expanded: bool) + ann: &'a dyn PpAnn) -> State<'a> { - let (cmnts, lits) = comments::gather_comments_and_literals(sess, filename, input); - - State::new(cm, - out, - ann, - Some(cmnts), - // If the code is post expansion, don't use the table of - // literals, since it doesn't correspond with the literals - // in the AST anymore. - if is_expanded { - None - } else { - Some(lits) - }) + let comments = comments::gather_comments(sess, filename, input); + State::new(cm, out, ann, Some(comments)) } pub fn new(cm: &'a SourceMap, out: Box, ann: &'a dyn PpAnn, - comments: Option>, - literals: Option>) + comments: Option>) -> State<'a> { State { s: pp::mk_printer(out, default_columns), cm: Some(cm), comments, - literals: literals.unwrap_or_default().into_iter().peekable(), cur_cmnt: 0, boxes: Vec::new(), ann, @@ -190,7 +163,6 @@ pub fn to_string(ann: &dyn PpAnn, f: F) -> String s: pp::mk_printer(Box::new(&mut wr), default_columns), cm: None, comments: None, - literals: vec![].into_iter().peekable(), cur_cmnt: 0, boxes: Vec::new(), ann, @@ -1279,9 +1251,6 @@ impl<'a> State<'a> { fn print_literal(&mut self, lit: &hir::Lit) -> io::Result<()> { self.maybe_print_comment(lit.span.lo())?; - if let Some(ltrl) = self.next_lit(lit.span.lo()) { - return self.writer().word(ltrl.lit.clone()); - } match lit.node { hir::LitKind::Str(st, style) => self.print_string(&st.as_str(), style), hir::LitKind::Err(st) => { diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index fc8bf0baa99f6..c74ed5ec30c3c 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -805,8 +805,7 @@ pub fn print_after_hir_lowering<'tcx>( src_name, &mut rdr, box out, - annotation.pp_ann(), - true) + annotation.pp_ann()) }) } @@ -829,8 +828,7 @@ pub fn print_after_hir_lowering<'tcx>( src_name, &mut rdr, box out, - annotation.pp_ann(), - true); + annotation.pp_ann()); for node_id in uii.all_matching_node_ids(hir_map) { let node = hir_map.get(node_id); pp_state.print_node(node)?; diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 69445451503cc..257f02af4cdd8 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -414,10 +414,9 @@ impl<'a> fmt::Display for Html<'a> { mod test { use super::Cfg; - use syntax::symbol::Symbol; - use syntax::ast::*; - use syntax::source_map::dummy_spanned; use syntax_pos::DUMMY_SP; + use syntax::ast::*; + use syntax::symbol::Symbol; use syntax::with_globals; fn word_cfg(s: &str) -> Cfg { @@ -592,12 +591,11 @@ mod test { let mi = dummy_meta_item_word("all"); assert_eq!(Cfg::parse(&mi), Ok(word_cfg("all"))); + let node = LitKind::Str(Symbol::intern("done"), StrStyle::Cooked); + let (token, suffix) = node.lit_token(); let mi = MetaItem { path: Path::from_ident(Ident::from_str("all")), - node: MetaItemKind::NameValue(dummy_spanned(LitKind::Str( - Symbol::intern("done"), - StrStyle::Cooked, - ))), + node: MetaItemKind::NameValue(Lit { node, token, suffix, span: DUMMY_SP }), span: DUMMY_SP, }; assert_eq!(Cfg::parse(&mi), Ok(name_value_cfg("all", "done"))); @@ -627,9 +625,11 @@ mod test { #[test] fn test_parse_err() { with_globals(|| { + let node = LitKind::Bool(false); + let (token, suffix) = node.lit_token(); let mi = MetaItem { path: Path::from_ident(Ident::from_str("foo")), - node: MetaItemKind::NameValue(dummy_spanned(LitKind::Bool(false))), + node: MetaItemKind::NameValue(Lit { node, token, suffix, span: DUMMY_SP }), span: DUMMY_SP, }; assert!(Cfg::parse(&mi).is_err()); diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index 2b87458108336..e23c18266519f 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -565,8 +565,9 @@ impl MetaItemKind { Some(TokenTree::Token(_, token::Eq)) => { tokens.next(); return if let Some(TokenTree::Token(span, token)) = tokens.next() { - LitKind::from_token(token) - .map(|(node, token, suffix)| MetaItemKind::NameValue(Lit { node, token, suffix, span })) + LitKind::from_token(token).map(|(node, token, suffix)| { + MetaItemKind::NameValue(Lit { node, token, suffix, span }) + }) } else { None }; @@ -635,7 +636,7 @@ impl LitKind { } } - pub(crate) fn lit_token(&self) -> (token::Lit, Option) { + pub fn lit_token(&self) -> (token::Lit, Option) { use std::ascii; match *self { diff --git a/src/libsyntax/parse/lexer/comments.rs b/src/libsyntax/parse/lexer/comments.rs index 74fff3324eacf..97d3fc002e9b0 100644 --- a/src/libsyntax/parse/lexer/comments.rs +++ b/src/libsyntax/parse/lexer/comments.rs @@ -3,8 +3,7 @@ pub use CommentStyle::*; use crate::ast; use crate::source_map::SourceMap; use crate::parse::lexer::{is_block_doc_comment, is_pattern_whitespace}; -use crate::parse::lexer::{self, ParseSess, StringReader, TokenAndSpan}; -use crate::print::pprust; +use crate::parse::lexer::{self, ParseSess, StringReader}; use syntax_pos::{BytePos, CharPos, Pos, FileName}; use log::debug; @@ -339,16 +338,9 @@ fn consume_comment(rdr: &mut StringReader<'_>, debug!("<<< consume comment"); } -#[derive(Clone)] -pub struct Literal { - pub lit: String, - pub pos: BytePos, -} - // it appears this function is called only from pprust... that's // probably not a good thing. -pub fn gather_comments_and_literals(sess: &ParseSess, path: FileName, srdr: &mut dyn Read) - -> (Vec, Vec) +pub fn gather_comments(sess: &ParseSess, path: FileName, srdr: &mut dyn Read) -> Vec { let mut src = String::new(); srdr.read_to_string(&mut src).unwrap(); @@ -357,7 +349,6 @@ pub fn gather_comments_and_literals(sess: &ParseSess, path: FileName, srdr: &mut let mut rdr = lexer::StringReader::new_raw(sess, source_file, None); let mut comments: Vec = Vec::new(); - let mut literals: Vec = Vec::new(); let mut code_to_the_left = false; // Only code let mut anything_to_the_left = false; // Code or comments @@ -382,26 +373,12 @@ pub fn gather_comments_and_literals(sess: &ParseSess, path: FileName, srdr: &mut } } - let bstart = rdr.pos; rdr.next_token(); - // discard, and look ahead; we're working with internal state - let TokenAndSpan { tok, sp } = rdr.peek(); - if tok.is_lit() { - rdr.with_str_from(bstart, |s| { - debug!("tok lit: {}", s); - literals.push(Literal { - lit: s.to_string(), - pos: sp.lo(), - }); - }) - } else { - debug!("tok: {}", pprust::token_to_string(&tok)); - } code_to_the_left = true; anything_to_the_left = true; } - (comments, literals) + comments } #[cfg(test)] diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index b988cb1447df7..8c0c2f4b6e28a 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2121,11 +2121,11 @@ impl<'a> Parser<'a> { Applicability::MachineApplicable, ); err.emit(); - return Ok(match float_suffix { - "f32" => (ast::LitKind::Float(val, ast::FloatTy::F32), token::Float(val), suffix), - "f64" => (ast::LitKind::Float(val, ast::FloatTy::F64), token::Float(val), suffix), - _ => (ast::LitKind::FloatUnsuffixed(val), token::Float(val), suffix), - }); + return Ok((match float_suffix { + "f32" => ast::LitKind::Float(val, ast::FloatTy::F32), + "f64" => ast::LitKind::Float(val, ast::FloatTy::F64), + _ => ast::LitKind::FloatUnsuffixed(val), + }, token::Float(val), suffix)); } else { unreachable!(); }; diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 0e93b857708f7..fa16a2b200ff3 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -20,10 +20,8 @@ use rustc_target::spec::abi::{self, Abi}; use syntax_pos::{self, BytePos}; use syntax_pos::{DUMMY_SP, FileName}; -use std::ascii; use std::borrow::Cow; use std::io::{self, Write, Read}; -use std::iter::Peekable; use std::vec; pub enum AnnNode<'a> { @@ -49,8 +47,7 @@ impl PpAnn for NoAnn {} pub struct State<'a> { pub s: pp::Printer<'a>, cm: Option<&'a SourceMap>, - comments: Option >, - literals: Peekable>, + comments: Option>, cur_cmnt: usize, boxes: Vec, ann: &'a (dyn PpAnn+'a), @@ -62,7 +59,6 @@ fn rust_printer<'a>(writer: Box, ann: &'a dyn PpAnn) -> State<'a> s: pp::mk_printer(writer, DEFAULT_COLUMNS), cm: None, comments: None, - literals: vec![].into_iter().peekable(), cur_cmnt: 0, boxes: Vec::new(), ann, @@ -75,8 +71,7 @@ pub const INDENT_UNIT: usize = 4; pub const DEFAULT_COLUMNS: usize = 78; /// Requires you to pass an input filename and reader so that -/// it can scan the input text for comments and literals to -/// copy forward. +/// it can scan the input text for comments to copy forward. pub fn print_crate<'a>(cm: &'a SourceMap, sess: &ParseSess, krate: &ast::Crate, @@ -118,36 +113,23 @@ impl<'a> State<'a> { out: Box, ann: &'a dyn PpAnn, is_expanded: bool) -> State<'a> { - let (cmnts, lits) = comments::gather_comments_and_literals(sess, filename, input); - - State::new( - cm, - out, - ann, - Some(cmnts), - // If the code is post expansion, don't use the table of - // literals, since it doesn't correspond with the literals - // in the AST anymore. - if is_expanded { None } else { Some(lits) }, - is_expanded - ) + let comments = comments::gather_comments(sess, filename, input); + State::new(cm, out, ann, Some(comments), is_expanded) } pub fn new(cm: &'a SourceMap, out: Box, ann: &'a dyn PpAnn, comments: Option>, - literals: Option>, is_expanded: bool) -> State<'a> { State { s: pp::mk_printer(out, DEFAULT_COLUMNS), cm: Some(cm), comments, - literals: literals.unwrap_or_default().into_iter().peekable(), cur_cmnt: 0, boxes: Vec::new(), ann, - is_expanded: is_expanded + is_expanded, } } } @@ -180,6 +162,31 @@ fn binop_to_string(op: BinOpToken) -> &'static str { } } +fn literal_to_string(lit: token::Lit, suffix: Option) -> String { + let mut out = match lit { + token::Byte(b) => format!("b'{}'", b), + token::Char(c) => format!("'{}'", c), + token::Err(c) => format!("'{}'", c), + token::Bool(c) | + token::Float(c) | + token::Integer(c) => c.to_string(), + token::Str_(s) => format!("\"{}\"", s), + token::StrRaw(s, n) => format!("r{delim}\"{string}\"{delim}", + delim="#".repeat(n as usize), + string=s), + token::ByteStr(v) => format!("b\"{}\"", v), + token::ByteStrRaw(s, n) => format!("br{delim}\"{string}\"{delim}", + delim="#".repeat(n as usize), + string=s), + }; + + if let Some(suffix) = suffix { + out.push_str(&suffix.as_str()) + } + + out +} + pub fn token_to_string(tok: &Token) -> String { match *tok { token::Eq => "=".to_string(), @@ -223,30 +230,7 @@ pub fn token_to_string(tok: &Token) -> String { token::SingleQuote => "'".to_string(), /* Literals */ - token::Literal(lit, suf) => { - let mut out = match lit { - token::Bool(_) => panic!("literal token contains `Lit::Bool`"), - token::Byte(b) => format!("b'{}'", b), - token::Char(c) => format!("'{}'", c), - token::Err(c) => format!("'{}'", c), - token::Float(c) | - token::Integer(c) => c.to_string(), - token::Str_(s) => format!("\"{}\"", s), - token::StrRaw(s, n) => format!("r{delim}\"{string}\"{delim}", - delim="#".repeat(n as usize), - string=s), - token::ByteStr(v) => format!("b\"{}\"", v), - token::ByteStrRaw(s, n) => format!("br{delim}\"{string}\"{delim}", - delim="#".repeat(n as usize), - string=s), - }; - - if let Some(s) = suf { - out.push_str(&s.as_str()) - } - - out - } + token::Literal(lit, suf) => literal_to_string(lit, suf), /* Name components */ token::Ident(s, false) => s.to_string(), @@ -439,8 +423,6 @@ pub trait PrintState<'a> { fn boxes(&mut self) -> &mut Vec; fn comments(&mut self) -> &mut Option>; fn cur_cmnt(&mut self) -> &mut usize; - fn cur_lit(&mut self) -> Option<&comments::Literal>; - fn bump_lit(&mut self) -> Option; fn word_space>>(&mut self, w: S) -> io::Result<()> { self.writer().word(w)?; @@ -505,21 +487,6 @@ pub trait PrintState<'a> { self.end() } - fn next_lit(&mut self, pos: BytePos) -> Option { - while let Some(ltrl) = self.cur_lit().cloned() { - if ltrl.pos > pos { break; } - - // we don't need the value here since we're forced to clone cur_lit - // due to lack of NLL. - self.bump_lit(); - if ltrl.pos == pos { - return Some(ltrl); - } - } - - None - } - fn maybe_print_comment(&mut self, pos: BytePos) -> io::Result<()> { while let Some(ref cmnt) = self.next_comment() { if cmnt.pos < pos { @@ -607,60 +574,7 @@ pub trait PrintState<'a> { fn print_literal(&mut self, lit: &ast::Lit) -> io::Result<()> { self.maybe_print_comment(lit.span.lo())?; - if let Some(ltrl) = self.next_lit(lit.span.lo()) { - return self.writer().word(ltrl.lit.clone()); - } - match lit.node { - ast::LitKind::Str(st, style) => self.print_string(&st.as_str(), style), - ast::LitKind::Err(st) => { - let st = st.as_str().escape_debug().to_string(); - let mut res = String::with_capacity(st.len() + 2); - res.push('\''); - res.push_str(&st); - res.push('\''); - self.writer().word(res) - } - ast::LitKind::Byte(byte) => { - let mut res = String::from("b'"); - res.extend(ascii::escape_default(byte).map(|c| c as char)); - res.push('\''); - self.writer().word(res) - } - ast::LitKind::Char(ch) => { - let mut res = String::from("'"); - res.extend(ch.escape_default()); - res.push('\''); - self.writer().word(res) - } - ast::LitKind::Int(i, t) => { - match t { - ast::LitIntType::Signed(st) => { - self.writer().word(st.val_to_string(i as i128)) - } - ast::LitIntType::Unsigned(ut) => { - self.writer().word(ut.val_to_string(i)) - } - ast::LitIntType::Unsuffixed => { - self.writer().word(i.to_string()) - } - } - } - ast::LitKind::Float(ref f, t) => { - self.writer().word(format!("{}{}", &f, t.ty_to_string())) - } - ast::LitKind::FloatUnsuffixed(ref f) => self.writer().word(f.as_str().to_string()), - ast::LitKind::Bool(val) => { - if val { self.writer().word("true") } else { self.writer().word("false") } - } - ast::LitKind::ByteStr(ref v) => { - let mut escaped: String = String::new(); - for &ch in v.iter() { - escaped.extend(ascii::escape_default(ch) - .map(|c| c as char)); - } - self.writer().word(format!("b\"{}\"", escaped)) - } - } + self.writer().word(literal_to_string(lit.token, lit.suffix)) } fn print_string(&mut self, st: &str, @@ -881,14 +795,6 @@ impl<'a> PrintState<'a> for State<'a> { fn cur_cmnt(&mut self) -> &mut usize { &mut self.cur_cmnt } - - fn cur_lit(&mut self) -> Option<&comments::Literal> { - self.literals.peek() - } - - fn bump_lit(&mut self) -> Option { - self.literals.next() - } } impl<'a> State<'a> { From 8739668438a40712a0bc617bc587d415c8cb42f0 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 10 May 2019 03:00:51 +0300 Subject: [PATCH 187/212] Simplify conversions between tokens and semantic literals --- src/librustc/hir/print.rs | 56 +---- src/librustdoc/clean/cfg.rs | 24 +- src/libsyntax/attr/mod.rs | 104 +++++---- src/libsyntax/ext/build.rs | 11 +- src/libsyntax/parse/mod.rs | 212 +++++++++++------- src/libsyntax/parse/parser.rs | 153 +++---------- src/libsyntax/parse/token.rs | 7 + src/libsyntax/print/pprust.rs | 2 +- .../ui/malformed/malformed-interpolated.rs | 5 +- .../malformed/malformed-interpolated.stderr | 9 +- 10 files changed, 259 insertions(+), 324 deletions(-) diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 6d48ad94a6677..475bf8d837239 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -5,7 +5,7 @@ use syntax::parse::ParseSess; use syntax::parse::lexer::comments; use syntax::print::pp::{self, Breaks}; use syntax::print::pp::Breaks::{Consistent, Inconsistent}; -use syntax::print::pprust::PrintState; +use syntax::print::pprust::{self, PrintState}; use syntax::ptr::P; use syntax::symbol::keywords; use syntax::util::parser::{self, AssocOp, Fixity}; @@ -15,7 +15,6 @@ use crate::hir; use crate::hir::{PatKind, GenericBound, TraitBoundModifier, RangeEnd}; use crate::hir::{GenericParam, GenericParamKind, GenericArg}; -use std::ascii; use std::borrow::Cow; use std::cell::Cell; use std::io::{self, Write, Read}; @@ -1251,57 +1250,8 @@ impl<'a> State<'a> { fn print_literal(&mut self, lit: &hir::Lit) -> io::Result<()> { self.maybe_print_comment(lit.span.lo())?; - match lit.node { - hir::LitKind::Str(st, style) => self.print_string(&st.as_str(), style), - hir::LitKind::Err(st) => { - let st = st.as_str().escape_debug().to_string(); - let mut res = String::with_capacity(st.len() + 2); - res.push('\''); - res.push_str(&st); - res.push('\''); - self.writer().word(res) - } - hir::LitKind::Byte(byte) => { - let mut res = String::from("b'"); - res.extend(ascii::escape_default(byte).map(|c| c as char)); - res.push('\''); - self.writer().word(res) - } - hir::LitKind::Char(ch) => { - let mut res = String::from("'"); - res.extend(ch.escape_default()); - res.push('\''); - self.writer().word(res) - } - hir::LitKind::Int(i, t) => { - match t { - ast::LitIntType::Signed(st) => { - self.writer().word(st.val_to_string(i as i128)) - } - ast::LitIntType::Unsigned(ut) => { - self.writer().word(ut.val_to_string(i)) - } - ast::LitIntType::Unsuffixed => { - self.writer().word(i.to_string()) - } - } - } - hir::LitKind::Float(ref f, t) => { - self.writer().word(format!("{}{}", &f, t.ty_to_string())) - } - hir::LitKind::FloatUnsuffixed(ref f) => self.writer().word(f.as_str().to_string()), - hir::LitKind::Bool(val) => { - if val { self.writer().word("true") } else { self.writer().word("false") } - } - hir::LitKind::ByteStr(ref v) => { - let mut escaped: String = String::new(); - for &ch in v.iter() { - escaped.extend(ascii::escape_default(ch) - .map(|c| c as char)); - } - self.writer().word(format!("b\"{}\"", escaped)) - } - } + let (token, suffix) = lit.node.to_lit_token(); + self.writer().word(pprust::literal_to_string(token, suffix)) } pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> { diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 257f02af4cdd8..51fe26b374313 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -591,13 +591,10 @@ mod test { let mi = dummy_meta_item_word("all"); assert_eq!(Cfg::parse(&mi), Ok(word_cfg("all"))); - let node = LitKind::Str(Symbol::intern("done"), StrStyle::Cooked); - let (token, suffix) = node.lit_token(); - let mi = MetaItem { - path: Path::from_ident(Ident::from_str("all")), - node: MetaItemKind::NameValue(Lit { node, token, suffix, span: DUMMY_SP }), - span: DUMMY_SP, - }; + let mi = attr::mk_name_value_item_str( + Ident::from_str("all"), + dummy_spanned(Symbol::intern("done")) + ); assert_eq!(Cfg::parse(&mi), Ok(name_value_cfg("all", "done"))); let mi = dummy_meta_item_list!(all, [a, b]); @@ -625,13 +622,12 @@ mod test { #[test] fn test_parse_err() { with_globals(|| { - let node = LitKind::Bool(false); - let (token, suffix) = node.lit_token(); - let mi = MetaItem { - path: Path::from_ident(Ident::from_str("foo")), - node: MetaItemKind::NameValue(Lit { node, token, suffix, span: DUMMY_SP }), - span: DUMMY_SP, - }; + let mi = attr::mk_name_value_item( + DUMMY_SP, + Ident::from_str("foo"), + LitKind::Bool(false), + DUMMY_SP, + ); assert!(Cfg::parse(&mi).is_err()); let mi = dummy_meta_item_list!(not, [a, b]); diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index e23c18266519f..c122e1994e749 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -14,7 +14,7 @@ pub use StabilityLevel::*; use crate::ast; use crate::ast::{AttrId, Attribute, AttrStyle, Name, Ident, Path, PathSegment}; use crate::ast::{MetaItem, MetaItemKind, NestedMetaItem}; -use crate::ast::{Lit, LitKind, Expr, ExprKind, Item, Local, Stmt, StmtKind, GenericParam}; +use crate::ast::{Lit, LitKind, Expr, Item, Local, Stmt, StmtKind, GenericParam}; use crate::mut_visit::visit_clobber; use crate::source_map::{BytePos, Spanned, dummy_spanned}; use crate::parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration}; @@ -27,9 +27,11 @@ use crate::ThinVec; use crate::tokenstream::{TokenStream, TokenTree, DelimSpan}; use crate::GLOBALS; +use errors::Handler; use log::debug; use syntax_pos::{FileName, Span}; +use std::ascii; use std::iter; use std::ops::DerefMut; @@ -350,14 +352,13 @@ impl Attribute { /* Constructors */ pub fn mk_name_value_item_str(ident: Ident, value: Spanned) -> MetaItem { - let node = LitKind::Str(value.node, ast::StrStyle::Cooked); - let (token, suffix) = node.lit_token(); - let value = Lit { node, token, suffix, span: value.span }; - mk_name_value_item(ident.span.to(value.span), ident, value) + let lit_kind = LitKind::Str(value.node, ast::StrStyle::Cooked); + mk_name_value_item(ident.span.to(value.span), ident, lit_kind, value.span) } -pub fn mk_name_value_item(span: Span, ident: Ident, value: Lit) -> MetaItem { - MetaItem { path: Path::from_ident(ident), span, node: MetaItemKind::NameValue(value) } +pub fn mk_name_value_item(span: Span, ident: Ident, lit_kind: LitKind, lit_span: Span) -> MetaItem { + let lit = Lit::from_lit_kind(lit_kind, lit_span); + MetaItem { path: Path::from_ident(ident), span, node: MetaItemKind::NameValue(lit) } } pub fn mk_list_item(span: Span, ident: Ident, items: Vec) -> MetaItem { @@ -419,9 +420,8 @@ pub fn mk_spanned_attr_outer(sp: Span, id: AttrId, item: MetaItem) -> Attribute pub fn mk_sugared_doc_attr(id: AttrId, text: Symbol, span: Span) -> Attribute { let style = doc_comment_style(&text.as_str()); - let node = LitKind::Str(text, ast::StrStyle::Cooked); - let (token, suffix) = node.lit_token(); - let lit = Lit { node, token, suffix, span }; + let lit_kind = LitKind::Str(text, ast::StrStyle::Cooked); + let lit = Lit::from_lit_kind(lit_kind, span); Attribute { id, style, @@ -565,9 +565,7 @@ impl MetaItemKind { Some(TokenTree::Token(_, token::Eq)) => { tokens.next(); return if let Some(TokenTree::Token(span, token)) = tokens.next() { - LitKind::from_token(token).map(|(node, token, suffix)| { - MetaItemKind::NameValue(Lit { node, token, suffix, span }) - }) + Lit::from_token(&token, span, None).map(MetaItemKind::NameValue) } else { None }; @@ -612,9 +610,9 @@ impl NestedMetaItem { where I: Iterator, { if let Some(TokenTree::Token(span, token)) = tokens.peek().cloned() { - if let Some((node, token, suffix)) = LitKind::from_token(token) { + if let Some(lit) = Lit::from_token(&token, span, None) { tokens.next(); - return Some(NestedMetaItem::Literal(Lit { node, token, suffix, span })); + return Some(NestedMetaItem::Literal(lit)); } } @@ -624,21 +622,19 @@ impl NestedMetaItem { impl Lit { crate fn tokens(&self) -> TokenStream { - TokenTree::Token(self.span, self.node.token()).into() + let token = match self.token { + token::Bool(symbol) => Token::Ident(Ident::with_empty_ctxt(symbol), false), + token => Token::Literal(token, self.suffix), + }; + TokenTree::Token(self.span, token).into() } } impl LitKind { - fn token(&self) -> Token { - match self.lit_token() { - (token::Bool(symbol), _) => Token::Ident(Ident::with_empty_ctxt(symbol), false), - (lit, suffix) => Token::Literal(lit, suffix), - } - } - - pub fn lit_token(&self) -> (token::Lit, Option) { - use std::ascii; - + /// Attempts to recover a token from semantic literal. + /// This function is used when the original token doesn't exist (e.g. the literal is created + /// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing). + pub fn to_lit_token(&self) -> (token::Lit, Option) { match *self { LitKind::Str(string, ast::StrStyle::Cooked) => { let escaped = string.as_str().escape_default().to_string(); @@ -679,29 +675,45 @@ impl LitKind { LitKind::Err(val) => (token::Lit::Err(val), None), } } +} - fn from_token(token: Token) -> Option<(LitKind, token::Lit, Option)> { - match token { - Token::Ident(ident, false) if ident.name == keywords::True.name() => - Some((LitKind::Bool(true), token::Bool(ident.name), None)), - Token::Ident(ident, false) if ident.name == keywords::False.name() => - Some((LitKind::Bool(false), token::Bool(ident.name), None)), - Token::Interpolated(nt) => match *nt { - token::NtExpr(ref v) | token::NtLiteral(ref v) => match v.node { - ExprKind::Lit(ref lit) => Some((lit.node.clone(), lit.token, lit.suffix)), - _ => None, - }, - _ => None, - }, - Token::Literal(lit, suf) => { - let (suffix_illegal, result) = parse::lit_token(lit, suf, None); - if result.is_none() || suffix_illegal && suf.is_some() { - return None; +impl Lit { + /// Converts literal token with a suffix into an AST literal. + /// Works speculatively and may return `None` is diagnostic handler is not passed. + /// If diagnostic handler is passed, may return `Some`, + /// possibly after reporting non-fatal errors and recovery, or `None` for irrecoverable errors. + crate fn from_token( + token: &token::Token, + span: Span, + diag: Option<(Span, &Handler)>, + ) -> Option { + let (token, suffix) = match *token { + token::Ident(ident, false) if ident.name == keywords::True.name() || + ident.name == keywords::False.name() => + (token::Bool(ident.name), None), + token::Literal(token, suffix) => + (token, suffix), + token::Interpolated(ref nt) => { + if let token::NtExpr(expr) | token::NtLiteral(expr) = &**nt { + if let ast::ExprKind::Lit(lit) = &expr.node { + return Some(lit.clone()); + } } - Some((result.unwrap(), lit, suf)) + return None; } - _ => None, - } + _ => return None, + }; + + let node = LitKind::from_lit_token(token, suffix, diag)?; + Some(Lit { node, token, suffix, span }) + } + + /// Attempts to recover an AST literal from semantic literal. + /// This function is used when the original token doesn't exist (e.g. the literal is created + /// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing). + pub fn from_lit_kind(node: LitKind, span: Span) -> Lit { + let (token, suffix) = node.to_lit_token(); + Lit { node, token, suffix, span } } } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 0f9977e85038b..d24106f697e19 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -697,9 +697,9 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.expr_struct(span, self.path_ident(span, id), fields) } - fn expr_lit(&self, span: Span, node: ast::LitKind) -> P { - let (token, suffix) = node.lit_token(); - self.expr(span, ast::ExprKind::Lit(ast::Lit { node, token, suffix, span })) + fn expr_lit(&self, span: Span, lit_kind: ast::LitKind) -> P { + let lit = ast::Lit::from_lit_kind(lit_kind, span); + self.expr(span, ast::ExprKind::Lit(lit)) } fn expr_usize(&self, span: Span, i: usize) -> P { self.expr_lit(span, ast::LitKind::Int(i as u128, @@ -1165,11 +1165,10 @@ impl<'a> AstBuilder for ExtCtxt<'a> { attr::mk_list_item(sp, Ident::with_empty_ctxt(name).with_span_pos(sp), mis) } - fn meta_name_value(&self, span: Span, name: ast::Name, node: ast::LitKind) + fn meta_name_value(&self, span: Span, name: ast::Name, lit_kind: ast::LitKind) -> ast::MetaItem { - let (token, suffix) = node.lit_token(); attr::mk_name_value_item(span, Ident::with_empty_ctxt(name).with_span_pos(span), - ast::Lit { node, token, suffix, span }) + lit_kind, span) } fn item_use(&self, sp: Span, diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 4d4e99009a9d2..868b344c06584 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -1,11 +1,11 @@ //! The main parser interface. -use crate::ast::{self, CrateConfig, NodeId}; +use crate::ast::{self, CrateConfig, LitKind, NodeId}; use crate::early_buffered_lints::{BufferedEarlyLint, BufferedEarlyLintId}; use crate::source_map::{SourceMap, FilePathMapping}; use crate::feature_gate::UnstableFeatures; use crate::parse::parser::Parser; -use crate::symbol::Symbol; +use crate::symbol::{keywords, Symbol}; use crate::syntax::parse::parser::emit_unclosed_delims; use crate::tokenstream::{TokenStream, TokenTree}; use crate::diagnostics::plugin::ErrorMap; @@ -371,97 +371,151 @@ macro_rules! err { } } -crate fn lit_token(lit: token::Lit, suf: Option, diag: Option<(Span, &Handler)>) - -> (bool /* suffix illegal? */, Option) { - use ast::LitKind; - - match lit { - token::Bool(_) => panic!("literal token contains `Lit::Bool`"), - token::Byte(i) => { - let lit_kind = match unescape_byte(&i.as_str()) { - Ok(c) => LitKind::Byte(c), - Err(_) => LitKind::Err(i), - }; - (true, Some(lit_kind)) - }, - token::Char(i) => { - let lit_kind = match unescape_char(&i.as_str()) { - Ok(c) => LitKind::Char(c), - Err(_) => LitKind::Err(i), +crate fn expect_no_suffix(sp: Span, diag: &Handler, kind: &str, suffix: Option) { + match suffix { + None => {/* everything ok */} + Some(suf) => { + let text = suf.as_str(); + if text.is_empty() { + diag.span_bug(sp, "found empty literal suffix in Some") + } + let mut err = if kind == "a tuple index" && + ["i32", "u32", "isize", "usize"].contains(&text.to_string().as_str()) + { + // #59553: warn instead of reject out of hand to allow the fix to percolate + // through the ecosystem when people fix their macros + let mut err = diag.struct_span_warn( + sp, + &format!("suffixes on {} are invalid", kind), + ); + err.note(&format!( + "`{}` is *temporarily* accepted on tuple index fields as it was \ + incorrectly accepted on stable for a few releases", + text, + )); + err.help( + "on proc macros, you'll want to use `syn::Index::from` or \ + `proc_macro::Literal::*_unsuffixed` for code that will desugar \ + to tuple field access", + ); + err.note( + "for more context, see https://github.com/rust-lang/rust/issues/60210", + ); + err + } else { + diag.struct_span_err(sp, &format!("suffixes on {} are invalid", kind)) }; - (true, Some(lit_kind)) - }, - token::Err(i) => (true, Some(LitKind::Err(i))), - - // There are some valid suffixes for integer and float literals, - // so all the handling is done internally. - token::Integer(s) => (false, integer_lit(&s.as_str(), suf, diag)), - token::Float(s) => (false, float_lit(&s.as_str(), suf, diag)), - - token::Str_(mut sym) => { - // If there are no characters requiring special treatment we can - // reuse the symbol from the Token. Otherwise, we must generate a - // new symbol because the string in the LitKind is different to the - // string in the Token. - let mut has_error = false; - let s = &sym.as_str(); - if s.as_bytes().iter().any(|&c| c == b'\\' || c == b'\r') { - let mut buf = String::with_capacity(s.len()); - unescape_str(s, &mut |_, unescaped_char| { - match unescaped_char { + err.span_label(sp, format!("invalid suffix `{}`", text)); + err.emit(); + } + } +} + +impl LitKind { + /// Converts literal token with a suffix into a semantic literal. + /// Works speculatively and may return `None` is diagnostic handler is not passed. + /// If diagnostic handler is passed, always returns `Some`, + /// possibly after reporting non-fatal errors and recovery. + crate fn from_lit_token( + lit: token::Lit, + suf: Option, + diag: Option<(Span, &Handler)> + ) -> Option { + if suf.is_some() && !lit.may_have_suffix() { + err!(diag, |span, diag| { + expect_no_suffix(span, diag, &format!("a {}", lit.literal_name()), suf) + }); + } + + Some(match lit { + token::Bool(i) => { + assert!(i == keywords::True.name() || i == keywords::False.name()); + LitKind::Bool(i == keywords::True.name()) + } + token::Byte(i) => { + match unescape_byte(&i.as_str()) { + Ok(c) => LitKind::Byte(c), + Err(_) => LitKind::Err(i), + } + }, + token::Char(i) => { + match unescape_char(&i.as_str()) { + Ok(c) => LitKind::Char(c), + Err(_) => LitKind::Err(i), + } + }, + token::Err(i) => LitKind::Err(i), + + // There are some valid suffixes for integer and float literals, + // so all the handling is done internally. + token::Integer(s) => return integer_lit(&s.as_str(), suf, diag), + token::Float(s) => return float_lit(&s.as_str(), suf, diag), + + token::Str_(mut sym) => { + // If there are no characters requiring special treatment we can + // reuse the symbol from the Token. Otherwise, we must generate a + // new symbol because the string in the LitKind is different to the + // string in the Token. + let mut has_error = false; + let s = &sym.as_str(); + if s.as_bytes().iter().any(|&c| c == b'\\' || c == b'\r') { + let mut buf = String::with_capacity(s.len()); + unescape_str(s, &mut |_, unescaped_char| { + match unescaped_char { + Ok(c) => buf.push(c), + Err(_) => has_error = true, + } + }); + if has_error { + return Some(LitKind::Err(sym)); + } + sym = Symbol::intern(&buf) + } + + LitKind::Str(sym, ast::StrStyle::Cooked) + } + token::StrRaw(mut sym, n) => { + // Ditto. + let s = &sym.as_str(); + if s.contains('\r') { + sym = Symbol::intern(&raw_str_lit(s)); + } + LitKind::Str(sym, ast::StrStyle::Raw(n)) + } + token::ByteStr(i) => { + let s = &i.as_str(); + let mut buf = Vec::with_capacity(s.len()); + let mut has_error = false; + unescape_byte_str(s, &mut |_, unescaped_byte| { + match unescaped_byte { Ok(c) => buf.push(c), Err(_) => has_error = true, } }); if has_error { - return (true, Some(LitKind::Err(sym))); + return Some(LitKind::Err(i)); } - sym = Symbol::intern(&buf) + buf.shrink_to_fit(); + LitKind::ByteStr(Lrc::new(buf)) } - - (true, Some(LitKind::Str(sym, ast::StrStyle::Cooked))) - } - token::StrRaw(mut sym, n) => { - // Ditto. - let s = &sym.as_str(); - if s.contains('\r') { - sym = Symbol::intern(&raw_str_lit(s)); + token::ByteStrRaw(i, _) => { + LitKind::ByteStr(Lrc::new(i.to_string().into_bytes())) } - (true, Some(LitKind::Str(sym, ast::StrStyle::Raw(n)))) - } - token::ByteStr(i) => { - let s = &i.as_str(); - let mut buf = Vec::with_capacity(s.len()); - let mut has_error = false; - unescape_byte_str(s, &mut |_, unescaped_byte| { - match unescaped_byte { - Ok(c) => buf.push(c), - Err(_) => has_error = true, - } - }); - if has_error { - return (true, Some(LitKind::Err(i))); - } - buf.shrink_to_fit(); - (true, Some(LitKind::ByteStr(Lrc::new(buf)))) - } - token::ByteStrRaw(i, _) => { - (true, Some(LitKind::ByteStr(Lrc::new(i.to_string().into_bytes())))) - } + }) } } fn filtered_float_lit(data: Symbol, suffix: Option, diag: Option<(Span, &Handler)>) - -> Option { + -> Option { debug!("filtered_float_lit: {}, {:?}", data, suffix); let suffix = match suffix { Some(suffix) => suffix, - None => return Some(ast::LitKind::FloatUnsuffixed(data)), + None => return Some(LitKind::FloatUnsuffixed(data)), }; Some(match &*suffix.as_str() { - "f32" => ast::LitKind::Float(data, ast::FloatTy::F32), - "f64" => ast::LitKind::Float(data, ast::FloatTy::F64), + "f32" => LitKind::Float(data, ast::FloatTy::F32), + "f64" => LitKind::Float(data, ast::FloatTy::F64), suf => { err!(diag, |span, diag| { if suf.len() >= 2 && looks_like_width_suffix(&['f'], suf) { @@ -477,12 +531,12 @@ fn filtered_float_lit(data: Symbol, suffix: Option, diag: Option<(Span, } }); - ast::LitKind::FloatUnsuffixed(data) + LitKind::FloatUnsuffixed(data) } }) } fn float_lit(s: &str, suffix: Option, diag: Option<(Span, &Handler)>) - -> Option { + -> Option { debug!("float_lit: {:?}, {:?}", s, suffix); // FIXME #2252: bounds checking float literals is deferred until trans @@ -499,7 +553,7 @@ fn float_lit(s: &str, suffix: Option, diag: Option<(Span, &Handler)>) } fn integer_lit(s: &str, suffix: Option, diag: Option<(Span, &Handler)>) - -> Option { + -> Option { // s can only be ascii, byte indexing is fine // Strip underscores without allocating a new String unless necessary. @@ -595,7 +649,7 @@ fn integer_lit(s: &str, suffix: Option, diag: Option<(Span, &Handler)>) string was {:?}, the original suffix was {:?}", ty, base, s, orig, suffix); Some(match u128::from_str_radix(s, base) { - Ok(r) => ast::LitKind::Int(r, ty), + Ok(r) => LitKind::Int(r, ty), Err(_) => { // small bases are lexed as if they were base 10, e.g, the string // might be `0b10201`. This will cause the conversion above to fail, @@ -608,7 +662,7 @@ fn integer_lit(s: &str, suffix: Option, diag: Option<(Span, &Handler)>) if !already_errored { err!(diag, |span, diag| diag.span_err(span, "int literal is too large")); } - ast::LitKind::Int(0, ty) + LitKind::Int(0, ty) } }) } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 8c0c2f4b6e28a..b81f7be9c2c14 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -15,7 +15,7 @@ use crate::ast::{ForeignItem, ForeignItemKind, FunctionRetTy}; use crate::ast::{GenericParam, GenericParamKind}; use crate::ast::GenericArg; use crate::ast::{Ident, ImplItem, IsAsync, IsAuto, Item, ItemKind}; -use crate::ast::{Label, Lifetime, Lit, LitKind}; +use crate::ast::{Label, Lifetime, Lit}; use crate::ast::{Local, LocalSource}; use crate::ast::MacStmtStyle; use crate::ast::{Mac, Mac_, MacDelimiter}; @@ -46,7 +46,7 @@ use crate::ptr::P; use crate::parse::PResult; use crate::ThinVec; use crate::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint}; -use crate::symbol::{Symbol, keywords}; +use crate::symbol::{keywords, Symbol}; use errors::{Applicability, DiagnosticBuilder, DiagnosticId, FatalError}; use rustc_target::spec::abi::{self, Abi}; @@ -1109,43 +1109,7 @@ impl<'a> Parser<'a> { } fn expect_no_suffix(&self, sp: Span, kind: &str, suffix: Option) { - match suffix { - None => {/* everything ok */} - Some(suf) => { - let text = suf.as_str(); - if text.is_empty() { - self.span_bug(sp, "found empty literal suffix in Some") - } - let mut err = if kind == "a tuple index" && - ["i32", "u32", "isize", "usize"].contains(&text.to_string().as_str()) - { - // #59553: warn instead of reject out of hand to allow the fix to percolate - // through the ecosystem when people fix their macros - let mut err = self.struct_span_warn( - sp, - &format!("suffixes on {} are invalid", kind), - ); - err.note(&format!( - "`{}` is *temporarily* accepted on tuple index fields as it was \ - incorrectly accepted on stable for a few releases", - text, - )); - err.help( - "on proc macros, you'll want to use `syn::Index::from` or \ - `proc_macro::Literal::*_unsuffixed` for code that will desugar \ - to tuple field access", - ); - err.note( - "for more context, see https://github.com/rust-lang/rust/issues/60210", - ); - err - } else { - self.struct_span_err(sp, &format!("suffixes on {} are invalid", kind)) - }; - err.span_label(sp, format!("invalid suffix `{}`", text)); - err.emit(); - } - } + parse::expect_no_suffix(sp, &self.sess.span_diagnostic, kind, suffix) } /// Attempts to consume a `<`. If `<<` is seen, replaces it with a single @@ -1452,9 +1416,6 @@ impl<'a> Parser<'a> { crate fn struct_span_err>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> { self.sess.span_diagnostic.struct_span_err(sp, m) } - fn struct_span_warn>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> { - self.sess.span_diagnostic.struct_span_warn(sp, m) - } crate fn span_bug>(&self, sp: S, m: &str) -> ! { self.sess.span_diagnostic.span_bug(sp, m) } @@ -2069,85 +2030,45 @@ impl<'a> Parser<'a> { } } - /// Matches `token_lit = LIT_INTEGER | ...`. - fn parse_lit_token(&mut self) -> PResult<'a, (LitKind, token::Lit, Option)> { - let out = match self.token { - token::Interpolated(ref nt) => match **nt { - token::NtExpr(ref v) | token::NtLiteral(ref v) => match v.node { - ExprKind::Lit(ref lit) => { (lit.node.clone(), lit.token, lit.suffix) } - _ => { return self.unexpected_last(&self.token); } - }, - _ => { return self.unexpected_last(&self.token); } - }, - token::Literal(lit, suf) => { - let diag = Some((self.span, &self.sess.span_diagnostic)); - let (suffix_illegal, result) = parse::lit_token(lit, suf, diag); - - if suffix_illegal { - let sp = self.span; - self.expect_no_suffix(sp, &format!("a {}", lit.literal_name()), suf) + /// Matches `lit = true | false | token_lit`. + crate fn parse_lit(&mut self) -> PResult<'a, Lit> { + let diag = Some((self.span, &self.sess.span_diagnostic)); + if let Some(lit) = Lit::from_token(&self.token, self.span, diag) { + self.bump(); + return Ok(lit); + } else if self.token == token::Dot { + // Recover `.4` as `0.4`. + let recovered = self.look_ahead(1, |t| { + if let token::Literal(token::Integer(val), suf) = *t { + let next_span = self.look_ahead_span(1); + if self.span.hi() == next_span.lo() { + let sym = String::from("0.") + &val.as_str(); + let token = token::Literal(token::Float(Symbol::intern(&sym)), suf); + return Some((token, self.span.to(next_span))); + } } - - (result.unwrap(), lit, suf) - } - token::Dot if self.look_ahead(1, |t| match t { - token::Literal(token::Lit::Integer(_) , _) => true, - _ => false, - }) => { // recover from `let x = .4;` - let lo = self.span; - self.bump(); - if let token::Literal( - token::Lit::Integer(val), - suffix, - ) = self.token { - let float_suffix = suffix.and_then(|s| { - let s = s.as_str(); - if s == "f32" { - Some("f32") - } else if s == "f64" { - Some("f64") - } else { - None - } - }).unwrap_or(""); - self.bump(); - let sp = lo.to(self.prev_span); - let mut err = self.diagnostic() - .struct_span_err(sp, "float literals must have an integer part"); - err.span_suggestion( - sp, + None + }); + if let Some((token, span)) = recovered { + self.diagnostic() + .struct_span_err(span, "float literals must have an integer part") + .span_suggestion( + span, "must have an integer part", - format!("0.{}{}", val, float_suffix), + pprust::token_to_string(&token), Applicability::MachineApplicable, - ); - err.emit(); - return Ok((match float_suffix { - "f32" => ast::LitKind::Float(val, ast::FloatTy::F32), - "f64" => ast::LitKind::Float(val, ast::FloatTy::F64), - _ => ast::LitKind::FloatUnsuffixed(val), - }, token::Float(val), suffix)); - } else { - unreachable!(); - }; + ) + .emit(); + let diag = Some((span, &self.sess.span_diagnostic)); + if let Some(lit) = Lit::from_token(&token, span, diag) { + self.bump(); + self.bump(); + return Ok(lit); + } } - _ => { return self.unexpected_last(&self.token); } - }; - - self.bump(); - Ok(out) - } + } - /// Matches `lit = true | false | token_lit`. - crate fn parse_lit(&mut self) -> PResult<'a, Lit> { - let lo = self.span; - let (node, token, suffix) = if self.eat_keyword(keywords::True) { - (LitKind::Bool(true), token::Bool(keywords::True.name()), None) - } else if self.eat_keyword(keywords::False) { - (LitKind::Bool(false), token::Bool(keywords::False.name()), None) - } else { - self.parse_lit_token()? - }; - Ok(Lit { node, token, suffix, span: lo.to(self.prev_span) }) + self.unexpected_last(&self.token) } /// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`). diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 48a949257ffb3..0c2ea70aa20c8 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -90,6 +90,13 @@ impl Lit { } } + crate fn may_have_suffix(&self) -> bool { + match *self { + Integer(..) | Float(..) => true, + _ => false, + } + } + // See comments in `Nonterminal::to_tokenstream` for why we care about // *probably* equal here rather than actual equality fn probably_equal_for_proc_macro(&self, other: &Lit) -> bool { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index fa16a2b200ff3..0e8ac6c35b9bf 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -162,7 +162,7 @@ fn binop_to_string(op: BinOpToken) -> &'static str { } } -fn literal_to_string(lit: token::Lit, suffix: Option) -> String { +pub fn literal_to_string(lit: token::Lit, suffix: Option) -> String { let mut out = match lit { token::Byte(b) => format!("b'{}'", b), token::Char(c) => format!("'{}'", c), diff --git a/src/test/ui/malformed/malformed-interpolated.rs b/src/test/ui/malformed/malformed-interpolated.rs index e452435968bac..7c4ca3c017e7b 100644 --- a/src/test/ui/malformed/malformed-interpolated.rs +++ b/src/test/ui/malformed/malformed-interpolated.rs @@ -2,8 +2,7 @@ macro_rules! check { ($expr: expr) => ( - #[my_attr = $expr] //~ ERROR suffixed literals are not allowed in attributes - //~| ERROR unexpected token: `-0` + #[my_attr = $expr] //~ ERROR unexpected token: `-0` //~| ERROR unexpected token: `0 + 0` use main as _; ); @@ -11,7 +10,7 @@ macro_rules! check { check!("0"); // OK check!(0); // OK -check!(0u8); // ERROR, see above +check!(0u8); //~ ERROR suffixed literals are not allowed in attributes check!(-0); // ERROR, see above check!(0 + 0); // ERROR, see above diff --git a/src/test/ui/malformed/malformed-interpolated.stderr b/src/test/ui/malformed/malformed-interpolated.stderr index efeede0148dac..bc2146e409d47 100644 --- a/src/test/ui/malformed/malformed-interpolated.stderr +++ b/src/test/ui/malformed/malformed-interpolated.stderr @@ -1,11 +1,8 @@ error: suffixed literals are not allowed in attributes - --> $DIR/malformed-interpolated.rs:5:21 + --> $DIR/malformed-interpolated.rs:13:8 | -LL | #[my_attr = $expr] - | ^^^^^ -... -LL | check!(0u8); // ERROR, see above - | ------------ in this macro invocation +LL | check!(0u8); + | ^^^ | = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.). From 3f064cae3d9d0d33951a44c30d83696563244572 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 11 May 2019 02:31:34 +0300 Subject: [PATCH 188/212] Move literal parsing code into a separate file Remove some dead code --- src/libsyntax/attr/mod.rs | 99 ---- src/libsyntax/parse/classify.rs | 13 - src/libsyntax/parse/lexer/mod.rs | 19 +- src/libsyntax/parse/literal.rs | 487 ++++++++++++++++++ src/libsyntax/parse/mod.rs | 352 +------------ src/libsyntax/parse/parser.rs | 56 +- src/test/ui/attr-eq-token-tree.stderr | 4 +- ...sive_range_pattern_syntax_collision.stderr | 4 +- ...ive_range_pattern_syntax_collision2.stderr | 4 +- src/test/ui/macros/macro-attribute.stderr | 4 +- .../malformed/malformed-interpolated.stderr | 8 +- src/test/ui/parser/attr-bad-meta-2.stderr | 4 +- src/test/ui/parser/pat-tuple-5.stderr | 4 +- 13 files changed, 521 insertions(+), 537 deletions(-) create mode 100644 src/libsyntax/parse/literal.rs diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index c122e1994e749..07e4bbf78ffdf 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -27,11 +27,9 @@ use crate::ThinVec; use crate::tokenstream::{TokenStream, TokenTree, DelimSpan}; use crate::GLOBALS; -use errors::Handler; use log::debug; use syntax_pos::{FileName, Span}; -use std::ascii; use std::iter; use std::ops::DerefMut; @@ -620,103 +618,6 @@ impl NestedMetaItem { } } -impl Lit { - crate fn tokens(&self) -> TokenStream { - let token = match self.token { - token::Bool(symbol) => Token::Ident(Ident::with_empty_ctxt(symbol), false), - token => Token::Literal(token, self.suffix), - }; - TokenTree::Token(self.span, token).into() - } -} - -impl LitKind { - /// Attempts to recover a token from semantic literal. - /// This function is used when the original token doesn't exist (e.g. the literal is created - /// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing). - pub fn to_lit_token(&self) -> (token::Lit, Option) { - match *self { - LitKind::Str(string, ast::StrStyle::Cooked) => { - let escaped = string.as_str().escape_default().to_string(); - (token::Lit::Str_(Symbol::intern(&escaped)), None) - } - LitKind::Str(string, ast::StrStyle::Raw(n)) => { - (token::Lit::StrRaw(string, n), None) - } - LitKind::ByteStr(ref bytes) => { - let string = bytes.iter().cloned().flat_map(ascii::escape_default) - .map(Into::::into).collect::(); - (token::Lit::ByteStr(Symbol::intern(&string)), None) - } - LitKind::Byte(byte) => { - let string: String = ascii::escape_default(byte).map(Into::::into).collect(); - (token::Lit::Byte(Symbol::intern(&string)), None) - } - LitKind::Char(ch) => { - let string: String = ch.escape_default().map(Into::::into).collect(); - (token::Lit::Char(Symbol::intern(&string)), None) - } - LitKind::Int(n, ty) => { - let suffix = match ty { - ast::LitIntType::Unsigned(ty) => Some(Symbol::intern(ty.ty_to_string())), - ast::LitIntType::Signed(ty) => Some(Symbol::intern(ty.ty_to_string())), - ast::LitIntType::Unsuffixed => None, - }; - (token::Lit::Integer(Symbol::intern(&n.to_string())), suffix) - } - LitKind::Float(symbol, ty) => { - (token::Lit::Float(symbol), Some(Symbol::intern(ty.ty_to_string()))) - } - LitKind::FloatUnsuffixed(symbol) => (token::Lit::Float(symbol), None), - LitKind::Bool(value) => { - let kw = if value { keywords::True } else { keywords::False }; - (token::Lit::Bool(kw.name()), None) - } - LitKind::Err(val) => (token::Lit::Err(val), None), - } - } -} - -impl Lit { - /// Converts literal token with a suffix into an AST literal. - /// Works speculatively and may return `None` is diagnostic handler is not passed. - /// If diagnostic handler is passed, may return `Some`, - /// possibly after reporting non-fatal errors and recovery, or `None` for irrecoverable errors. - crate fn from_token( - token: &token::Token, - span: Span, - diag: Option<(Span, &Handler)>, - ) -> Option { - let (token, suffix) = match *token { - token::Ident(ident, false) if ident.name == keywords::True.name() || - ident.name == keywords::False.name() => - (token::Bool(ident.name), None), - token::Literal(token, suffix) => - (token, suffix), - token::Interpolated(ref nt) => { - if let token::NtExpr(expr) | token::NtLiteral(expr) = &**nt { - if let ast::ExprKind::Lit(lit) = &expr.node { - return Some(lit.clone()); - } - } - return None; - } - _ => return None, - }; - - let node = LitKind::from_lit_token(token, suffix, diag)?; - Some(Lit { node, token, suffix, span }) - } - - /// Attempts to recover an AST literal from semantic literal. - /// This function is used when the original token doesn't exist (e.g. the literal is created - /// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing). - pub fn from_lit_kind(node: LitKind, span: Span) -> Lit { - let (token, suffix) = node.to_lit_token(); - Lit { node, token, suffix, span } - } -} - pub trait HasAttrs: Sized { fn attrs(&self) -> &[ast::Attribute]; fn visit_attrs)>(&mut self, f: F); diff --git a/src/libsyntax/parse/classify.rs b/src/libsyntax/parse/classify.rs index b4103440e3577..dfd6f451c28d7 100644 --- a/src/libsyntax/parse/classify.rs +++ b/src/libsyntax/parse/classify.rs @@ -25,16 +25,3 @@ pub fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool { _ => true, } } - -/// this statement requires a semicolon after it. -/// note that in one case (`stmt_semi`), we've already -/// seen the semicolon, and thus don't need another. -pub fn stmt_ends_with_semi(stmt: &ast::StmtKind) -> bool { - match *stmt { - ast::StmtKind::Local(_) => true, - ast::StmtKind::Expr(ref e) => expr_requires_semi_to_be_stmt(e), - ast::StmtKind::Item(_) | - ast::StmtKind::Semi(..) | - ast::StmtKind::Mac(..) => false, - } -} diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 2882acb0e780c..e76605cde32ab 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -262,18 +262,6 @@ impl<'a> StringReader<'a> { } } - pub fn new(sess: &'a ParseSess, - source_file: Lrc, - override_span: Option) -> Self { - let mut sr = StringReader::new_raw(sess, source_file, override_span); - if sr.advance_token().is_err() { - sr.emit_fatal_errors(); - FatalError.raise(); - } - - sr - } - pub fn new_or_buffered_errs(sess: &'a ParseSess, source_file: Lrc, override_span: Option) -> Result> { @@ -1627,7 +1615,12 @@ mod tests { teststr: String) -> StringReader<'a> { let sf = sm.new_source_file(PathBuf::from(teststr.clone()).into(), teststr); - StringReader::new(sess, sf, None) + let mut sr = StringReader::new_raw(sess, sf, None); + if sr.advance_token().is_err() { + sr.emit_fatal_errors(); + FatalError.raise(); + } + sr } #[test] diff --git a/src/libsyntax/parse/literal.rs b/src/libsyntax/parse/literal.rs new file mode 100644 index 0000000000000..2c7ba13fbef82 --- /dev/null +++ b/src/libsyntax/parse/literal.rs @@ -0,0 +1,487 @@ +//! Code related to parsing literals. + +use crate::ast::{self, Ident, Lit, LitKind}; +use crate::parse::parser::Parser; +use crate::parse::PResult; +use crate::parse::token::{self, Token}; +use crate::parse::unescape::{unescape_str, unescape_char, unescape_byte_str, unescape_byte}; +use crate::print::pprust; +use crate::symbol::{keywords, Symbol}; +use crate::tokenstream::{TokenStream, TokenTree}; + +use errors::{Applicability, Handler}; +use log::debug; +use rustc_data_structures::sync::Lrc; +use syntax_pos::Span; + +use std::ascii; + +macro_rules! err { + ($opt_diag:expr, |$span:ident, $diag:ident| $($body:tt)*) => { + match $opt_diag { + Some(($span, $diag)) => { $($body)* } + None => return None, + } + } +} + +impl LitKind { + /// Converts literal token with a suffix into a semantic literal. + /// Works speculatively and may return `None` is diagnostic handler is not passed. + /// If diagnostic handler is passed, always returns `Some`, + /// possibly after reporting non-fatal errors and recovery. + fn from_lit_token( + lit: token::Lit, + suf: Option, + diag: Option<(Span, &Handler)> + ) -> Option { + if suf.is_some() && !lit.may_have_suffix() { + err!(diag, |span, diag| { + expect_no_suffix(span, diag, &format!("a {}", lit.literal_name()), suf) + }); + } + + Some(match lit { + token::Bool(i) => { + assert!(i == keywords::True.name() || i == keywords::False.name()); + LitKind::Bool(i == keywords::True.name()) + } + token::Byte(i) => { + match unescape_byte(&i.as_str()) { + Ok(c) => LitKind::Byte(c), + Err(_) => LitKind::Err(i), + } + }, + token::Char(i) => { + match unescape_char(&i.as_str()) { + Ok(c) => LitKind::Char(c), + Err(_) => LitKind::Err(i), + } + }, + token::Err(i) => LitKind::Err(i), + + // There are some valid suffixes for integer and float literals, + // so all the handling is done internally. + token::Integer(s) => return integer_lit(&s.as_str(), suf, diag), + token::Float(s) => return float_lit(&s.as_str(), suf, diag), + + token::Str_(mut sym) => { + // If there are no characters requiring special treatment we can + // reuse the symbol from the Token. Otherwise, we must generate a + // new symbol because the string in the LitKind is different to the + // string in the Token. + let mut has_error = false; + let s = &sym.as_str(); + if s.as_bytes().iter().any(|&c| c == b'\\' || c == b'\r') { + let mut buf = String::with_capacity(s.len()); + unescape_str(s, &mut |_, unescaped_char| { + match unescaped_char { + Ok(c) => buf.push(c), + Err(_) => has_error = true, + } + }); + if has_error { + return Some(LitKind::Err(sym)); + } + sym = Symbol::intern(&buf) + } + + LitKind::Str(sym, ast::StrStyle::Cooked) + } + token::StrRaw(mut sym, n) => { + // Ditto. + let s = &sym.as_str(); + if s.contains('\r') { + sym = Symbol::intern(&raw_str_lit(s)); + } + LitKind::Str(sym, ast::StrStyle::Raw(n)) + } + token::ByteStr(i) => { + let s = &i.as_str(); + let mut buf = Vec::with_capacity(s.len()); + let mut has_error = false; + unescape_byte_str(s, &mut |_, unescaped_byte| { + match unescaped_byte { + Ok(c) => buf.push(c), + Err(_) => has_error = true, + } + }); + if has_error { + return Some(LitKind::Err(i)); + } + buf.shrink_to_fit(); + LitKind::ByteStr(Lrc::new(buf)) + } + token::ByteStrRaw(i, _) => { + LitKind::ByteStr(Lrc::new(i.to_string().into_bytes())) + } + }) + } + + /// Attempts to recover a token from semantic literal. + /// This function is used when the original token doesn't exist (e.g. the literal is created + /// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing). + pub fn to_lit_token(&self) -> (token::Lit, Option) { + match *self { + LitKind::Str(string, ast::StrStyle::Cooked) => { + let escaped = string.as_str().escape_default().to_string(); + (token::Lit::Str_(Symbol::intern(&escaped)), None) + } + LitKind::Str(string, ast::StrStyle::Raw(n)) => { + (token::Lit::StrRaw(string, n), None) + } + LitKind::ByteStr(ref bytes) => { + let string = bytes.iter().cloned().flat_map(ascii::escape_default) + .map(Into::::into).collect::(); + (token::Lit::ByteStr(Symbol::intern(&string)), None) + } + LitKind::Byte(byte) => { + let string: String = ascii::escape_default(byte).map(Into::::into).collect(); + (token::Lit::Byte(Symbol::intern(&string)), None) + } + LitKind::Char(ch) => { + let string: String = ch.escape_default().map(Into::::into).collect(); + (token::Lit::Char(Symbol::intern(&string)), None) + } + LitKind::Int(n, ty) => { + let suffix = match ty { + ast::LitIntType::Unsigned(ty) => Some(Symbol::intern(ty.ty_to_string())), + ast::LitIntType::Signed(ty) => Some(Symbol::intern(ty.ty_to_string())), + ast::LitIntType::Unsuffixed => None, + }; + (token::Lit::Integer(Symbol::intern(&n.to_string())), suffix) + } + LitKind::Float(symbol, ty) => { + (token::Lit::Float(symbol), Some(Symbol::intern(ty.ty_to_string()))) + } + LitKind::FloatUnsuffixed(symbol) => (token::Lit::Float(symbol), None), + LitKind::Bool(value) => { + let kw = if value { keywords::True } else { keywords::False }; + (token::Lit::Bool(kw.name()), None) + } + LitKind::Err(val) => (token::Lit::Err(val), None), + } + } +} + +impl Lit { + /// Converts literal token with a suffix into an AST literal. + /// Works speculatively and may return `None` is diagnostic handler is not passed. + /// If diagnostic handler is passed, may return `Some`, + /// possibly after reporting non-fatal errors and recovery, or `None` for irrecoverable errors. + crate fn from_token( + token: &token::Token, + span: Span, + diag: Option<(Span, &Handler)>, + ) -> Option { + let (token, suffix) = match *token { + token::Ident(ident, false) if ident.name == keywords::True.name() || + ident.name == keywords::False.name() => + (token::Bool(ident.name), None), + token::Literal(token, suffix) => + (token, suffix), + token::Interpolated(ref nt) => { + if let token::NtExpr(expr) | token::NtLiteral(expr) = &**nt { + if let ast::ExprKind::Lit(lit) = &expr.node { + return Some(lit.clone()); + } + } + return None; + } + _ => return None, + }; + + let node = LitKind::from_lit_token(token, suffix, diag)?; + Some(Lit { node, token, suffix, span }) + } + + /// Attempts to recover an AST literal from semantic literal. + /// This function is used when the original token doesn't exist (e.g. the literal is created + /// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing). + pub fn from_lit_kind(node: LitKind, span: Span) -> Lit { + let (token, suffix) = node.to_lit_token(); + Lit { node, token, suffix, span } + } + + /// Losslessly convert an AST literal into a token stream. + crate fn tokens(&self) -> TokenStream { + let token = match self.token { + token::Bool(symbol) => Token::Ident(Ident::with_empty_ctxt(symbol), false), + token => Token::Literal(token, self.suffix), + }; + TokenTree::Token(self.span, token).into() + } +} + +impl<'a> Parser<'a> { + /// Matches `lit = true | false | token_lit`. + crate fn parse_lit(&mut self) -> PResult<'a, Lit> { + let diag = Some((self.span, &self.sess.span_diagnostic)); + if let Some(lit) = Lit::from_token(&self.token, self.span, diag) { + self.bump(); + return Ok(lit); + } else if self.token == token::Dot { + // Recover `.4` as `0.4`. + let recovered = self.look_ahead(1, |t| { + if let token::Literal(token::Integer(val), suf) = *t { + let next_span = self.look_ahead_span(1); + if self.span.hi() == next_span.lo() { + let sym = String::from("0.") + &val.as_str(); + let token = token::Literal(token::Float(Symbol::intern(&sym)), suf); + return Some((token, self.span.to(next_span))); + } + } + None + }); + if let Some((token, span)) = recovered { + self.diagnostic() + .struct_span_err(span, "float literals must have an integer part") + .span_suggestion( + span, + "must have an integer part", + pprust::token_to_string(&token), + Applicability::MachineApplicable, + ) + .emit(); + let diag = Some((span, &self.sess.span_diagnostic)); + if let Some(lit) = Lit::from_token(&token, span, diag) { + self.bump(); + self.bump(); + return Ok(lit); + } + } + } + + Err(self.span_fatal(self.span, &format!("unexpected token: {}", self.this_token_descr()))) + } +} + +crate fn expect_no_suffix(sp: Span, diag: &Handler, kind: &str, suffix: Option) { + match suffix { + None => {/* everything ok */} + Some(suf) => { + let text = suf.as_str(); + if text.is_empty() { + diag.span_bug(sp, "found empty literal suffix in Some") + } + let mut err = if kind == "a tuple index" && + ["i32", "u32", "isize", "usize"].contains(&text.to_string().as_str()) + { + // #59553: warn instead of reject out of hand to allow the fix to percolate + // through the ecosystem when people fix their macros + let mut err = diag.struct_span_warn( + sp, + &format!("suffixes on {} are invalid", kind), + ); + err.note(&format!( + "`{}` is *temporarily* accepted on tuple index fields as it was \ + incorrectly accepted on stable for a few releases", + text, + )); + err.help( + "on proc macros, you'll want to use `syn::Index::from` or \ + `proc_macro::Literal::*_unsuffixed` for code that will desugar \ + to tuple field access", + ); + err.note( + "for more context, see https://github.com/rust-lang/rust/issues/60210", + ); + err + } else { + diag.struct_span_err(sp, &format!("suffixes on {} are invalid", kind)) + }; + err.span_label(sp, format!("invalid suffix `{}`", text)); + err.emit(); + } + } +} + +/// Parses a string representing a raw string literal into its final form. The +/// only operation this does is convert embedded CRLF into a single LF. +fn raw_str_lit(lit: &str) -> String { + debug!("raw_str_lit: given {}", lit.escape_default()); + let mut res = String::with_capacity(lit.len()); + + let mut chars = lit.chars().peekable(); + while let Some(c) = chars.next() { + if c == '\r' { + if *chars.peek().unwrap() != '\n' { + panic!("lexer accepted bare CR"); + } + chars.next(); + res.push('\n'); + } else { + res.push(c); + } + } + + res.shrink_to_fit(); + res +} + +// check if `s` looks like i32 or u1234 etc. +fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool { + s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit()) +} + +fn filtered_float_lit(data: Symbol, suffix: Option, diag: Option<(Span, &Handler)>) + -> Option { + debug!("filtered_float_lit: {}, {:?}", data, suffix); + let suffix = match suffix { + Some(suffix) => suffix, + None => return Some(LitKind::FloatUnsuffixed(data)), + }; + + Some(match &*suffix.as_str() { + "f32" => LitKind::Float(data, ast::FloatTy::F32), + "f64" => LitKind::Float(data, ast::FloatTy::F64), + suf => { + err!(diag, |span, diag| { + if suf.len() >= 2 && looks_like_width_suffix(&['f'], suf) { + // if it looks like a width, lets try to be helpful. + let msg = format!("invalid width `{}` for float literal", &suf[1..]); + diag.struct_span_err(span, &msg).help("valid widths are 32 and 64").emit() + } else { + let msg = format!("invalid suffix `{}` for float literal", suf); + diag.struct_span_err(span, &msg) + .span_label(span, format!("invalid suffix `{}`", suf)) + .help("valid suffixes are `f32` and `f64`") + .emit(); + } + }); + + LitKind::FloatUnsuffixed(data) + } + }) +} +fn float_lit(s: &str, suffix: Option, diag: Option<(Span, &Handler)>) + -> Option { + debug!("float_lit: {:?}, {:?}", s, suffix); + // FIXME #2252: bounds checking float literals is deferred until trans + + // Strip underscores without allocating a new String unless necessary. + let s2; + let s = if s.chars().any(|c| c == '_') { + s2 = s.chars().filter(|&c| c != '_').collect::(); + &s2 + } else { + s + }; + + filtered_float_lit(Symbol::intern(s), suffix, diag) +} + +fn integer_lit(s: &str, suffix: Option, diag: Option<(Span, &Handler)>) + -> Option { + // s can only be ascii, byte indexing is fine + + // Strip underscores without allocating a new String unless necessary. + let s2; + let mut s = if s.chars().any(|c| c == '_') { + s2 = s.chars().filter(|&c| c != '_').collect::(); + &s2 + } else { + s + }; + + debug!("integer_lit: {}, {:?}", s, suffix); + + let mut base = 10; + let orig = s; + let mut ty = ast::LitIntType::Unsuffixed; + + if s.starts_with('0') && s.len() > 1 { + match s.as_bytes()[1] { + b'x' => base = 16, + b'o' => base = 8, + b'b' => base = 2, + _ => { } + } + } + + // 1f64 and 2f32 etc. are valid float literals. + if let Some(suf) = suffix { + if looks_like_width_suffix(&['f'], &suf.as_str()) { + let err = match base { + 16 => Some("hexadecimal float literal is not supported"), + 8 => Some("octal float literal is not supported"), + 2 => Some("binary float literal is not supported"), + _ => None, + }; + if let Some(err) = err { + err!(diag, |span, diag| { + diag.struct_span_err(span, err) + .span_label(span, "not supported") + .emit(); + }); + } + return filtered_float_lit(Symbol::intern(s), Some(suf), diag) + } + } + + if base != 10 { + s = &s[2..]; + } + + if let Some(suf) = suffix { + if suf.as_str().is_empty() { + err!(diag, |span, diag| diag.span_bug(span, "found empty literal suffix in Some")); + } + ty = match &*suf.as_str() { + "isize" => ast::LitIntType::Signed(ast::IntTy::Isize), + "i8" => ast::LitIntType::Signed(ast::IntTy::I8), + "i16" => ast::LitIntType::Signed(ast::IntTy::I16), + "i32" => ast::LitIntType::Signed(ast::IntTy::I32), + "i64" => ast::LitIntType::Signed(ast::IntTy::I64), + "i128" => ast::LitIntType::Signed(ast::IntTy::I128), + "usize" => ast::LitIntType::Unsigned(ast::UintTy::Usize), + "u8" => ast::LitIntType::Unsigned(ast::UintTy::U8), + "u16" => ast::LitIntType::Unsigned(ast::UintTy::U16), + "u32" => ast::LitIntType::Unsigned(ast::UintTy::U32), + "u64" => ast::LitIntType::Unsigned(ast::UintTy::U64), + "u128" => ast::LitIntType::Unsigned(ast::UintTy::U128), + suf => { + // i and u look like widths, so lets + // give an error message along those lines + err!(diag, |span, diag| { + if looks_like_width_suffix(&['i', 'u'], suf) { + let msg = format!("invalid width `{}` for integer literal", &suf[1..]); + diag.struct_span_err(span, &msg) + .help("valid widths are 8, 16, 32, 64 and 128") + .emit(); + } else { + let msg = format!("invalid suffix `{}` for numeric literal", suf); + diag.struct_span_err(span, &msg) + .span_label(span, format!("invalid suffix `{}`", suf)) + .help("the suffix must be one of the integral types \ + (`u32`, `isize`, etc)") + .emit(); + } + }); + + ty + } + } + } + + debug!("integer_lit: the type is {:?}, base {:?}, the new string is {:?}, the original \ + string was {:?}, the original suffix was {:?}", ty, base, s, orig, suffix); + + Some(match u128::from_str_radix(s, base) { + Ok(r) => LitKind::Int(r, ty), + Err(_) => { + // small bases are lexed as if they were base 10, e.g, the string + // might be `0b10201`. This will cause the conversion above to fail, + // but these cases have errors in the lexer: we don't want to emit + // two errors, and we especially don't want to emit this error since + // it isn't necessarily true. + let already_errored = base < 10 && + s.chars().any(|c| c.to_digit(10).map_or(false, |d| d >= base)); + + if !already_errored { + err!(diag, |span, diag| diag.span_err(span, "int literal is too large")); + } + LitKind::Int(0, ty) + } + }) +} diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 868b344c06584..526143b28755f 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -1,11 +1,10 @@ //! The main parser interface. -use crate::ast::{self, CrateConfig, LitKind, NodeId}; +use crate::ast::{self, CrateConfig, NodeId}; use crate::early_buffered_lints::{BufferedEarlyLint, BufferedEarlyLintId}; use crate::source_map::{SourceMap, FilePathMapping}; use crate::feature_gate::UnstableFeatures; use crate::parse::parser::Parser; -use crate::symbol::{keywords, Symbol}; use crate::syntax::parse::parser::emit_unclosed_delims; use crate::tokenstream::{TokenStream, TokenTree}; use crate::diagnostics::plugin::ErrorMap; @@ -14,7 +13,6 @@ use crate::print::pprust::token_to_string; use errors::{Applicability, FatalError, Level, Handler, ColorConfig, Diagnostic, DiagnosticBuilder}; use rustc_data_structures::sync::{Lrc, Lock}; use syntax_pos::{Span, SourceFile, FileName, MultiSpan}; -use log::debug; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use std::borrow::Cow; @@ -25,18 +23,15 @@ pub type PResult<'a, T> = Result>; #[macro_use] pub mod parser; - +pub mod attr; pub mod lexer; pub mod token; -pub mod attr; -pub mod diagnostics; - -pub mod classify; - -pub(crate) mod unescape; -use unescape::{unescape_str, unescape_char, unescape_byte_str, unescape_byte}; -pub(crate) mod unescape_error_reporting; +crate mod classify; +crate mod diagnostics; +crate mod literal; +crate mod unescape; +crate mod unescape_error_reporting; /// Info about a parsing session. pub struct ParseSess { @@ -334,339 +329,6 @@ pub fn stream_to_parser(sess: &ParseSess, stream: TokenStream) -> Parser<'_> { Parser::new(sess, stream, None, true, false) } -/// Parses a string representing a raw string literal into its final form. The -/// only operation this does is convert embedded CRLF into a single LF. -fn raw_str_lit(lit: &str) -> String { - debug!("raw_str_lit: given {}", lit.escape_default()); - let mut res = String::with_capacity(lit.len()); - - let mut chars = lit.chars().peekable(); - while let Some(c) = chars.next() { - if c == '\r' { - if *chars.peek().unwrap() != '\n' { - panic!("lexer accepted bare CR"); - } - chars.next(); - res.push('\n'); - } else { - res.push(c); - } - } - - res.shrink_to_fit(); - res -} - -// check if `s` looks like i32 or u1234 etc. -fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool { - s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit()) -} - -macro_rules! err { - ($opt_diag:expr, |$span:ident, $diag:ident| $($body:tt)*) => { - match $opt_diag { - Some(($span, $diag)) => { $($body)* } - None => return None, - } - } -} - -crate fn expect_no_suffix(sp: Span, diag: &Handler, kind: &str, suffix: Option) { - match suffix { - None => {/* everything ok */} - Some(suf) => { - let text = suf.as_str(); - if text.is_empty() { - diag.span_bug(sp, "found empty literal suffix in Some") - } - let mut err = if kind == "a tuple index" && - ["i32", "u32", "isize", "usize"].contains(&text.to_string().as_str()) - { - // #59553: warn instead of reject out of hand to allow the fix to percolate - // through the ecosystem when people fix their macros - let mut err = diag.struct_span_warn( - sp, - &format!("suffixes on {} are invalid", kind), - ); - err.note(&format!( - "`{}` is *temporarily* accepted on tuple index fields as it was \ - incorrectly accepted on stable for a few releases", - text, - )); - err.help( - "on proc macros, you'll want to use `syn::Index::from` or \ - `proc_macro::Literal::*_unsuffixed` for code that will desugar \ - to tuple field access", - ); - err.note( - "for more context, see https://github.com/rust-lang/rust/issues/60210", - ); - err - } else { - diag.struct_span_err(sp, &format!("suffixes on {} are invalid", kind)) - }; - err.span_label(sp, format!("invalid suffix `{}`", text)); - err.emit(); - } - } -} - -impl LitKind { - /// Converts literal token with a suffix into a semantic literal. - /// Works speculatively and may return `None` is diagnostic handler is not passed. - /// If diagnostic handler is passed, always returns `Some`, - /// possibly after reporting non-fatal errors and recovery. - crate fn from_lit_token( - lit: token::Lit, - suf: Option, - diag: Option<(Span, &Handler)> - ) -> Option { - if suf.is_some() && !lit.may_have_suffix() { - err!(diag, |span, diag| { - expect_no_suffix(span, diag, &format!("a {}", lit.literal_name()), suf) - }); - } - - Some(match lit { - token::Bool(i) => { - assert!(i == keywords::True.name() || i == keywords::False.name()); - LitKind::Bool(i == keywords::True.name()) - } - token::Byte(i) => { - match unescape_byte(&i.as_str()) { - Ok(c) => LitKind::Byte(c), - Err(_) => LitKind::Err(i), - } - }, - token::Char(i) => { - match unescape_char(&i.as_str()) { - Ok(c) => LitKind::Char(c), - Err(_) => LitKind::Err(i), - } - }, - token::Err(i) => LitKind::Err(i), - - // There are some valid suffixes for integer and float literals, - // so all the handling is done internally. - token::Integer(s) => return integer_lit(&s.as_str(), suf, diag), - token::Float(s) => return float_lit(&s.as_str(), suf, diag), - - token::Str_(mut sym) => { - // If there are no characters requiring special treatment we can - // reuse the symbol from the Token. Otherwise, we must generate a - // new symbol because the string in the LitKind is different to the - // string in the Token. - let mut has_error = false; - let s = &sym.as_str(); - if s.as_bytes().iter().any(|&c| c == b'\\' || c == b'\r') { - let mut buf = String::with_capacity(s.len()); - unescape_str(s, &mut |_, unescaped_char| { - match unescaped_char { - Ok(c) => buf.push(c), - Err(_) => has_error = true, - } - }); - if has_error { - return Some(LitKind::Err(sym)); - } - sym = Symbol::intern(&buf) - } - - LitKind::Str(sym, ast::StrStyle::Cooked) - } - token::StrRaw(mut sym, n) => { - // Ditto. - let s = &sym.as_str(); - if s.contains('\r') { - sym = Symbol::intern(&raw_str_lit(s)); - } - LitKind::Str(sym, ast::StrStyle::Raw(n)) - } - token::ByteStr(i) => { - let s = &i.as_str(); - let mut buf = Vec::with_capacity(s.len()); - let mut has_error = false; - unescape_byte_str(s, &mut |_, unescaped_byte| { - match unescaped_byte { - Ok(c) => buf.push(c), - Err(_) => has_error = true, - } - }); - if has_error { - return Some(LitKind::Err(i)); - } - buf.shrink_to_fit(); - LitKind::ByteStr(Lrc::new(buf)) - } - token::ByteStrRaw(i, _) => { - LitKind::ByteStr(Lrc::new(i.to_string().into_bytes())) - } - }) - } -} - -fn filtered_float_lit(data: Symbol, suffix: Option, diag: Option<(Span, &Handler)>) - -> Option { - debug!("filtered_float_lit: {}, {:?}", data, suffix); - let suffix = match suffix { - Some(suffix) => suffix, - None => return Some(LitKind::FloatUnsuffixed(data)), - }; - - Some(match &*suffix.as_str() { - "f32" => LitKind::Float(data, ast::FloatTy::F32), - "f64" => LitKind::Float(data, ast::FloatTy::F64), - suf => { - err!(diag, |span, diag| { - if suf.len() >= 2 && looks_like_width_suffix(&['f'], suf) { - // if it looks like a width, lets try to be helpful. - let msg = format!("invalid width `{}` for float literal", &suf[1..]); - diag.struct_span_err(span, &msg).help("valid widths are 32 and 64").emit() - } else { - let msg = format!("invalid suffix `{}` for float literal", suf); - diag.struct_span_err(span, &msg) - .span_label(span, format!("invalid suffix `{}`", suf)) - .help("valid suffixes are `f32` and `f64`") - .emit(); - } - }); - - LitKind::FloatUnsuffixed(data) - } - }) -} -fn float_lit(s: &str, suffix: Option, diag: Option<(Span, &Handler)>) - -> Option { - debug!("float_lit: {:?}, {:?}", s, suffix); - // FIXME #2252: bounds checking float literals is deferred until trans - - // Strip underscores without allocating a new String unless necessary. - let s2; - let s = if s.chars().any(|c| c == '_') { - s2 = s.chars().filter(|&c| c != '_').collect::(); - &s2 - } else { - s - }; - - filtered_float_lit(Symbol::intern(s), suffix, diag) -} - -fn integer_lit(s: &str, suffix: Option, diag: Option<(Span, &Handler)>) - -> Option { - // s can only be ascii, byte indexing is fine - - // Strip underscores without allocating a new String unless necessary. - let s2; - let mut s = if s.chars().any(|c| c == '_') { - s2 = s.chars().filter(|&c| c != '_').collect::(); - &s2 - } else { - s - }; - - debug!("integer_lit: {}, {:?}", s, suffix); - - let mut base = 10; - let orig = s; - let mut ty = ast::LitIntType::Unsuffixed; - - if s.starts_with('0') && s.len() > 1 { - match s.as_bytes()[1] { - b'x' => base = 16, - b'o' => base = 8, - b'b' => base = 2, - _ => { } - } - } - - // 1f64 and 2f32 etc. are valid float literals. - if let Some(suf) = suffix { - if looks_like_width_suffix(&['f'], &suf.as_str()) { - let err = match base { - 16 => Some("hexadecimal float literal is not supported"), - 8 => Some("octal float literal is not supported"), - 2 => Some("binary float literal is not supported"), - _ => None, - }; - if let Some(err) = err { - err!(diag, |span, diag| { - diag.struct_span_err(span, err) - .span_label(span, "not supported") - .emit(); - }); - } - return filtered_float_lit(Symbol::intern(s), Some(suf), diag) - } - } - - if base != 10 { - s = &s[2..]; - } - - if let Some(suf) = suffix { - if suf.as_str().is_empty() { - err!(diag, |span, diag| diag.span_bug(span, "found empty literal suffix in Some")); - } - ty = match &*suf.as_str() { - "isize" => ast::LitIntType::Signed(ast::IntTy::Isize), - "i8" => ast::LitIntType::Signed(ast::IntTy::I8), - "i16" => ast::LitIntType::Signed(ast::IntTy::I16), - "i32" => ast::LitIntType::Signed(ast::IntTy::I32), - "i64" => ast::LitIntType::Signed(ast::IntTy::I64), - "i128" => ast::LitIntType::Signed(ast::IntTy::I128), - "usize" => ast::LitIntType::Unsigned(ast::UintTy::Usize), - "u8" => ast::LitIntType::Unsigned(ast::UintTy::U8), - "u16" => ast::LitIntType::Unsigned(ast::UintTy::U16), - "u32" => ast::LitIntType::Unsigned(ast::UintTy::U32), - "u64" => ast::LitIntType::Unsigned(ast::UintTy::U64), - "u128" => ast::LitIntType::Unsigned(ast::UintTy::U128), - suf => { - // i and u look like widths, so lets - // give an error message along those lines - err!(diag, |span, diag| { - if looks_like_width_suffix(&['i', 'u'], suf) { - let msg = format!("invalid width `{}` for integer literal", &suf[1..]); - diag.struct_span_err(span, &msg) - .help("valid widths are 8, 16, 32, 64 and 128") - .emit(); - } else { - let msg = format!("invalid suffix `{}` for numeric literal", suf); - diag.struct_span_err(span, &msg) - .span_label(span, format!("invalid suffix `{}`", suf)) - .help("the suffix must be one of the integral types \ - (`u32`, `isize`, etc)") - .emit(); - } - }); - - ty - } - } - } - - debug!("integer_lit: the type is {:?}, base {:?}, the new string is {:?}, the original \ - string was {:?}, the original suffix was {:?}", ty, base, s, orig, suffix); - - Some(match u128::from_str_radix(s, base) { - Ok(r) => LitKind::Int(r, ty), - Err(_) => { - // small bases are lexed as if they were base 10, e.g, the string - // might be `0b10201`. This will cause the conversion above to fail, - // but these cases have errors in the lexer: we don't want to emit - // two errors, and we especially don't want to emit this error since - // it isn't necessarily true. - let already_errored = base < 10 && - s.chars().any(|c| c.to_digit(10).map_or(false, |d| d >= base)); - - if !already_errored { - err!(diag, |span, diag| diag.span_err(span, "int literal is too large")); - } - LitKind::Int(0, ty) - } - }) -} - /// A sequence separator. pub struct SeqSep { /// The seperator token. diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index b81f7be9c2c14..f95981680b940 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -15,7 +15,7 @@ use crate::ast::{ForeignItem, ForeignItemKind, FunctionRetTy}; use crate::ast::{GenericParam, GenericParamKind}; use crate::ast::GenericArg; use crate::ast::{Ident, ImplItem, IsAsync, IsAuto, Item, ItemKind}; -use crate::ast::{Label, Lifetime, Lit}; +use crate::ast::{Label, Lifetime}; use crate::ast::{Local, LocalSource}; use crate::ast::MacStmtStyle; use crate::ast::{Mac, Mac_, MacDelimiter}; @@ -35,7 +35,7 @@ use crate::ast::{RangeEnd, RangeSyntax}; use crate::{ast, attr}; use crate::ext::base::DummyResult; use crate::source_map::{self, SourceMap, Spanned, respan}; -use crate::parse::{self, SeqSep, classify, token}; +use crate::parse::{SeqSep, classify, literal, token}; use crate::parse::lexer::{TokenAndSpan, UnmatchedBrace}; use crate::parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration}; use crate::parse::token::DelimToken; @@ -613,7 +613,7 @@ impl<'a> Parser<'a> { }) } - fn this_token_descr(&self) -> String { + crate fn this_token_descr(&self) -> String { if let Some(prefix) = self.token_descr() { format!("{} `{}`", prefix, self.this_token_to_string()) } else { @@ -621,11 +621,6 @@ impl<'a> Parser<'a> { } } - fn unexpected_last(&self, t: &token::Token) -> PResult<'a, T> { - let token_str = pprust::token_to_string(t); - Err(self.span_fatal(self.prev_span, &format!("unexpected token: `{}`", token_str))) - } - crate fn unexpected(&mut self) -> PResult<'a, T> { match self.expect_one_of(&[], &[]) { Err(e) => Err(e), @@ -1109,7 +1104,7 @@ impl<'a> Parser<'a> { } fn expect_no_suffix(&self, sp: Span, kind: &str, suffix: Option) { - parse::expect_no_suffix(sp, &self.sess.span_diagnostic, kind, suffix) + literal::expect_no_suffix(sp, &self.sess.span_diagnostic, kind, suffix) } /// Attempts to consume a `<`. If `<<` is seen, replaces it with a single @@ -1387,7 +1382,7 @@ impl<'a> Parser<'a> { }) } - fn look_ahead_span(&self, dist: usize) -> Span { + crate fn look_ahead_span(&self, dist: usize) -> Span { if dist == 0 { return self.span } @@ -2030,47 +2025,6 @@ impl<'a> Parser<'a> { } } - /// Matches `lit = true | false | token_lit`. - crate fn parse_lit(&mut self) -> PResult<'a, Lit> { - let diag = Some((self.span, &self.sess.span_diagnostic)); - if let Some(lit) = Lit::from_token(&self.token, self.span, diag) { - self.bump(); - return Ok(lit); - } else if self.token == token::Dot { - // Recover `.4` as `0.4`. - let recovered = self.look_ahead(1, |t| { - if let token::Literal(token::Integer(val), suf) = *t { - let next_span = self.look_ahead_span(1); - if self.span.hi() == next_span.lo() { - let sym = String::from("0.") + &val.as_str(); - let token = token::Literal(token::Float(Symbol::intern(&sym)), suf); - return Some((token, self.span.to(next_span))); - } - } - None - }); - if let Some((token, span)) = recovered { - self.diagnostic() - .struct_span_err(span, "float literals must have an integer part") - .span_suggestion( - span, - "must have an integer part", - pprust::token_to_string(&token), - Applicability::MachineApplicable, - ) - .emit(); - let diag = Some((span, &self.sess.span_diagnostic)); - if let Some(lit) = Lit::from_token(&token, span, diag) { - self.bump(); - self.bump(); - return Ok(lit); - } - } - } - - self.unexpected_last(&self.token) - } - /// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`). crate fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P> { maybe_whole_expr!(self); diff --git a/src/test/ui/attr-eq-token-tree.stderr b/src/test/ui/attr-eq-token-tree.stderr index aae25b2721e4d..571779dfa1ae7 100644 --- a/src/test/ui/attr-eq-token-tree.stderr +++ b/src/test/ui/attr-eq-token-tree.stderr @@ -1,8 +1,8 @@ error: unexpected token: `!` - --> $DIR/attr-eq-token-tree.rs:3:11 + --> $DIR/attr-eq-token-tree.rs:3:13 | LL | #[my_attr = !] - | ^ + | ^ error: aborting due to previous error diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr index 03867a8e43b10..359725a41c105 100644 --- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr +++ b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr @@ -1,8 +1,8 @@ error: unexpected token: `,` - --> $DIR/exclusive_range_pattern_syntax_collision.rs:5:15 + --> $DIR/exclusive_range_pattern_syntax_collision.rs:5:17 | LL | [_, 99.., _] => {}, - | ^^ + | ^ error: aborting due to previous error diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr index 5ac435bf011e4..8f849d7b3f87c 100644 --- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr +++ b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr @@ -1,8 +1,8 @@ error: unexpected token: `]` - --> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:15 + --> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:17 | LL | [_, 99..] => {}, - | ^^ + | ^ error: aborting due to previous error diff --git a/src/test/ui/macros/macro-attribute.stderr b/src/test/ui/macros/macro-attribute.stderr index aa1cd94b0c638..d28ce25341d3a 100644 --- a/src/test/ui/macros/macro-attribute.stderr +++ b/src/test/ui/macros/macro-attribute.stderr @@ -1,8 +1,8 @@ error: unexpected token: `$` - --> $DIR/macro-attribute.rs:1:7 + --> $DIR/macro-attribute.rs:1:9 | LL | #[doc = $not_there] - | ^ + | ^ error: aborting due to previous error diff --git a/src/test/ui/malformed/malformed-interpolated.stderr b/src/test/ui/malformed/malformed-interpolated.stderr index bc2146e409d47..e805416172bab 100644 --- a/src/test/ui/malformed/malformed-interpolated.stderr +++ b/src/test/ui/malformed/malformed-interpolated.stderr @@ -7,19 +7,19 @@ LL | check!(0u8); = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.). error: unexpected token: `-0` - --> $DIR/malformed-interpolated.rs:5:19 + --> $DIR/malformed-interpolated.rs:5:21 | LL | #[my_attr = $expr] - | ^ + | ^^^^^ ... LL | check!(-0); // ERROR, see above | ----------- in this macro invocation error: unexpected token: `0 + 0` - --> $DIR/malformed-interpolated.rs:5:19 + --> $DIR/malformed-interpolated.rs:5:21 | LL | #[my_attr = $expr] - | ^ + | ^^^^^ ... LL | check!(0 + 0); // ERROR, see above | -------------- in this macro invocation diff --git a/src/test/ui/parser/attr-bad-meta-2.stderr b/src/test/ui/parser/attr-bad-meta-2.stderr index ffbfc583e8a75..2d772dae69125 100644 --- a/src/test/ui/parser/attr-bad-meta-2.stderr +++ b/src/test/ui/parser/attr-bad-meta-2.stderr @@ -1,8 +1,8 @@ error: unexpected token: `]` - --> $DIR/attr-bad-meta-2.rs:1:8 + --> $DIR/attr-bad-meta-2.rs:1:9 | LL | #[path =] - | ^ + | ^ error: aborting due to previous error diff --git a/src/test/ui/parser/pat-tuple-5.stderr b/src/test/ui/parser/pat-tuple-5.stderr index 61ae40b355d38..f9832214c6800 100644 --- a/src/test/ui/parser/pat-tuple-5.stderr +++ b/src/test/ui/parser/pat-tuple-5.stderr @@ -1,8 +1,8 @@ error: unexpected token: `)` - --> $DIR/pat-tuple-5.rs:3:14 + --> $DIR/pat-tuple-5.rs:3:16 | LL | (pat ..) => {} - | ^^ + | ^ error: aborting due to previous error From 362431b4d6029e473166b9df307a171d961b5675 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 11 May 2019 15:42:14 +0200 Subject: [PATCH 189/212] Cleanup the .await HIR lowering with .stmt(..). --- src/librustc/hir/lowering.rs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 7ccfb826e37b7..1612e0a6e9df3 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -5647,11 +5647,7 @@ impl<'a> LoweringContext<'a> { hir_vec![ready_arm, pending_arm], hir::MatchSource::AwaitDesugar, )); - hir::Stmt { - hir_id: self.next_id(), - node: hir::StmtKind::Expr(match_expr), - span, - } + self.stmt(span, hir::StmtKind::Expr(match_expr)) }; let yield_stmt = { @@ -5661,11 +5657,7 @@ impl<'a> LoweringContext<'a> { hir::ExprKind::Yield(P(unit)), ThinVec::new(), )); - hir::Stmt { - hir_id: self.next_id(), - node: hir::StmtKind::Expr(yield_expr), - span, - } + self.stmt(span, hir::StmtKind::Expr(yield_expr)) }; let loop_block = P(self.block_all( From 83ed781c017632d48746553bdb2bf3d1633d5ca4 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 11 May 2019 16:03:27 +0300 Subject: [PATCH 190/212] Address comments + Fix tests --- src/librustdoc/clean/cfg.rs | 2 ++ src/libsyntax/ast.rs | 9 +++++++-- src/libsyntax/parse/literal.rs | 4 ++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 51fe26b374313..b96ac19c1ea61 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -416,6 +416,8 @@ mod test { use syntax_pos::DUMMY_SP; use syntax::ast::*; + use syntax::attr; + use syntax::source_map::dummy_spanned; use syntax::symbol::Symbol; use syntax::with_globals; diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index a188f1a936890..aa176c8925883 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1351,12 +1351,17 @@ pub enum StrStyle { Raw(u16), } -/// A literal. +/// An AST literal. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Lit { - pub node: LitKind, + /// The original literal token as written in source code. pub token: token::Lit, + /// The original literal suffix as written in source code. pub suffix: Option, + /// The "semantic" representation of the literal lowered from the original tokens. + /// Strings are unescaped, hexadecimal forms are eliminated, etc. + /// FIXME: Remove this and only create the semantic representation during lowering to HIR. + pub node: LitKind, pub span: Span, } diff --git a/src/libsyntax/parse/literal.rs b/src/libsyntax/parse/literal.rs index 2c7ba13fbef82..53195421ddcee 100644 --- a/src/libsyntax/parse/literal.rs +++ b/src/libsyntax/parse/literal.rs @@ -27,7 +27,7 @@ macro_rules! err { impl LitKind { /// Converts literal token with a suffix into a semantic literal. - /// Works speculatively and may return `None` is diagnostic handler is not passed. + /// Works speculatively and may return `None` if diagnostic handler is not passed. /// If diagnostic handler is passed, always returns `Some`, /// possibly after reporting non-fatal errors and recovery. fn from_lit_token( @@ -166,7 +166,7 @@ impl LitKind { impl Lit { /// Converts literal token with a suffix into an AST literal. - /// Works speculatively and may return `None` is diagnostic handler is not passed. + /// Works speculatively and may return `None` if diagnostic handler is not passed. /// If diagnostic handler is passed, may return `Some`, /// possibly after reporting non-fatal errors and recovery, or `None` for irrecoverable errors. crate fn from_token( From d17713599cca675d2ca5def29fdce4b353c97234 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sat, 11 May 2019 08:56:38 -0700 Subject: [PATCH 191/212] Update clippy --- Cargo.lock | 2 -- src/tools/clippy | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f6334e9bdb815..982070a243ee5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -378,7 +378,6 @@ dependencies = [ "rustc_tools_util 0.1.1", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -399,7 +398,6 @@ dependencies = [ "regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/src/tools/clippy b/src/tools/clippy index 341c96afd3311..3710ec5996229 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit 341c96afd331195beeb001436535c1feb479ff9d +Subproject commit 3710ec59962295336ab4aed100267b584dd7df7d From a145b14b3e1f7bf15ea67d2bd9c39c85395f94bb Mon Sep 17 00:00:00 2001 From: Yusuke Matsushita Date: Sun, 12 May 2019 01:47:20 +0900 Subject: [PATCH 192/212] Remove redundant "let mut" in write_graph_label Removed the redundant "let mut" in the write_graph_label function (it caused "let mut let mut" for non-user-defined local variables). --- src/librustc_mir/util/graphviz.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/util/graphviz.rs b/src/librustc_mir/util/graphviz.rs index 04b0e16cd9a81..188da9a82dc99 100644 --- a/src/librustc_mir/util/graphviz.rs +++ b/src/librustc_mir/util/graphviz.rs @@ -167,7 +167,7 @@ fn write_graph_label<'a, 'gcx, 'tcx, W: Write>(tcx: TyCtxt<'a, 'gcx, 'tcx>, write!(w, r#"{:?}: {}; // {}
"#, Place::Base(PlaceBase::Local(local)), escape(&decl.ty), name)?; } else { - write!(w, r#"let mut {:?}: {};
"#, + write!(w, r#"{:?}: {};
"#, Place::Base(PlaceBase::Local(local)), escape(&decl.ty))?; } } From 5ccf2fb985b5581fdc3f1a3a647b0d613da996d3 Mon Sep 17 00:00:00 2001 From: Mike Boutin Date: Sun, 5 May 2019 10:25:01 -0400 Subject: [PATCH 193/212] Add #[doc(hidden)] attribute on compiler generated proc-macro module. Stops unavoidable `missing_docs` warning/error on proc-macro crates. Resolves #42008. --- src/libsyntax_ext/proc_macro_decls.rs | 7 ++++++- src/test/ui/proc-macro/no-missing-docs.rs | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/proc-macro/no-missing-docs.rs diff --git a/src/libsyntax_ext/proc_macro_decls.rs b/src/libsyntax_ext/proc_macro_decls.rs index f0390ba3d40cb..e14781c4fa9f5 100644 --- a/src/libsyntax_ext/proc_macro_decls.rs +++ b/src/libsyntax_ext/proc_macro_decls.rs @@ -324,6 +324,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { // Creates a new module which looks like: // +// #[doc(hidden)] // mod $gensym { // extern crate proc_macro; // @@ -357,6 +358,10 @@ fn mk_decls( }); let span = DUMMY_SP.apply_mark(mark); + let hidden = cx.meta_list_item_word(span, Symbol::intern("hidden")); + let doc = cx.meta_list(span, Symbol::intern("doc"), vec![hidden]); + let doc_hidden = cx.attribute(span, doc); + let proc_macro = Ident::from_str("proc_macro"); let krate = cx.item(span, proc_macro, @@ -421,7 +426,7 @@ fn mk_decls( span, span, ast::Ident::with_empty_ctxt(Symbol::gensym("decls")), - vec![], + vec![doc_hidden], vec![krate, decls_static], ).map(|mut i| { i.vis = respan(span, ast::VisibilityKind::Public); diff --git a/src/test/ui/proc-macro/no-missing-docs.rs b/src/test/ui/proc-macro/no-missing-docs.rs new file mode 100644 index 0000000000000..e5a5f8beb4585 --- /dev/null +++ b/src/test/ui/proc-macro/no-missing-docs.rs @@ -0,0 +1,16 @@ +//! Verify that the `decls` module implicitly added by the compiler does not cause `missing_docs` +//! warnings. + +// compile-pass +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![deny(missing_docs)] + +extern crate proc_macro; +use proc_macro::*; + +/// Foo1. +#[proc_macro] +pub fn foo1(input: TokenStream) -> TokenStream { input } From 3b78a474f3048dd6221e1ddd3e5b1af61df3945d Mon Sep 17 00:00:00 2001 From: Pulkit Goyal <7895pulkit@gmail.com> Date: Thu, 9 May 2019 21:32:33 +0300 Subject: [PATCH 194/212] Fix HIR printing of existential type #60662 This fixes https://github.com/rust-lang/rust/issues/60662 --- src/librustc/hir/print.rs | 1 - src/test/ui/issues/issue-60662.rs | 11 +++++++++++ src/test/ui/issues/issue-60662.stdout | 14 ++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/issues/issue-60662.rs create mode 100644 src/test/ui/issues/issue-60662.stdout diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index c42d8f3cb3c36..88fbe9a06ddd1 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -646,7 +646,6 @@ impl<'a> State<'a> { self.print_where_clause(&exist.generics.where_clause)?; self.s.space()?; - self.word_space(":")?; let mut real_bounds = Vec::with_capacity(exist.bounds.len()); for b in exist.bounds.iter() { if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b { diff --git a/src/test/ui/issues/issue-60662.rs b/src/test/ui/issues/issue-60662.rs new file mode 100644 index 0000000000000..fe4eaff742d62 --- /dev/null +++ b/src/test/ui/issues/issue-60662.rs @@ -0,0 +1,11 @@ +// compile-pass +// compile-flags: -Z unpretty=hir + +#![feature(existential_type)] + +trait Animal { +} + +fn main() { + pub existential type ServeFut: Animal; +} diff --git a/src/test/ui/issues/issue-60662.stdout b/src/test/ui/issues/issue-60662.stdout new file mode 100644 index 0000000000000..5acfdf9ed5342 --- /dev/null +++ b/src/test/ui/issues/issue-60662.stdout @@ -0,0 +1,14 @@ +// compile-pass +// compile-flags: -Z unpretty=hir + +#![feature(existential_type)] +#[prelude_import] +use ::std::prelude::v1::*; +#[macro_use] +extern crate std; + +trait Animal { } + +fn main() { + pub existential type ServeFut : Animal; + } From 14b353820f94d8613a678be73ce96cf646038bf4 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 11 May 2019 22:44:33 +0300 Subject: [PATCH 195/212] syntax: Remove some legacy nonterminal tokens --- src/libsyntax/mut_visit.rs | 4 ---- src/libsyntax/parse/parser.rs | 8 -------- src/libsyntax/parse/token.rs | 14 ++++---------- src/libsyntax/print/pprust.rs | 4 ---- 4 files changed, 4 insertions(+), 26 deletions(-) diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 6eb8b1b5004c9..f587e63e12b94 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -663,7 +663,6 @@ pub fn noop_visit_interpolated(nt: &mut token::Nonterminal, vis: token::NtMeta(meta) => vis.visit_meta_item(meta), token::NtPath(path) => vis.visit_path(path), token::NtTT(tt) => vis.visit_tt(tt), - token::NtArm(arm) => vis.visit_arm(arm), token::NtImplItem(item) => visit_clobber(item, |item| { // See reasoning above. @@ -676,9 +675,6 @@ pub fn noop_visit_interpolated(nt: &mut token::Nonterminal, vis: vis.flat_map_trait_item(item) .expect_one("expected visitor to produce exactly one item") }), - token::NtGenerics(generics) => vis.visit_generics(generics), - token::NtWhereClause(where_clause) => vis.visit_where_clause(where_clause), - token::NtArg(arg) => vis.visit_arg(arg), token::NtVis(visib) => vis.visit_vis(visib), token::NtForeignItem(item) => visit_clobber(item, |item| { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d97d1e2f0f4ee..48aaa1cbb0342 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1925,8 +1925,6 @@ impl<'a> Parser<'a> { /// This version of parse arg doesn't necessarily require identifier names. fn parse_arg_general(&mut self, require_name: bool, is_trait_item: bool, allow_c_variadic: bool) -> PResult<'a, Arg> { - maybe_whole!(self, NtArg, |x| x); - if let Ok(Some(_)) = self.parse_self_arg() { let mut err = self.struct_span_err(self.prev_span, "unexpected `self` argument in function"); @@ -4179,8 +4177,6 @@ impl<'a> Parser<'a> { } crate fn parse_arm(&mut self) -> PResult<'a, Arm> { - maybe_whole!(self, NtArm, |x| x); - let attrs = self.parse_outer_attributes()?; let pats = self.parse_pats()?; let guard = if self.eat_keyword(keywords::If) { @@ -5915,8 +5911,6 @@ impl<'a> Parser<'a> { /// | ( < lifetimes , typaramseq ( , )? > ) /// where typaramseq = ( typaram ) | ( typaram , typaramseq ) fn parse_generics(&mut self) -> PResult<'a, ast::Generics> { - maybe_whole!(self, NtGenerics, |x| x); - let span_lo = self.span; if self.eat_lt() { let params = self.parse_generic_params()?; @@ -6169,8 +6163,6 @@ impl<'a> Parser<'a> { /// where T : Trait + 'b, 'a : 'b /// ``` fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> { - maybe_whole!(self, NtWhereClause, |x| x); - let mut where_clause = WhereClause { id: ast::DUMMY_NODE_ID, predicates: Vec::new(), diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index fd7a39c576daa..79852e38596d6 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -585,14 +585,12 @@ pub enum Nonterminal { NtPath(ast::Path), NtVis(ast::Visibility), NtTT(TokenTree), - // These are not exposed to macros, but are used by quasiquote. - NtArm(ast::Arm), - NtImplItem(ast::ImplItem), + // Used only for passing items to proc macro attributes (they are not + // strictly necessary for that, `Annotatable` can be converted into + // tokens directly, but doing that naively regresses pretty-printing). NtTraitItem(ast::TraitItem), + NtImplItem(ast::ImplItem), NtForeignItem(ast::ForeignItem), - NtGenerics(ast::Generics), - NtWhereClause(ast::WhereClause), - NtArg(ast::Arg), } impl PartialEq for Nonterminal { @@ -625,13 +623,9 @@ impl fmt::Debug for Nonterminal { NtMeta(..) => f.pad("NtMeta(..)"), NtPath(..) => f.pad("NtPath(..)"), NtTT(..) => f.pad("NtTT(..)"), - NtArm(..) => f.pad("NtArm(..)"), NtImplItem(..) => f.pad("NtImplItem(..)"), NtTraitItem(..) => f.pad("NtTraitItem(..)"), NtForeignItem(..) => f.pad("NtForeignItem(..)"), - NtGenerics(..) => f.pad("NtGenerics(..)"), - NtWhereClause(..) => f.pad("NtWhereClause(..)"), - NtArg(..) => f.pad("NtArg(..)"), NtVis(..) => f.pad("NtVis(..)"), NtLifetime(..) => f.pad("NtLifetime(..)"), } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 682621d40ab65..0a402e9240058 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -278,12 +278,8 @@ pub fn nonterminal_to_string(nt: &Nonterminal) -> String { token::NtLifetime(e) => ident_to_string(e), token::NtLiteral(ref e) => expr_to_string(e), token::NtTT(ref tree) => tt_to_string(tree.clone()), - token::NtArm(ref e) => arm_to_string(e), token::NtImplItem(ref e) => impl_item_to_string(e), token::NtTraitItem(ref e) => trait_item_to_string(e), - token::NtGenerics(ref e) => generic_params_to_string(&e.params), - token::NtWhereClause(ref e) => where_clause_to_string(e), - token::NtArg(ref e) => arg_to_string(e), token::NtVis(ref e) => vis_to_string(e), token::NtForeignItem(ref e) => foreign_item_to_string(e), } From 0535e42678d45084e2cff03dbd63f5168731564c Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 5 May 2019 14:06:04 +0200 Subject: [PATCH 196/212] ast_validation: comments -> doc comments --- src/librustc_passes/ast_validation.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 6cb3161382af2..16935796d4ba7 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -54,21 +54,21 @@ struct AstValidator<'a> { has_proc_macro_decls: bool, has_global_allocator: bool, - // Used to ban nested `impl Trait`, e.g., `impl Into`. - // Nested `impl Trait` _is_ allowed in associated type position, - // e.g `impl Iterator` + /// Used to ban nested `impl Trait`, e.g., `impl Into`. + /// Nested `impl Trait` _is_ allowed in associated type position, + /// e.g `impl Iterator` outer_impl_trait: Option, - // Used to ban `impl Trait` in path projections like `::Item` - // or `Foo::Bar` + /// Used to ban `impl Trait` in path projections like `::Item` + /// or `Foo::Bar` is_impl_trait_banned: bool, - // rust-lang/rust#57979: the ban of nested `impl Trait` was buggy - // until PRs #57730 and #57981 landed: it would jump directly to - // walk_ty rather than visit_ty (or skip recurring entirely for - // impl trait in projections), and thus miss some cases. We track - // whether we should downgrade to a warning for short-term via - // these booleans. + /// rust-lang/rust#57979: the ban of nested `impl Trait` was buggy + /// until PRs #57730 and #57981 landed: it would jump directly to + /// walk_ty rather than visit_ty (or skip recurring entirely for + /// impl trait in projections), and thus miss some cases. We track + /// whether we should downgrade to a warning for short-term via + /// these booleans. warning_period_57979_didnt_record_next_impl_trait: bool, warning_period_57979_impl_trait_in_proj: bool, } From 9b4a630baaba9bc36bce91d0721886f38ad1b182 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 12 May 2019 02:00:06 +0200 Subject: [PATCH 197/212] syntax::parse::parser: convert unnecessary '&mut self's to '&self'. --- src/libsyntax/parse/parser.rs | 38 +++++++++++++++++------------------ 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d97d1e2f0f4ee..36ee1949ad587 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1877,7 +1877,7 @@ impl<'a> Parser<'a> { Ok(MutTy { ty: t, mutbl: mutbl }) } - fn is_named_argument(&mut self) -> bool { + fn is_named_argument(&self) -> bool { let offset = match self.token { token::Interpolated(ref nt) => match **nt { token::NtPat(..) => return self.look_ahead(1, |t| t == &token::Colon), @@ -2471,27 +2471,27 @@ impl<'a> Parser<'a> { }) } - fn mk_expr(&mut self, span: Span, node: ExprKind, attrs: ThinVec) -> P { + fn mk_expr(&self, span: Span, node: ExprKind, attrs: ThinVec) -> P { P(Expr { node, span, attrs, id: ast::DUMMY_NODE_ID }) } - fn mk_unary(&mut self, unop: ast::UnOp, expr: P) -> ast::ExprKind { + fn mk_unary(&self, unop: ast::UnOp, expr: P) -> ast::ExprKind { ExprKind::Unary(unop, expr) } - fn mk_binary(&mut self, binop: ast::BinOp, lhs: P, rhs: P) -> ast::ExprKind { + fn mk_binary(&self, binop: ast::BinOp, lhs: P, rhs: P) -> ast::ExprKind { ExprKind::Binary(binop, lhs, rhs) } - fn mk_call(&mut self, f: P, args: Vec>) -> ast::ExprKind { + fn mk_call(&self, f: P, args: Vec>) -> ast::ExprKind { ExprKind::Call(f, args) } - fn mk_index(&mut self, expr: P, idx: P) -> ast::ExprKind { + fn mk_index(&self, expr: P, idx: P) -> ast::ExprKind { ExprKind::Index(expr, idx) } - fn mk_range(&mut self, + fn mk_range(&self, start: Option>, end: Option>, limits: RangeLimits) @@ -2503,7 +2503,7 @@ impl<'a> Parser<'a> { } } - fn mk_assign_op(&mut self, binop: ast::BinOp, + fn mk_assign_op(&self, binop: ast::BinOp, lhs: P, rhs: P) -> ast::ExprKind { ExprKind::AssignOp(binop, lhs, rhs) } @@ -3840,7 +3840,7 @@ impl<'a> Parser<'a> { /// Produce an error if comparison operators are chained (RFC #558). /// We only need to check lhs, not rhs, because all comparison ops /// have same precedence and are left-associative - fn check_no_chained_comparison(&mut self, lhs: &Expr, outer_op: &AssocOp) { + fn check_no_chained_comparison(&self, lhs: &Expr, outer_op: &AssocOp) { debug_assert!(outer_op.is_comparison(), "check_no_chained_comparison: {:?} is not comparison", outer_op); @@ -5137,7 +5137,7 @@ impl<'a> Parser<'a> { }) } - fn is_async_block(&mut self) -> bool { + fn is_async_block(&self) -> bool { self.token.is_keyword(keywords::Async) && ( ( // `async move {` @@ -5149,19 +5149,19 @@ impl<'a> Parser<'a> { ) } - fn is_async_fn(&mut self) -> bool { + fn is_async_fn(&self) -> bool { self.token.is_keyword(keywords::Async) && self.look_ahead(1, |t| t.is_keyword(keywords::Fn)) } - fn is_do_catch_block(&mut self) -> bool { + fn is_do_catch_block(&self) -> bool { self.token.is_keyword(keywords::Do) && self.look_ahead(1, |t| t.is_keyword(keywords::Catch)) && self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace)) && !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL) } - fn is_try_block(&mut self) -> bool { + fn is_try_block(&self) -> bool { self.token.is_keyword(keywords::Try) && self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) && self.span.rust_2018() && @@ -5183,7 +5183,7 @@ impl<'a> Parser<'a> { self.look_ahead(1, |t| t.is_keyword(keywords::Type)) } - fn is_auto_trait_item(&mut self) -> bool { + fn is_auto_trait_item(&self) -> bool { // auto trait (self.token.is_keyword(keywords::Auto) && self.look_ahead(1, |t| t.is_keyword(keywords::Trait))) @@ -5445,7 +5445,7 @@ impl<'a> Parser<'a> { } /// Checks if this expression is a successfully parsed statement. - fn expr_is_complete(&mut self, e: &Expr) -> bool { + fn expr_is_complete(&self, e: &Expr) -> bool { self.restrictions.contains(Restrictions::STMT_EXPR) && !classify::expr_requires_semi_to_be_stmt(e) } @@ -6517,7 +6517,7 @@ impl<'a> Parser<'a> { Ok((id, generics)) } - fn mk_item(&mut self, span: Span, ident: Ident, node: ItemKind, vis: Visibility, + fn mk_item(&self, span: Span, ident: Ident, node: ItemKind, vis: Visibility, attrs: Vec) -> P { P(Item { ident, @@ -6549,7 +6549,7 @@ impl<'a> Parser<'a> { /// Returns `true` if we are looking at `const ID` /// (returns `false` for things like `const fn`, etc.). - fn is_const_item(&mut self) -> bool { + fn is_const_item(&self) -> bool { self.token.is_keyword(keywords::Const) && !self.look_ahead(1, |t| t.is_keyword(keywords::Fn)) && !self.look_ahead(1, |t| t.is_keyword(keywords::Unsafe)) @@ -6657,7 +6657,7 @@ impl<'a> Parser<'a> { }) } - fn complain_if_pub_macro(&mut self, vis: &VisibilityKind, sp: Span) { + fn complain_if_pub_macro(&self, vis: &VisibilityKind, sp: Span) { match *vis { VisibilityKind::Inherited => {} _ => { @@ -6686,7 +6686,7 @@ impl<'a> Parser<'a> { } } - fn missing_assoc_item_kind_err(&mut self, item_type: &str, prev_span: Span) + fn missing_assoc_item_kind_err(&self, item_type: &str, prev_span: Span) -> DiagnosticBuilder<'a> { let expected_kinds = if item_type == "extern" { From b680b66dddf0d4ea4286c1ed921ac48511937923 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 12 May 2019 02:01:32 +0200 Subject: [PATCH 198/212] parse_bottom_expr: extract common 'return' out. --- src/libsyntax/parse/parser.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 36ee1949ad587..3eb5281e3b169 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2643,13 +2643,12 @@ impl<'a> Parser<'a> { hi = path.span; return Ok(self.mk_expr(lo.to(hi), ExprKind::Path(Some(qself), path), attrs)); } - if self.span.rust_2018() && self.check_keyword(keywords::Async) - { - if self.is_async_block() { // check for `async {` and `async move {` - return self.parse_async_block(attrs); + if self.span.rust_2018() && self.check_keyword(keywords::Async) { + return if self.is_async_block() { // check for `async {` and `async move {` + self.parse_async_block(attrs) } else { - return self.parse_lambda_expr(attrs); - } + self.parse_lambda_expr(attrs) + }; } if self.check_keyword(keywords::Move) || self.check_keyword(keywords::Static) { return self.parse_lambda_expr(attrs); From 4aa4a8f776d9ab3f0110f74f85cc8313b9e4d604 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 12 May 2019 02:17:34 +0200 Subject: [PATCH 199/212] Minor cleanup in parse_assoc_expr_with. --- src/libsyntax/parse/parser.rs | 38 +++++++++++++---------------------- 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 3eb5281e3b169..0e2e4eceabf44 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3573,7 +3573,8 @@ impl<'a> Parser<'a> { } else { self.restrictions }; - if op.precedence() < min_prec { + let prec = op.precedence(); + if prec < min_prec { break; } // Check for deprecated `...` syntax @@ -3614,8 +3615,7 @@ impl<'a> Parser<'a> { // We have 2 alternatives here: `x..y`/`x..=y` and `x..`/`x..=` The other // two variants are handled with `parse_prefix_range_expr` call above. let rhs = if self.is_at_start_of_range_notation_rhs() { - Some(self.parse_assoc_expr_with(op.precedence() + 1, - LhsExpr::NotYetParsed)?) + Some(self.parse_assoc_expr_with(prec + 1, LhsExpr::NotYetParsed)?) } else { None }; @@ -3635,28 +3635,18 @@ impl<'a> Parser<'a> { break } - let rhs = match op.fixity() { - Fixity::Right => self.with_res( - restrictions - Restrictions::STMT_EXPR, - |this| { - this.parse_assoc_expr_with(op.precedence(), - LhsExpr::NotYetParsed) - }), - Fixity::Left => self.with_res( - restrictions - Restrictions::STMT_EXPR, - |this| { - this.parse_assoc_expr_with(op.precedence() + 1, - LhsExpr::NotYetParsed) - }), + let fixity = op.fixity(); + let prec_adjustment = match fixity { + Fixity::Right => 0, + Fixity::Left => 1, // We currently have no non-associative operators that are not handled above by // the special cases. The code is here only for future convenience. - Fixity::None => self.with_res( - restrictions - Restrictions::STMT_EXPR, - |this| { - this.parse_assoc_expr_with(op.precedence() + 1, - LhsExpr::NotYetParsed) - }), - }?; + Fixity::None => 1, + }; + let rhs = self.with_res( + restrictions - Restrictions::STMT_EXPR, + |this| this.parse_assoc_expr_with(prec + prec_adjustment, LhsExpr::NotYetParsed) + )?; // Make sure that the span of the parent node is larger than the span of lhs and rhs, // including the attributes. @@ -3702,7 +3692,7 @@ impl<'a> Parser<'a> { } }; - if op.fixity() == Fixity::None { break } + if let Fixity::None = fixity { break } } Ok(lhs) } From 0fc2cfb66c7de60099386a3cc091e2bbb2b2187a Mon Sep 17 00:00:00 2001 From: Yusuke Matsushita Date: Sun, 12 May 2019 09:52:38 +0900 Subject: [PATCH 200/212] Fix minor typos for ItemLocalId * added comma before 'that is' * "can be implement" -> "can be implemented" --- src/librustc/hir/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 9f7fa6c5557ef..3778324f01a19 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -126,12 +126,12 @@ mod item_local_id_inner { use rustc_macros::HashStable; newtype_index! { /// An `ItemLocalId` uniquely identifies something within a given "item-like", - /// that is within a hir::Item, hir::TraitItem, or hir::ImplItem. There is no + /// that is, within a hir::Item, hir::TraitItem, or hir::ImplItem. There is no /// guarantee that the numerical value of a given `ItemLocalId` corresponds to /// the node's position within the owning item in any way, but there is a /// guarantee that the `LocalItemId`s within an owner occupy a dense range of /// integers starting at zero, so a mapping that maps all or most nodes within - /// an "item-like" to something else can be implement by a `Vec` instead of a + /// an "item-like" to something else can be implemented by a `Vec` instead of a /// tree or hash map. pub struct ItemLocalId { derive [HashStable] From 664c8ed301c8089e77775ac3a52d3f3d938e74d3 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 12 May 2019 17:12:49 +0100 Subject: [PATCH 201/212] Always use the stronger outlives version for opaque types --- src/librustc/infer/opaque_types/mod.rs | 34 +++++++++++++++---- .../can-return-unconstrained-closure.rs | 4 +++ .../issue-57464-unexpected-regions.rs | 7 ++++ 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index f85fd524a5d9b..6bf23ab864abd 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -284,18 +284,40 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { debug!("constrain_opaque_type: def_id={:?}", def_id); debug!("constrain_opaque_type: opaque_defn={:#?}", opaque_defn); + let tcx = self.tcx; + let concrete_ty = self.resolve_type_vars_if_possible(&opaque_defn.concrete_ty); debug!("constrain_opaque_type: concrete_ty={:?}", concrete_ty); - let abstract_type_generics = self.tcx.generics_of(def_id); + let abstract_type_generics = tcx.generics_of(def_id); - let span = self.tcx.def_span(def_id); + let span = tcx.def_span(def_id); - // If there are required region bounds, we can just skip - // ahead. There will already be a registered region - // obligation related `concrete_ty` to those regions. + // If there are required region bounds, we can use them. if opaque_defn.has_required_region_bounds { + let predicates_of = tcx.predicates_of(def_id); + debug!( + "constrain_opaque_type: predicates: {:#?}", + predicates_of, + ); + let bounds = predicates_of.instantiate(tcx, opaque_defn.substs); + debug!("constrain_opaque_type: bounds={:#?}", bounds); + let opaque_type = tcx.mk_opaque(def_id, opaque_defn.substs); + + let required_region_bounds = tcx.required_region_bounds( + opaque_type, + bounds.predicates.clone(), + ); + debug_assert!(!required_region_bounds.is_empty()); + + for region in required_region_bounds { + concrete_ty.visit_with(&mut OpaqueTypeOutlivesVisitor { + infcx: self, + least_region: region, + span, + }); + } return; } @@ -371,7 +393,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } - let least_region = least_region.unwrap_or(self.tcx.lifetimes.re_static); + let least_region = least_region.unwrap_or(tcx.lifetimes.re_static); debug!("constrain_opaque_types: least_region={:?}", least_region); concrete_ty.visit_with(&mut OpaqueTypeOutlivesVisitor { diff --git a/src/test/ui/impl-trait/can-return-unconstrained-closure.rs b/src/test/ui/impl-trait/can-return-unconstrained-closure.rs index a982b176ecda1..90a7519074b53 100644 --- a/src/test/ui/impl-trait/can-return-unconstrained-closure.rs +++ b/src/test/ui/impl-trait/can-return-unconstrained-closure.rs @@ -16,4 +16,8 @@ fn make_identity() -> impl Sized { |x: &'static i32| x } +fn make_identity_static() -> impl Sized + 'static { + |x: &'static i32| x +} + fn main() {} diff --git a/src/test/ui/impl-trait/issue-57464-unexpected-regions.rs b/src/test/ui/impl-trait/issue-57464-unexpected-regions.rs index 29e271c68ec90..11f1a392239dc 100644 --- a/src/test/ui/impl-trait/issue-57464-unexpected-regions.rs +++ b/src/test/ui/impl-trait/issue-57464-unexpected-regions.rs @@ -17,6 +17,13 @@ fn wrapped_closure() -> impl Sized { A(f) } +fn wrapped_closure_with_bound() -> impl Sized + 'static { + let f = |x| x; + f(&0); + A(f) +} + fn main() { let x: Box = Box::new(wrapped_closure()); + let y: Box = Box::new(wrapped_closure_with_bound()); } From 1f5145e2735083475d586f4a6a1a389a090f30e4 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 12 May 2019 17:52:33 +0100 Subject: [PATCH 202/212] Treat generators the same as closure for escaping lifetimes --- src/librustc/infer/opaque_types/mod.rs | 17 +++++++++++++++++ src/test/run-pass/impl-trait/lifetimes.rs | 6 ++++++ 2 files changed, 23 insertions(+) diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index 6bf23ab864abd..a8dca9062bd2c 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -705,6 +705,23 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ReverseMapper<'cx, 'gcx, 'tcx> self.tcx.mk_closure(def_id, ty::ClosureSubsts { substs }) } + ty::Generator(def_id, substs, movability) => { + let generics = self.tcx.generics_of(def_id); + let substs = self.tcx.mk_substs(substs.substs.iter().enumerate().map( + |(index, &kind)| { + if index < generics.parent_count { + // Accommodate missing regions in the parent kinds... + self.fold_kind_mapping_missing_regions_to_empty(kind) + } else { + // ...but not elsewhere. + self.fold_kind_normally(kind) + } + }, + )); + + self.tcx.mk_generator(def_id, ty::GeneratorSubsts { substs }, movability) + } + _ => ty.super_fold_with(self), } } diff --git a/src/test/run-pass/impl-trait/lifetimes.rs b/src/test/run-pass/impl-trait/lifetimes.rs index 5a21e1dd81759..9a9843375e4c5 100644 --- a/src/test/run-pass/impl-trait/lifetimes.rs +++ b/src/test/run-pass/impl-trait/lifetimes.rs @@ -1,6 +1,7 @@ // run-pass #![allow(warnings)] +#![feature(generators)] use std::fmt::Debug; @@ -112,6 +113,11 @@ impl<'unnecessary_lifetime> MyVec { fn iter_doesnt_capture_unnecessary_lifetime<'s>(&'s self) -> impl Iterator { self.0.iter().flat_map(|inner_vec| inner_vec.iter()) } + + fn generator_doesnt_capture_unnecessary_lifetime<'s: 's>() -> impl Sized { + || yield + } } + fn main() {} From 9a4f0abd7a385416acf9d93b9d77ea1fdf755f93 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 12 May 2019 18:51:40 +0100 Subject: [PATCH 203/212] Don't allow any ReScope in impl trait types This shouldn't be possible any more, but if it does happen, emit an error rather than maybe panicking later when NLL finds a the ReScope. Impl trait in bindings is sufficiently broken that I don't think this breaks anything that works for it. --- src/librustc/infer/opaque_types/mod.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index a8dca9062bd2c..4351f94df2f13 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -611,10 +611,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ReverseMapper<'cx, 'gcx, 'tcx> ty::ReLateBound(..) | // ignore `'static`, as that can appear anywhere - ty::ReStatic | - - // ignore `ReScope`, which may appear in impl Trait in bindings. - ty::ReScope(..) => return r, + ty::ReStatic => return r, _ => { } } From a8245f5a38d0aa9cc392a1893fcbefb29bf77c2b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 7 May 2019 09:55:12 +1000 Subject: [PATCH 204/212] Add lots of static `Symbols`. These will be used in the subsequent commits. Many of them are attributes. The commit also adds the ability to handle symbols that aren't identifiers (e.g. "proc-macro"). --- src/librustc_macros/src/symbols.rs | 43 +++- src/libsyntax_pos/symbol.rs | 388 ++++++++++++++++++++++++++++- 2 files changed, 415 insertions(+), 16 deletions(-) diff --git a/src/librustc_macros/src/symbols.rs b/src/librustc_macros/src/symbols.rs index 169c5e1371833..a4c7daf088ff2 100644 --- a/src/librustc_macros/src/symbols.rs +++ b/src/librustc_macros/src/symbols.rs @@ -11,7 +11,7 @@ use quote::quote; #[allow(non_camel_case_types)] mod kw { syn::custom_keyword!(Keywords); - syn::custom_keyword!(Other); + syn::custom_keyword!(Symbols); } struct Keyword { @@ -33,14 +33,24 @@ impl Parse for Keyword { } } -struct Symbol(Ident); +struct Symbol { + name: Ident, + value: Option, +} impl Parse for Symbol { fn parse(input: ParseStream<'_>) -> Result { - let ident: Ident = input.parse()?; + let name = input.parse()?; + let value = match input.parse::() { + Ok(_) => Some(input.parse()?), + Err(_) => None, + }; input.parse::()?; - Ok(Symbol(ident)) + Ok(Symbol { + name, + value, + }) } } @@ -69,7 +79,7 @@ impl Parse for Input { braced!(content in input); let keywords = content.parse()?; - input.parse::()?; + input.parse::()?; let content; braced!(content in input); let symbols = content.parse()?; @@ -116,19 +126,22 @@ pub fn symbols(input: TokenStream) -> TokenStream { } for symbol in &input.symbols.0 { - let value = &symbol.0; - let value_str = value.to_string(); - check_dup(&value_str); + let name = &symbol.name; + let value = match &symbol.value { + Some(value) => value.value(), + None => name.to_string(), + }; + check_dup(&value); prefill_stream.extend(quote! { - #value_str, + #value, }); symbols_stream.extend(quote! { - pub const #value: Symbol = Symbol::new(#counter); + pub const #name: Symbol = Symbol::new(#counter); }); counter += 1; } - TokenStream::from(quote! { + let tt = TokenStream::from(quote! { macro_rules! keywords { () => { #keyword_stream @@ -159,5 +172,11 @@ pub fn symbols(input: TokenStream) -> TokenStream { ]) } } - }) + }); + + // To see the generated code generated, uncomment this line, recompile, and + // run the resulting output through `rustfmt`. + //eprintln!("{}", tt); + + tt } diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index c0c9c2a100042..5459f3904fa7c 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -99,88 +99,375 @@ symbols! { Union: "union", } - // Other symbols that can be referred to with syntax_pos::symbols::* - Other { + // Symbols that can be referred to with syntax_pos::symbols::*. The symbol + // is the stringified identifier unless otherwise specified (e.g. + // `proc_dash_macro` represents "proc-macro"). + Symbols { + aarch64_target_feature, + abi, + abi_amdgpu_kernel, + abi_msp430_interrupt, + abi_ptx, + abi_sysv64, + abi_thiscall, + abi_unadjusted, + abi_vectorcall, + abi_x86_interrupt, + aborts, + advanced_slice_patterns, + adx_target_feature, alias, align, + alignstack, + all, + allocator, + allocator_internals, alloc_error_handler, allow, + allowed, allow_fail, allow_internal_unsafe, allow_internal_unstable, + allow_internal_unstable_backcompat_hack, + always, + any, + arbitrary_self_types, + arm_target_feature, + asm, + associated_consts, + associated_type_defaults, + associated_types, + async_await, + attr, + attributes, + attr_literals, + augmented_assignments, automatically_derived, + avx512_target_feature, + await_macro, + bin, + bind_by_move_pattern_guards, + block, + borrowck_graphviz_postflow, + borrowck_graphviz_preflow, + box_patterns, + box_syntax, + braced_empty_structs, + C, + cdylib, cfg, cfg_attr, + cfg_attr_multi, + cfg_target_feature, + cfg_target_has_atomic, + cfg_target_thread_local, + cfg_target_vendor, + clone, + clone_closures, + clone_from, + closure_to_fn_coercion, + cmpxchg16b_target_feature, cold, + compile_error, compiler_builtins, + concat_idents, + conservative_impl_trait, + console, + const_compare_raw_pointers, + const_fn, + const_fn_union, + const_generics, + const_indexing, + const_let, + const_panic, + const_raw_ptr_deref, + const_raw_ptr_to_usize_cast, + const_transmute, + contents, + convert, + copy_closures, + core, + core_intrinsics, crate_id, + crate_in_paths, crate_name, crate_type, + crate_visibility_modifier, + custom_attribute, + custom_derive, + custom_inner_attributes, + custom_test_frameworks, + c_variadic, + decl_macro, default_lib_allocator, + default_type_parameter_fallback, + default_type_params, deny, deprecated, derive, doc, + doc_alias, + doc_cfg, + doc_keyword, + doc_masked, + doc_spotlight, + document_private_items, + dotdoteq_in_patterns, + dotdot_in_tuple_patterns, + dropck_eyepatch, + dropck_parametricity, + drop_types_in_const, + dylib, + dyn_trait, + eh_personality, + eh_unwind_resume, + enable, + Err, + except, + exclusive_range_pattern, + exhaustive_integer_patterns, + exhaustive_patterns, + existential_type, + expected, export_name, + extern_absolute_paths, + external_doc, + extern_crate_item_prelude, + extern_crate_self, + extern_in_paths, + extern_prelude, + extern_types, + f16c_target_feature, feature, ffi_returns_twice, + field_init_shorthand, + file, + fn_must_use, forbid, + format_args_nl, + from, + From, + from_error, + from_generator, + from_ok, fundamental, + future, + Future, + generators, + generic_associated_types, + generic_param_attrs, global_allocator, + global_asm, + globs, + hexagon_target_feature, + hidden, + homogeneous_aggregate, + html_favicon_url, + html_logo_url, + html_no_source, + html_playground_url, + html_root_url, + i128, + i128_type, + i16, + i32, + i64, + i8, + ident, + if_let, + if_while_or_patterns, ignore, + impl_header_lifetime_elision, + impl_trait_in_bindings, + import_shadowing, + in_band_lifetimes, include, + inclusive_range_syntax, + infer_outlives_requirements, + infer_static_outlives_requirements, inline, + intel, + into_iter, + IntoIterator, + into_result, + intrinsics, + irrefutable_let_patterns, + isize, + issue, + issue_5723_bootstrap, + issue_tracker_base_url, + item_like_imports, + iter, + Iterator, keyword, + kind, + label, + label_break_value, lang, + lang_items, + lib, link, + linkage, link_args, + link_cfg, + link_llvm_intrinsics, link_name, link_section, - linkage, + lint_reasons, + local_inner_macros, + log_syntax, + loop_break_value, + macro_at_most_once_rep, macro_escape, macro_export, + macro_lifetime_matcher, + macro_literal_matcher, + macro_reexport, + macro_rules, + macros_in_extern, macro_use, + macro_vis_matcher, main, + managed_boxes, marker, + marker_trait_attr, masked, + match_beginning_vert, + match_default_bindings, may_dangle, + message, + min_const_fn, + min_const_unsafe_fn, + mips_target_feature, + mmx_target_feature, + module, + more_struct_aliases, + movbe_target_feature, must_use, naked, + naked_functions, + name, needs_allocator, needs_panic_runtime, + negate_unsigned, + never, + never_type, + next, + nll, no_builtins, no_core, + no_crate_inject, no_debug, + no_default_passes, no_implicit_prelude, + no_inline, no_link, no_main, no_mangle, + non_ascii_idents, + None, + non_exhaustive, + non_modrs_mods, + no_stack_check, no_start, no_std, - non_exhaustive, + not, + note, + Ok, omit_gdb_pretty_printer_section, + on, + on_unimplemented, + oom, + ops, optimize, + optimize_attribute, + optin_builtin_traits, + option, + Option, + opt_out_copy, + overlapping_marker_traits, + packed, panic_handler, + panic_impl, + panic_implementation, panic_runtime, + passes, path, + pattern_parentheses, + Pending, + pin, + Pin, + platform_intrinsics, plugin, plugin_registrar, + plugins, + Poll, + poll_with_tls_context, + powerpc_target_feature, + precise_pointer_size_matching, + prelude, prelude_import, + primitive, + proc_dash_macro: "proc-macro", proc_macro, proc_macro_attribute, proc_macro_derive, + proc_macro_expr, + proc_macro_gen, + proc_macro_hygiene, + proc_macro_mod, + proc_macro_non_items, + proc_macro_path_invoc, profiler_runtime, + pub_restricted, + pushpop_unsafe, + quad_precision_float, + question_mark, + quote, + Range, + RangeFrom, + RangeFull, + RangeInclusive, + RangeTo, + RangeToInclusive, + raw_identifiers, + Ready, + reason, recursion_limit, reexport_test_harness_main, + reflect, + relaxed_adts, repr, + repr128, + repr_align, + repr_align_enum, + repr_packed, + repr_simd, + repr_transparent, + re_rebalance_coherence, + result, + Result, + Return, + rlib, + rtm_target_feature, + rust, + rust_2015_preview, + rust_2018_preview, + rust_begin_unwind, + rustc_allocator_nounwind, + rustc_allow_const_fn_ptr, rustc_args_required_const, + rustc_attrs, rustc_clean, rustc_const_unstable, rustc_conversion_suggestion, rustc_copy_clone_marker, rustc_def_path, rustc_deprecated, + rustc_diagnostic_macros, rustc_dirty, + rustc_doc_only_macro, + rustc_dump_env_program_clauses, rustc_dump_program_clauses, rustc_dump_user_substs, rustc_error, @@ -191,13 +478,21 @@ symbols! { rustc_layout_scalar_valid_range_end, rustc_layout_scalar_valid_range_start, rustc_mir, + rustc_object_lifetime_default, rustc_on_unimplemented, rustc_outlives, rustc_paren_sugar, rustc_partition_codegened, rustc_partition_reused, + rustc_peek, + rustc_peek_definite_init, + rustc_peek_maybe_init, + rustc_peek_maybe_uninit, + rustc_private, rustc_proc_macro_decls, + rustc_promotable, rustc_regions, + rustc_stable, rustc_std_internal_symbol, rustc_symbol_name, rustc_synthetic, @@ -205,23 +500,108 @@ symbols! { rustc_then_this_would_need, rustc_transparent_macro, rustc_variance, + rustdoc, + rust_eh_personality, + rust_eh_unwind_resume, + rust_oom, + __rust_unstable_column, + rvalue_static_promotion, sanitizer_runtime, + self_in_typedefs, + self_struct_ctor, + Send, should_panic, simd, + simd_ffi, + since, + size, + slice_patterns, + slicing_syntax, + Some, + specialization, + speed, spotlight, + sse4a_target_feature, stable, + staged_api, start, + static_in_const, + staticlib, + static_nobundle, + static_recursion, + std, + stmt_expr_attributes, + stop_after_dataflow, + struct_field_attributes, + struct_inherit, structural_match, + struct_variant, + suggestion, target_feature, + target_has_atomic, + target_thread_local, + task, + tbm_target_feature, + termination_trait, + termination_trait_test, + test, + test_2018_feature, + test_accepted_feature, + test_removed_feature, test_runner, thread_local, + tool_attributes, + tool_lints, + trace_macros, + trait_alias, + transmute, + transparent, + trivial_bounds, + Try, + try_blocks, + tuple_indexing, + ty, + type_alias_enum_variants, + type_ascription, type_length_limit, + type_macros, + u128, + u16, + u32, + u64, + u8, + unboxed_closures, + underscore_const_names, + underscore_imports, + underscore_lifetimes, + uniform_paths, + universal_impl_trait, + unmarked_api, + unrestricted_attribute_tokens, unsafe_destructor_blind_to_params, + unsafe_no_drop_flag, + unsized_locals, + unsized_tuple_coercion, unstable, + untagged_unions, unwind, + unwind_attributes, used, + use_extern_macros, + use_nested_groups, + usize, + v1, + vis, + visible_private_types, + volatile, warn, + warn_directory_ownership, + wasm_import_module, + wasm_target_feature, + while_let, + windows, windows_subsystem, + Yield, } } From 79602c87b561e26fa1a8fe58b9130cca37375f90 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 10 May 2019 09:57:08 +1000 Subject: [PATCH 205/212] Rename `syntax::symbol::symbols` as `syntax::symbol::sym`. Because it's going to be used a lot. --- src/librustc/middle/lib_features.rs | 4 +- src/libsyntax/feature_gate.rs | 264 ++++++++++++++-------------- src/libsyntax_pos/lib.rs | 2 +- src/libsyntax_pos/symbol.rs | 7 +- 4 files changed, 139 insertions(+), 138 deletions(-) diff --git a/src/librustc/middle/lib_features.rs b/src/librustc/middle/lib_features.rs index e79ef8bfc6fb4..5acd48c77d820 100644 --- a/src/librustc/middle/lib_features.rs +++ b/src/librustc/middle/lib_features.rs @@ -8,7 +8,7 @@ use crate::ty::TyCtxt; use crate::hir::intravisit::{self, NestedVisitorMap, Visitor}; use syntax::symbol::Symbol; use syntax::ast::{Attribute, MetaItem, MetaItemKind}; -use syntax_pos::{Span, symbols}; +use syntax_pos::{Span, sym}; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use rustc_macros::HashStable; use errors::DiagnosticId; @@ -51,7 +51,7 @@ impl<'a, 'tcx> LibFeatureCollector<'a, 'tcx> { } fn extract(&self, attr: &Attribute) -> Option<(Symbol, Option, Span)> { - let stab_attrs = [symbols::stable, symbols::unstable, symbols::rustc_const_unstable]; + let stab_attrs = [sym::stable, sym::unstable, sym::rustc_const_unstable]; // Find a stability attribute (i.e., `#[stable (..)]`, `#[unstable (..)]`, // `#[rustc_const_unstable (..)]`). diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index c3bad3aba184b..c4977f9240238 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -28,7 +28,7 @@ use crate::tokenstream::TokenTree; use errors::{DiagnosticBuilder, Handler}; use rustc_data_structures::fx::FxHashMap; use rustc_target::spec::abi::Abi; -use syntax_pos::{Span, DUMMY_SP, symbols}; +use syntax_pos::{Span, DUMMY_SP, sym}; use log::debug; use lazy_static::lazy_static; @@ -962,108 +962,108 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Normal attributes ( - symbols::warn, + sym::warn, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), Ungated ), ( - symbols::allow, + sym::allow, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), Ungated ), ( - symbols::forbid, + sym::forbid, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), Ungated ), ( - symbols::deny, + sym::deny, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), Ungated ), - (symbols::macro_use, Normal, template!(Word, List: "name1, name2, ..."), Ungated), - (symbols::macro_export, Normal, template!(Word, List: "local_inner_macros"), Ungated), - (symbols::plugin_registrar, Normal, template!(Word), Ungated), - - (symbols::cfg, Normal, template!(List: "predicate"), Ungated), - (symbols::cfg_attr, Normal, template!(List: "predicate, attr1, attr2, ..."), Ungated), - (symbols::main, Normal, template!(Word), Ungated), - (symbols::start, Normal, template!(Word), Ungated), - (symbols::repr, Normal, template!(List: "C, packed, ..."), Ungated), - (symbols::path, Normal, template!(NameValueStr: "file"), Ungated), - (symbols::automatically_derived, Normal, template!(Word), Ungated), - (symbols::no_mangle, Normal, template!(Word), Ungated), - (symbols::no_link, Normal, template!(Word), Ungated), - (symbols::derive, Normal, template!(List: "Trait1, Trait2, ..."), Ungated), + (sym::macro_use, Normal, template!(Word, List: "name1, name2, ..."), Ungated), + (sym::macro_export, Normal, template!(Word, List: "local_inner_macros"), Ungated), + (sym::plugin_registrar, Normal, template!(Word), Ungated), + + (sym::cfg, Normal, template!(List: "predicate"), Ungated), + (sym::cfg_attr, Normal, template!(List: "predicate, attr1, attr2, ..."), Ungated), + (sym::main, Normal, template!(Word), Ungated), + (sym::start, Normal, template!(Word), Ungated), + (sym::repr, Normal, template!(List: "C, packed, ..."), Ungated), + (sym::path, Normal, template!(NameValueStr: "file"), Ungated), + (sym::automatically_derived, Normal, template!(Word), Ungated), + (sym::no_mangle, Normal, template!(Word), Ungated), + (sym::no_link, Normal, template!(Word), Ungated), + (sym::derive, Normal, template!(List: "Trait1, Trait2, ..."), Ungated), ( - symbols::should_panic, + sym::should_panic, Normal, template!(Word, List: r#"expected = "reason"#, NameValueStr: "reason"), Ungated ), - (symbols::ignore, Normal, template!(Word, NameValueStr: "reason"), Ungated), - (symbols::no_implicit_prelude, Normal, template!(Word), Ungated), - (symbols::reexport_test_harness_main, Normal, template!(NameValueStr: "name"), Ungated), - (symbols::link_args, Normal, template!(NameValueStr: "args"), Gated(Stability::Unstable, + (sym::ignore, Normal, template!(Word, NameValueStr: "reason"), Ungated), + (sym::no_implicit_prelude, Normal, template!(Word), Ungated), + (sym::reexport_test_harness_main, Normal, template!(NameValueStr: "name"), Ungated), + (sym::link_args, Normal, template!(NameValueStr: "args"), Gated(Stability::Unstable, "link_args", "the `link_args` attribute is experimental and not \ portable across platforms, it is recommended to \ use `#[link(name = \"foo\")] instead", cfg_fn!(link_args))), - (symbols::macro_escape, Normal, template!(Word), Ungated), + (sym::macro_escape, Normal, template!(Word), Ungated), // RFC #1445. - (symbols::structural_match, Whitelisted, template!(Word), Gated(Stability::Unstable, + (sym::structural_match, Whitelisted, template!(Word), Gated(Stability::Unstable, "structural_match", "the semantics of constant patterns is \ not yet settled", cfg_fn!(structural_match))), // RFC #2008 - (symbols::non_exhaustive, Whitelisted, template!(Word), Gated(Stability::Unstable, + (sym::non_exhaustive, Whitelisted, template!(Word), Gated(Stability::Unstable, "non_exhaustive", "non exhaustive is an experimental feature", cfg_fn!(non_exhaustive))), // RFC #1268 - (symbols::marker, Normal, template!(Word), Gated(Stability::Unstable, + (sym::marker, Normal, template!(Word), Gated(Stability::Unstable, "marker_trait_attr", "marker traits is an experimental feature", cfg_fn!(marker_trait_attr))), - (symbols::plugin, CrateLevel, template!(List: "name|name(args)"), Gated(Stability::Unstable, + (sym::plugin, CrateLevel, template!(List: "name|name(args)"), Gated(Stability::Unstable, "plugin", "compiler plugins are experimental \ and possibly buggy", cfg_fn!(plugin))), - (symbols::no_std, CrateLevel, template!(Word), Ungated), - (symbols::no_core, CrateLevel, template!(Word), Gated(Stability::Unstable, + (sym::no_std, CrateLevel, template!(Word), Ungated), + (sym::no_core, CrateLevel, template!(Word), Gated(Stability::Unstable, "no_core", "no_core is experimental", cfg_fn!(no_core))), - (symbols::lang, Normal, template!(NameValueStr: "name"), Gated(Stability::Unstable, + (sym::lang, Normal, template!(NameValueStr: "name"), Gated(Stability::Unstable, "lang_items", "language items are subject to change", cfg_fn!(lang_items))), - (symbols::linkage, Whitelisted, template!(NameValueStr: "external|internal|..."), + (sym::linkage, Whitelisted, template!(NameValueStr: "external|internal|..."), Gated(Stability::Unstable, "linkage", "the `linkage` attribute is experimental \ and not portable across platforms", cfg_fn!(linkage))), - (symbols::thread_local, Whitelisted, template!(Word), Gated(Stability::Unstable, + (sym::thread_local, Whitelisted, template!(Word), Gated(Stability::Unstable, "thread_local", "`#[thread_local]` is an experimental feature, and does \ not currently handle destructors", cfg_fn!(thread_local))), - (symbols::rustc_on_unimplemented, Whitelisted, template!(List: + (sym::rustc_on_unimplemented, Whitelisted, template!(List: r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#, NameValueStr: "message"), Gated(Stability::Unstable, @@ -1071,101 +1071,101 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ "the `#[rustc_on_unimplemented]` attribute \ is an experimental feature", cfg_fn!(on_unimplemented))), - (symbols::rustc_const_unstable, Normal, template!(List: r#"feature = "name""#), + (sym::rustc_const_unstable, Normal, template!(List: r#"feature = "name""#), Gated(Stability::Unstable, "rustc_const_unstable", "the `#[rustc_const_unstable]` attribute \ is an internal feature", cfg_fn!(rustc_const_unstable))), - (symbols::global_allocator, Normal, template!(Word), Ungated), - (symbols::default_lib_allocator, Whitelisted, template!(Word), Gated(Stability::Unstable, + (sym::global_allocator, Normal, template!(Word), Ungated), + (sym::default_lib_allocator, Whitelisted, template!(Word), Gated(Stability::Unstable, "allocator_internals", "the `#[default_lib_allocator]` \ attribute is an experimental feature", cfg_fn!(allocator_internals))), - (symbols::needs_allocator, Normal, template!(Word), Gated(Stability::Unstable, + (sym::needs_allocator, Normal, template!(Word), Gated(Stability::Unstable, "allocator_internals", "the `#[needs_allocator]` \ attribute is an experimental \ feature", cfg_fn!(allocator_internals))), - (symbols::panic_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, + (sym::panic_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, "panic_runtime", "the `#[panic_runtime]` attribute is \ an experimental feature", cfg_fn!(panic_runtime))), - (symbols::needs_panic_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, + (sym::needs_panic_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, "needs_panic_runtime", "the `#[needs_panic_runtime]` \ attribute is an experimental \ feature", cfg_fn!(needs_panic_runtime))), - (symbols::rustc_outlives, Normal, template!(Word), Gated(Stability::Unstable, + (sym::rustc_outlives, Normal, template!(Word), Gated(Stability::Unstable, "rustc_attrs", "the `#[rustc_outlives]` attribute \ is just used for rustc unit tests \ and will never be stable", cfg_fn!(rustc_attrs))), - (symbols::rustc_variance, Normal, template!(Word), Gated(Stability::Unstable, + (sym::rustc_variance, Normal, template!(Word), Gated(Stability::Unstable, "rustc_attrs", "the `#[rustc_variance]` attribute \ is just used for rustc unit tests \ and will never be stable", cfg_fn!(rustc_attrs))), - (symbols::rustc_layout, Normal, template!(List: "field1, field2, ..."), + (sym::rustc_layout, Normal, template!(List: "field1, field2, ..."), Gated(Stability::Unstable, "rustc_attrs", "the `#[rustc_layout]` attribute \ is just used for rustc unit tests \ and will never be stable", cfg_fn!(rustc_attrs))), - (symbols::rustc_layout_scalar_valid_range_start, Whitelisted, template!(List: "value"), + (sym::rustc_layout_scalar_valid_range_start, Whitelisted, template!(List: "value"), Gated(Stability::Unstable, "rustc_attrs", "the `#[rustc_layout_scalar_valid_range_start]` attribute \ is just used to enable niche optimizations in libcore \ and will never be stable", cfg_fn!(rustc_attrs))), - (symbols::rustc_layout_scalar_valid_range_end, Whitelisted, template!(List: "value"), + (sym::rustc_layout_scalar_valid_range_end, Whitelisted, template!(List: "value"), Gated(Stability::Unstable, "rustc_attrs", "the `#[rustc_layout_scalar_valid_range_end]` attribute \ is just used to enable niche optimizations in libcore \ and will never be stable", cfg_fn!(rustc_attrs))), - (symbols::rustc_regions, Normal, template!(Word), Gated(Stability::Unstable, + (sym::rustc_regions, Normal, template!(Word), Gated(Stability::Unstable, "rustc_attrs", "the `#[rustc_regions]` attribute \ is just used for rustc unit tests \ and will never be stable", cfg_fn!(rustc_attrs))), - (symbols::rustc_error, Whitelisted, template!(Word), Gated(Stability::Unstable, + (sym::rustc_error, Whitelisted, template!(Word), Gated(Stability::Unstable, "rustc_attrs", "the `#[rustc_error]` attribute \ is just used for rustc unit tests \ and will never be stable", cfg_fn!(rustc_attrs))), - (symbols::rustc_dump_user_substs, Whitelisted, template!(Word), Gated(Stability::Unstable, + (sym::rustc_dump_user_substs, Whitelisted, template!(Word), Gated(Stability::Unstable, "rustc_attrs", "this attribute \ is just used for rustc unit tests \ and will never be stable", cfg_fn!(rustc_attrs))), - (symbols::rustc_if_this_changed, Whitelisted, template!(Word, List: "DepNode"), + (sym::rustc_if_this_changed, Whitelisted, template!(Word, List: "DepNode"), Gated(Stability::Unstable, "rustc_attrs", "the `#[rustc_if_this_changed]` attribute \ is just used for rustc unit tests \ and will never be stable", cfg_fn!(rustc_attrs))), - (symbols::rustc_then_this_would_need, Whitelisted, template!(List: "DepNode"), + (sym::rustc_then_this_would_need, Whitelisted, template!(List: "DepNode"), Gated(Stability::Unstable, "rustc_attrs", "the `#[rustc_if_this_changed]` attribute \ is just used for rustc unit tests \ and will never be stable", cfg_fn!(rustc_attrs))), - (symbols::rustc_dirty, Whitelisted, template!(List: r#"cfg = "...", /*opt*/ label = "...", + (sym::rustc_dirty, Whitelisted, template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#), Gated(Stability::Unstable, "rustc_attrs", @@ -1173,7 +1173,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ is just used for rustc unit tests \ and will never be stable", cfg_fn!(rustc_attrs))), - (symbols::rustc_clean, Whitelisted, template!(List: r#"cfg = "...", /*opt*/ label = "...", + (sym::rustc_clean, Whitelisted, template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#), Gated(Stability::Unstable, "rustc_attrs", @@ -1182,7 +1182,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ and will never be stable", cfg_fn!(rustc_attrs))), ( - symbols::rustc_partition_reused, + sym::rustc_partition_reused, Whitelisted, template!(List: r#"cfg = "...", module = "...""#), Gated( @@ -1195,7 +1195,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ) ), ( - symbols::rustc_partition_codegened, + sym::rustc_partition_codegened, Whitelisted, template!(List: r#"cfg = "...", module = "...""#), Gated( @@ -1207,7 +1207,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ cfg_fn!(rustc_attrs), ) ), - (symbols::rustc_expected_cgu_reuse, Whitelisted, template!(List: r#"cfg = "...", module = "...", + (sym::rustc_expected_cgu_reuse, Whitelisted, template!(List: r#"cfg = "...", module = "...", kind = "...""#), Gated(Stability::Unstable, "rustc_attrs", @@ -1215,28 +1215,28 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ is just used for rustc unit tests \ and will never be stable", cfg_fn!(rustc_attrs))), - (symbols::rustc_synthetic, Whitelisted, template!(Word), Gated(Stability::Unstable, + (sym::rustc_synthetic, Whitelisted, template!(Word), Gated(Stability::Unstable, "rustc_attrs", "this attribute \ is just used for rustc unit tests \ and will never be stable", cfg_fn!(rustc_attrs))), - (symbols::rustc_symbol_name, Whitelisted, template!(Word), Gated(Stability::Unstable, + (sym::rustc_symbol_name, Whitelisted, template!(Word), Gated(Stability::Unstable, "rustc_attrs", "internal rustc attributes will never be stable", cfg_fn!(rustc_attrs))), - (symbols::rustc_def_path, Whitelisted, template!(Word), Gated(Stability::Unstable, + (sym::rustc_def_path, Whitelisted, template!(Word), Gated(Stability::Unstable, "rustc_attrs", "internal rustc attributes will never be stable", cfg_fn!(rustc_attrs))), - (symbols::rustc_mir, Whitelisted, template!(List: "arg1, arg2, ..."), Gated(Stability::Unstable, + (sym::rustc_mir, Whitelisted, template!(List: "arg1, arg2, ..."), Gated(Stability::Unstable, "rustc_attrs", "the `#[rustc_mir]` attribute \ is just used for rustc unit tests \ and will never be stable", cfg_fn!(rustc_attrs))), ( - symbols::rustc_inherit_overflow_checks, + sym::rustc_inherit_overflow_checks, Whitelisted, template!(Word), Gated( @@ -1251,35 +1251,35 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ) ), - (symbols::rustc_dump_program_clauses, Whitelisted, template!(Word), Gated(Stability::Unstable, + (sym::rustc_dump_program_clauses, Whitelisted, template!(Word), Gated(Stability::Unstable, "rustc_attrs", "the `#[rustc_dump_program_clauses]` \ attribute is just used for rustc unit \ tests and will never be stable", cfg_fn!(rustc_attrs))), - (symbols::rustc_test_marker, Normal, template!(Word), Gated(Stability::Unstable, + (sym::rustc_test_marker, Normal, template!(Word), Gated(Stability::Unstable, "rustc_attrs", "the `#[rustc_test_marker]` attribute \ is used internally to track tests", cfg_fn!(rustc_attrs))), - (symbols::rustc_transparent_macro, Whitelisted, template!(Word), Gated(Stability::Unstable, + (sym::rustc_transparent_macro, Whitelisted, template!(Word), Gated(Stability::Unstable, "rustc_attrs", "used internally for testing macro hygiene", cfg_fn!(rustc_attrs))), - (symbols::compiler_builtins, Whitelisted, template!(Word), Gated(Stability::Unstable, + (sym::compiler_builtins, Whitelisted, template!(Word), Gated(Stability::Unstable, "compiler_builtins", "the `#[compiler_builtins]` attribute is used to \ identify the `compiler_builtins` crate which \ contains compiler-rt intrinsics and will never be \ stable", cfg_fn!(compiler_builtins))), - (symbols::sanitizer_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, + (sym::sanitizer_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, "sanitizer_runtime", "the `#[sanitizer_runtime]` attribute is used to \ identify crates that contain the runtime of a \ sanitizer and will never be stable", cfg_fn!(sanitizer_runtime))), - (symbols::profiler_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, + (sym::profiler_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, "profiler_runtime", "the `#[profiler_runtime]` attribute is used to \ identify the `profiler_builtins` crate which \ @@ -1287,35 +1287,35 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ stable", cfg_fn!(profiler_runtime))), - (symbols::allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), + (sym::allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), Gated(Stability::Unstable, "allow_internal_unstable", EXPLAIN_ALLOW_INTERNAL_UNSTABLE, cfg_fn!(allow_internal_unstable))), - (symbols::allow_internal_unsafe, Normal, template!(Word), Gated(Stability::Unstable, + (sym::allow_internal_unsafe, Normal, template!(Word), Gated(Stability::Unstable, "allow_internal_unsafe", EXPLAIN_ALLOW_INTERNAL_UNSAFE, cfg_fn!(allow_internal_unsafe))), - (symbols::fundamental, Whitelisted, template!(Word), Gated(Stability::Unstable, + (sym::fundamental, Whitelisted, template!(Word), Gated(Stability::Unstable, "fundamental", "the `#[fundamental]` attribute \ is an experimental feature", cfg_fn!(fundamental))), - (symbols::proc_macro_derive, Normal, template!(List: "TraitName, \ + (sym::proc_macro_derive, Normal, template!(List: "TraitName, \ /*opt*/ attributes(name1, name2, ...)"), Ungated), - (symbols::rustc_copy_clone_marker, Whitelisted, template!(Word), Gated(Stability::Unstable, + (sym::rustc_copy_clone_marker, Whitelisted, template!(Word), Gated(Stability::Unstable, "rustc_attrs", "internal implementation detail", cfg_fn!(rustc_attrs))), // FIXME: #14408 whitelist docs since rustdoc looks at them ( - symbols::doc, + sym::doc, Whitelisted, template!(List: "hidden|inline|...", NameValueStr: "string"), Ungated @@ -1323,33 +1323,33 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // FIXME: #14406 these are processed in codegen, which happens after the // lint pass - (symbols::cold, Whitelisted, template!(Word), Ungated), - (symbols::naked, Whitelisted, template!(Word), Gated(Stability::Unstable, + (sym::cold, Whitelisted, template!(Word), Ungated), + (sym::naked, Whitelisted, template!(Word), Gated(Stability::Unstable, "naked_functions", "the `#[naked]` attribute \ is an experimental feature", cfg_fn!(naked_functions))), - (symbols::ffi_returns_twice, Whitelisted, template!(Word), Gated(Stability::Unstable, + (sym::ffi_returns_twice, Whitelisted, template!(Word), Gated(Stability::Unstable, "ffi_returns_twice", "the `#[ffi_returns_twice]` attribute \ is an experimental feature", cfg_fn!(ffi_returns_twice))), - (symbols::target_feature, Whitelisted, template!(List: r#"enable = "name""#), Ungated), - (symbols::export_name, Whitelisted, template!(NameValueStr: "name"), Ungated), - (symbols::inline, Whitelisted, template!(Word, List: "always|never"), Ungated), - (symbols::link, Whitelisted, template!(List: r#"name = "...", /*opt*/ kind = "dylib|static|...", + (sym::target_feature, Whitelisted, template!(List: r#"enable = "name""#), Ungated), + (sym::export_name, Whitelisted, template!(NameValueStr: "name"), Ungated), + (sym::inline, Whitelisted, template!(Word, List: "always|never"), Ungated), + (sym::link, Whitelisted, template!(List: r#"name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ cfg = "...""#), Ungated), - (symbols::link_name, Whitelisted, template!(NameValueStr: "name"), Ungated), - (symbols::link_section, Whitelisted, template!(NameValueStr: "name"), Ungated), - (symbols::no_builtins, Whitelisted, template!(Word), Ungated), - (symbols::no_debug, Whitelisted, template!(Word), Gated( + (sym::link_name, Whitelisted, template!(NameValueStr: "name"), Ungated), + (sym::link_section, Whitelisted, template!(NameValueStr: "name"), Ungated), + (sym::no_builtins, Whitelisted, template!(Word), Ungated), + (sym::no_debug, Whitelisted, template!(Word), Gated( Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721", None), "no_debug", "the `#[no_debug]` attribute was an experimental feature that has been \ deprecated due to lack of demand", cfg_fn!(no_debug))), ( - symbols::omit_gdb_pretty_printer_section, + sym::omit_gdb_pretty_printer_section, Whitelisted, template!(Word), Gated( @@ -1361,7 +1361,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ cfg_fn!(omit_gdb_pretty_printer_section) ) ), - (symbols::unsafe_destructor_blind_to_params, + (sym::unsafe_destructor_blind_to_params, Normal, template!(Word), Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761", @@ -1370,21 +1370,21 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ "unsafe_destructor_blind_to_params has been replaced by \ may_dangle and will be removed in the future", cfg_fn!(dropck_parametricity))), - (symbols::may_dangle, + (sym::may_dangle, Normal, template!(Word), Gated(Stability::Unstable, "dropck_eyepatch", "may_dangle has unstable semantics and may be removed in the future", cfg_fn!(dropck_eyepatch))), - (symbols::unwind, Whitelisted, template!(List: "allowed|aborts"), Gated(Stability::Unstable, + (sym::unwind, Whitelisted, template!(List: "allowed|aborts"), Gated(Stability::Unstable, "unwind_attributes", "#[unwind] is experimental", cfg_fn!(unwind_attributes))), - (symbols::used, Whitelisted, template!(Word), Ungated), + (sym::used, Whitelisted, template!(Word), Ungated), // used in resolve - (symbols::prelude_import, Whitelisted, template!(Word), Gated(Stability::Unstable, + (sym::prelude_import, Whitelisted, template!(Word), Gated(Stability::Unstable, "prelude_import", "`#[prelude_import]` is for use by rustc only", cfg_fn!(prelude_import))), @@ -1392,25 +1392,25 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // FIXME: #14407 these are only looked at on-demand so we can't // guarantee they'll have already been checked ( - symbols::rustc_deprecated, + sym::rustc_deprecated, Whitelisted, template!(List: r#"since = "version", reason = "...""#), Ungated ), - (symbols::must_use, Whitelisted, template!(Word, NameValueStr: "reason"), Ungated), + (sym::must_use, Whitelisted, template!(Word, NameValueStr: "reason"), Ungated), ( - symbols::stable, + sym::stable, Whitelisted, template!(List: r#"feature = "name", since = "version""#), Ungated ), ( - symbols::unstable, + sym::unstable, Whitelisted, template!(List: r#"feature = "name", reason = "...", issue = "N""#), Ungated ), - (symbols::deprecated, + (sym::deprecated, Normal, template!( Word, @@ -1420,69 +1420,69 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ Ungated ), - (symbols::rustc_paren_sugar, Normal, template!(Word), Gated(Stability::Unstable, + (sym::rustc_paren_sugar, Normal, template!(Word), Gated(Stability::Unstable, "unboxed_closures", "unboxed_closures are still evolving", cfg_fn!(unboxed_closures))), - (symbols::windows_subsystem, Whitelisted, template!(NameValueStr: "windows|console"), Ungated), + (sym::windows_subsystem, Whitelisted, template!(NameValueStr: "windows|console"), Ungated), - (symbols::proc_macro_attribute, Normal, template!(Word), Ungated), - (symbols::proc_macro, Normal, template!(Word), Ungated), + (sym::proc_macro_attribute, Normal, template!(Word), Ungated), + (sym::proc_macro, Normal, template!(Word), Ungated), - (symbols::rustc_proc_macro_decls, Normal, template!(Word), Gated(Stability::Unstable, + (sym::rustc_proc_macro_decls, Normal, template!(Word), Gated(Stability::Unstable, "rustc_attrs", "used internally by rustc", cfg_fn!(rustc_attrs))), - (symbols::allow_fail, Normal, template!(Word), Gated(Stability::Unstable, + (sym::allow_fail, Normal, template!(Word), Gated(Stability::Unstable, "allow_fail", "allow_fail attribute is currently unstable", cfg_fn!(allow_fail))), - (symbols::rustc_std_internal_symbol, Whitelisted, template!(Word), Gated(Stability::Unstable, + (sym::rustc_std_internal_symbol, Whitelisted, template!(Word), Gated(Stability::Unstable, "rustc_attrs", "this is an internal attribute that will \ never be stable", cfg_fn!(rustc_attrs))), // whitelists "identity-like" conversion methods to suggest on type mismatch - (symbols::rustc_conversion_suggestion, Whitelisted, template!(Word), Gated(Stability::Unstable, + (sym::rustc_conversion_suggestion, Whitelisted, template!(Word), Gated(Stability::Unstable, "rustc_attrs", "this is an internal attribute that will \ never be stable", cfg_fn!(rustc_attrs))), ( - symbols::rustc_args_required_const, + sym::rustc_args_required_const, Whitelisted, template!(List: "N"), Gated(Stability::Unstable, "rustc_attrs", "never will be stable", cfg_fn!(rustc_attrs)) ), // RFC 2070 - (symbols::panic_handler, Normal, template!(Word), Ungated), + (sym::panic_handler, Normal, template!(Word), Ungated), - (symbols::alloc_error_handler, Normal, template!(Word), Gated(Stability::Unstable, + (sym::alloc_error_handler, Normal, template!(Word), Gated(Stability::Unstable, "alloc_error_handler", "#[alloc_error_handler] is an unstable feature", cfg_fn!(alloc_error_handler))), // RFC 2412 - (symbols::optimize, Whitelisted, template!(List: "size|speed"), Gated(Stability::Unstable, + (sym::optimize, Whitelisted, template!(List: "size|speed"), Gated(Stability::Unstable, "optimize_attribute", "#[optimize] attribute is an unstable feature", cfg_fn!(optimize_attribute))), // Crate level attributes - (symbols::crate_name, CrateLevel, template!(NameValueStr: "name"), Ungated), - (symbols::crate_type, CrateLevel, template!(NameValueStr: "bin|lib|..."), Ungated), - (symbols::crate_id, CrateLevel, template!(NameValueStr: "ignored"), Ungated), - (symbols::feature, CrateLevel, template!(List: "name1, name1, ..."), Ungated), - (symbols::no_start, CrateLevel, template!(Word), Ungated), - (symbols::no_main, CrateLevel, template!(Word), Ungated), - (symbols::recursion_limit, CrateLevel, template!(NameValueStr: "N"), Ungated), - (symbols::type_length_limit, CrateLevel, template!(NameValueStr: "N"), Ungated), - (symbols::test_runner, CrateLevel, template!(List: "path"), Gated(Stability::Unstable, + (sym::crate_name, CrateLevel, template!(NameValueStr: "name"), Ungated), + (sym::crate_type, CrateLevel, template!(NameValueStr: "bin|lib|..."), Ungated), + (sym::crate_id, CrateLevel, template!(NameValueStr: "ignored"), Ungated), + (sym::feature, CrateLevel, template!(List: "name1, name1, ..."), Ungated), + (sym::no_start, CrateLevel, template!(Word), Ungated), + (sym::no_main, CrateLevel, template!(Word), Ungated), + (sym::recursion_limit, CrateLevel, template!(NameValueStr: "N"), Ungated), + (sym::type_length_limit, CrateLevel, template!(NameValueStr: "N"), Ungated), + (sym::test_runner, CrateLevel, template!(List: "path"), Gated(Stability::Unstable, "custom_test_frameworks", EXPLAIN_CUSTOM_TEST_FRAMEWORKS, cfg_fn!(custom_test_frameworks))), @@ -1582,9 +1582,9 @@ impl<'a> Context<'a> { self, has_feature, attr.span, name, desc, GateStrength::Hard ); } - } else if name == symbols::doc { + } else if name == sym::doc { if let Some(content) = attr.meta_item_list() { - if content.iter().any(|c| c.check_name(symbols::include)) { + if content.iter().any(|c| c.check_name(sym::include)) { gate_feature!(self, external_doc, attr.span, "#[doc(include = \"...\")] is experimental" ); @@ -1841,11 +1841,11 @@ impl<'a> PostExpansionVisitor<'a> { template: AttributeTemplate) { // Some special attributes like `cfg` must be checked // before the generic check, so we skip them here. - let should_skip = |name| name == symbols::cfg; + let should_skip = |name| name == sym::cfg; // Some of previously accepted forms were used in practice, // report them as warnings for now. - let should_warn = |name| name == symbols::doc || name == symbols::ignore || - name == symbols::inline || name == symbols::link; + let should_warn = |name| name == sym::doc || name == sym::ignore || + name == sym::inline || name == sym::link; match attr.parse_meta(self.context.parse_sess) { Ok(meta) => if !should_skip(name) && !template.compatible(&meta.node) { @@ -1893,25 +1893,25 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { // check for gated attributes self.context.check_attribute(attr, attr_info, false); - if attr.check_name(symbols::doc) { + if attr.check_name(sym::doc) { if let Some(content) = attr.meta_item_list() { - if content.len() == 1 && content[0].check_name(symbols::cfg) { + if content.len() == 1 && content[0].check_name(sym::cfg) { gate_feature_post!(&self, doc_cfg, attr.span, "#[doc(cfg(...))] is experimental" ); - } else if content.iter().any(|c| c.check_name(symbols::masked)) { + } else if content.iter().any(|c| c.check_name(sym::masked)) { gate_feature_post!(&self, doc_masked, attr.span, "#[doc(masked)] is experimental" ); - } else if content.iter().any(|c| c.check_name(symbols::spotlight)) { + } else if content.iter().any(|c| c.check_name(sym::spotlight)) { gate_feature_post!(&self, doc_spotlight, attr.span, "#[doc(spotlight)] is experimental" ); - } else if content.iter().any(|c| c.check_name(symbols::alias)) { + } else if content.iter().any(|c| c.check_name(sym::alias)) { gate_feature_post!(&self, doc_alias, attr.span, "#[doc(alias = \"...\")] is experimental" ); - } else if content.iter().any(|c| c.check_name(symbols::keyword)) { + } else if content.iter().any(|c| c.check_name(sym::keyword)) { gate_feature_post!(&self, doc_keyword, attr.span, "#[doc(keyword = \"...\")] is experimental" ); @@ -1978,7 +1978,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::ItemKind::Struct(..) => { for attr in attr::filter_by_name(&i.attrs[..], "repr") { for item in attr.meta_item_list().unwrap_or_else(Vec::new) { - if item.check_name(symbols::simd) { + if item.check_name(sym::simd) { gate_feature_post!(&self, repr_simd, attr.span, "SIMD types are experimental and possibly buggy"); } @@ -1989,7 +1989,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::ItemKind::Enum(..) => { for attr in attr::filter_by_name(&i.attrs[..], "repr") { for item in attr.meta_item_list().unwrap_or_else(Vec::new) { - if item.check_name(symbols::align) { + if item.check_name(sym::align) { gate_feature_post!(&self, repr_align_enum, attr.span, "`#[repr(align(x))]` on enums is experimental"); } @@ -2319,7 +2319,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], // Process the edition umbrella feature-gates first, to ensure // `edition_enabled_features` is completed before it's queried. for attr in krate_attrs { - if !attr.check_name(symbols::feature) { + if !attr.check_name(sym::feature) { continue } @@ -2364,7 +2364,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], } for attr in krate_attrs { - if !attr.check_name(symbols::feature) { + if !attr.check_name(sym::feature) { continue } @@ -2496,7 +2496,7 @@ fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate, }; if !allow_features { for attr in &krate.attrs { - if attr.check_name(symbols::feature) { + if attr.check_name(sym::feature) { let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)"); span_err!(span_handler, attr.span, E0554, "#![feature] may not be used on the {} release channel", diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 3f09405a5c8c6..d690a39199625 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -33,7 +33,7 @@ mod span_encoding; pub use span_encoding::{Span, DUMMY_SP}; pub mod symbol; -pub use symbol::symbols; +pub use symbol::sym; mod analyze_source_file; diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 5459f3904fa7c..ac3f999c53794 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -99,8 +99,8 @@ symbols! { Union: "union", } - // Symbols that can be referred to with syntax_pos::symbols::*. The symbol - // is the stringified identifier unless otherwise specified (e.g. + // Symbols that can be referred to with syntax_pos::sym::*. The symbol is + // the stringified identifier unless otherwise specified (e.g. // `proc_dash_macro` represents "proc-macro"). Symbols { aarch64_target_feature, @@ -937,7 +937,8 @@ pub mod keywords { keywords!(); } -pub mod symbols { +// This module has a very short name because it's used a lot. +pub mod sym { use super::Symbol; symbols!(); } From fb084a48e2ca663de41b316dc6ece2dceb93e24e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 8 May 2019 13:21:18 +1000 Subject: [PATCH 206/212] Pass a `Symbol` to `check_name`, `emit_feature_err`, and related functions. --- src/librustc/hir/check_attr.rs | 21 +- src/librustc/hir/lowering.rs | 10 +- src/librustc/ich/hcx.rs | 2 +- src/librustc/ich/mod.rs | 20 +- src/librustc/lint/levels.rs | 4 +- src/librustc/middle/dead.rs | 9 +- src/librustc/middle/entry.rs | 7 +- src/librustc/middle/lang_items.rs | 8 +- src/librustc/middle/liveness.rs | 4 +- src/librustc/middle/mem_categorization.rs | 3 +- src/librustc/middle/recursion_limit.rs | 7 +- src/librustc/middle/resolve_lifetime.rs | 4 +- src/librustc/middle/stability.rs | 10 +- src/librustc/query/mod.rs | 2 +- src/librustc/session/mod.rs | 3 +- src/librustc/traits/coherence.rs | 9 +- src/librustc/traits/error_reporting.rs | 3 +- src/librustc/traits/on_unimplemented.rs | 11 +- src/librustc/ty/context.rs | 9 +- src/librustc/ty/mod.rs | 12 +- src/librustc/ty/util.rs | 3 +- src/librustc_allocator/expand.rs | 4 +- src/librustc_codegen_llvm/attributes.rs | 4 +- src/librustc_codegen_llvm/consts.rs | 3 +- src/librustc_codegen_llvm/debuginfo/gdb.rs | 4 +- src/librustc_codegen_llvm/llvm_util.rs | 135 +++++++------ src/librustc_codegen_ssa/back/write.rs | 6 +- src/librustc_codegen_ssa/mir/rvalue.rs | 6 +- src/librustc_codegen_utils/lib.rs | 3 +- src/librustc_codegen_utils/link.rs | 3 +- .../symbol_names_test.rs | 6 +- .../assert_module_sources.rs | 9 +- .../persist/dirty_clean.rs | 13 +- src/librustc_interface/passes.rs | 2 +- src/librustc_interface/proc_macro_decls.rs | 3 +- src/librustc_interface/util.rs | 4 +- src/librustc_lint/builtin.rs | 22 +- src/librustc_lint/nonstandard_style.rs | 7 +- src/librustc_lint/unused.rs | 8 +- src/librustc_metadata/creader.rs | 12 +- src/librustc_metadata/decoder.rs | 4 +- src/librustc_metadata/encoder.rs | 18 +- src/librustc_metadata/link_args.rs | 3 +- src/librustc_metadata/native_libs.rs | 16 +- .../borrow_check/error_reporting.rs | 3 +- src/librustc_mir/borrow_check/nll/mod.rs | 3 +- src/librustc_mir/dataflow/mod.rs | 11 +- src/librustc_mir/hair/cx/mod.rs | 4 +- src/librustc_mir/hair/pattern/mod.rs | 5 +- src/librustc_mir/interpret/cast.rs | 6 +- src/librustc_mir/transform/check_unsafety.rs | 4 +- src/librustc_mir/transform/qualify_consts.rs | 25 +-- src/librustc_mir/transform/rustc_peek.rs | 11 +- src/librustc_passes/ast_validation.rs | 8 +- src/librustc_passes/layout_test.rs | 3 +- src/librustc_passes/rvalue_promotion.rs | 3 +- src/librustc_plugin/build.rs | 4 +- src/librustc_plugin/load.rs | 3 +- src/librustc_plugin/registry.rs | 4 +- src/librustc_privacy/lib.rs | 7 +- src/librustc_resolve/build_reduced_graph.rs | 22 +- src/librustc_resolve/lib.rs | 8 +- src/librustc_resolve/macros.rs | 15 +- src/librustc_save_analysis/lib.rs | 6 +- src/librustc_traits/lowering/mod.rs | 5 +- src/librustc_typeck/astconv.rs | 3 +- src/librustc_typeck/check/coercion.rs | 3 +- src/librustc_typeck/check/demand.rs | 3 +- src/librustc_typeck/check/mod.rs | 8 +- src/librustc_typeck/check/wfcheck.rs | 3 +- src/librustc_typeck/check/writeback.rs | 5 +- src/librustc_typeck/collect.rs | 84 ++++---- src/librustc_typeck/outlives/mod.rs | 3 +- src/librustc_typeck/outlives/test.rs | 3 +- src/librustc_typeck/variance/test.rs | 3 +- src/librustdoc/clean/inline.rs | 3 +- src/librustdoc/clean/mod.rs | 59 +++--- src/librustdoc/core.rs | 3 +- src/librustdoc/html/render.rs | 11 +- .../passes/calculate_doc_coverage.rs | 3 +- src/librustdoc/passes/collect_trait_impls.rs | 5 +- src/librustdoc/passes/strip_hidden.rs | 3 +- src/librustdoc/test.rs | 16 +- src/librustdoc/visit_ast.rs | 26 +-- src/librustdoc/visit_lib.rs | 3 +- src/libsyntax/attr/builtin.rs | 18 +- src/libsyntax/attr/mod.rs | 25 +-- src/libsyntax/config.rs | 11 +- src/libsyntax/entry.rs | 5 +- src/libsyntax/ext/expand.rs | 30 +-- src/libsyntax/ext/source_util.rs | 4 +- src/libsyntax/ext/tt/macro_rules.rs | 12 +- src/libsyntax/feature_gate.rs | 191 +++++++++--------- src/libsyntax/parse/mod.rs | 6 +- src/libsyntax/parse/parser.rs | 6 +- src/libsyntax/std_inject.rs | 8 +- src/libsyntax/test.rs | 11 +- src/libsyntax_ext/asm.rs | 4 +- src/libsyntax_ext/concat_idents.rs | 4 +- src/libsyntax_ext/deriving/clone.rs | 4 +- src/libsyntax_ext/deriving/generic/mod.rs | 4 +- src/libsyntax_ext/format.rs | 6 +- src/libsyntax_ext/global_asm.rs | 4 +- src/libsyntax_ext/log_syntax.rs | 3 +- src/libsyntax_ext/proc_macro_decls.rs | 18 +- src/libsyntax_ext/test.rs | 12 +- src/libsyntax_ext/test_case.rs | 4 +- src/libsyntax_ext/trace_macros.rs | 4 +- src/libsyntax_pos/lib.rs | 4 +- .../auxiliary/custom-derive-plugin-attr.rs | 4 +- .../auxiliary/issue-40001-plugin.rs | 4 +- .../auxiliary/lint-for-crate.rs | 7 +- .../ui-fulldeps/auxiliary/attr-plugin-test.rs | 8 +- .../ui-fulldeps/auxiliary/lint-for-crate.rs | 3 +- 114 files changed, 670 insertions(+), 620 deletions(-) diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index 4c527f80d0f5d..23c8a671ec5b3 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -12,6 +12,7 @@ use crate::hir; use crate::hir::def_id::DefId; use crate::hir::intravisit::{self, Visitor, NestedVisitorMap}; use std::fmt::{self, Display}; +use syntax::symbol::sym; use syntax_pos::Span; #[derive(Copy, Clone, PartialEq)] @@ -95,18 +96,18 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { fn check_attributes(&self, item: &hir::Item, target: Target) { if target == Target::Fn || target == Target::Const { self.tcx.codegen_fn_attrs(self.tcx.hir().local_def_id_from_hir_id(item.hir_id)); - } else if let Some(a) = item.attrs.iter().find(|a| a.check_name("target_feature")) { + } else if let Some(a) = item.attrs.iter().find(|a| a.check_name(sym::target_feature)) { self.tcx.sess.struct_span_err(a.span, "attribute should be applied to a function") .span_label(item.span, "not a function") .emit(); } for attr in &item.attrs { - if attr.check_name("inline") { + if attr.check_name(sym::inline) { self.check_inline(attr, &item.span, target) - } else if attr.check_name("non_exhaustive") { + } else if attr.check_name(sym::non_exhaustive) { self.check_non_exhaustive(attr, item, target) - } else if attr.check_name("marker") { + } else if attr.check_name(sym::marker) { self.check_marker(attr, item, target) } } @@ -166,7 +167,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { // ``` let hints: Vec<_> = item.attrs .iter() - .filter(|attr| attr.check_name("repr")) + .filter(|attr| attr.check_name(sym::repr)) .filter_map(|attr| attr.meta_item_list()) .flatten() .collect(); @@ -268,10 +269,10 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { // When checking statements ignore expressions, they will be checked later if let hir::StmtKind::Local(ref l) = stmt.node { for attr in l.attrs.iter() { - if attr.check_name("inline") { + if attr.check_name(sym::inline) { self.check_inline(attr, &stmt.span, Target::Statement); } - if attr.check_name("repr") { + if attr.check_name(sym::repr) { self.emit_repr_error( attr.span, stmt.span, @@ -289,10 +290,10 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { _ => Target::Expression, }; for attr in expr.attrs.iter() { - if attr.check_name("inline") { + if attr.check_name(sym::inline) { self.check_inline(attr, &expr.span, target); } - if attr.check_name("repr") { + if attr.check_name(sym::repr) { self.emit_repr_error( attr.span, expr.span, @@ -305,7 +306,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { fn check_used(&self, item: &hir::Item, target: Target) { for attr in &item.attrs { - if attr.check_name("used") && target != Target::Static { + if attr.check_name(sym::used) && target != Target::Static { self.tcx.sess .span_err(attr.span, "attribute must be applied to a `static` variable"); } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 5b334b24e2f41..0d80a0874e63f 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -64,7 +64,7 @@ use syntax::ptr::P; use syntax::source_map::{respan, CompilerDesugaringKind, Spanned}; use syntax::source_map::CompilerDesugaringKind::IfTemporary; use syntax::std_inject; -use syntax::symbol::{keywords, Symbol}; +use syntax::symbol::{keywords, Symbol, sym}; use syntax::tokenstream::{TokenStream, TokenTree}; use syntax::parse::token::Token; use syntax::visit::{self, Visitor}; @@ -2727,7 +2727,7 @@ impl<'a> LoweringContext<'a> { self.lower_ty(x, ImplTraitContext::disallowed()) }), synthetic: param.attrs.iter() - .filter(|attr| attr.check_name("rustc_synthetic")) + .filter(|attr| attr.check_name(sym::rustc_synthetic)) .map(|_| hir::SyntheticTyParamKind::ImplTrait) .next(), }; @@ -2745,7 +2745,7 @@ impl<'a> LoweringContext<'a> { hir_id: self.lower_node_id(param.id), name, span: param.ident.span, - pure_wrt_drop: attr::contains_name(¶m.attrs, "may_dangle"), + pure_wrt_drop: attr::contains_name(¶m.attrs, sym::may_dangle), attrs: self.lower_attrs(¶m.attrs), bounds, kind, @@ -3773,8 +3773,8 @@ impl<'a> LoweringContext<'a> { let mut vis = self.lower_visibility(&i.vis, None); let attrs = self.lower_attrs(&i.attrs); if let ItemKind::MacroDef(ref def) = i.node { - if !def.legacy || attr::contains_name(&i.attrs, "macro_export") || - attr::contains_name(&i.attrs, "rustc_doc_only_macro") { + if !def.legacy || attr::contains_name(&i.attrs, sym::macro_export) || + attr::contains_name(&i.attrs, sym::rustc_doc_only_macro) { let body = self.lower_token_stream(def.stream()); let hir_id = self.lower_node_id(i.id); self.exported_macros.push(hir::MacroDef { diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index 6da2cb9ab57ea..8be610e8bf7af 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -28,7 +28,7 @@ use smallvec::SmallVec; fn compute_ignored_attr_names() -> FxHashSet { debug_assert!(ich::IGNORED_ATTRIBUTES.len() > 0); - ich::IGNORED_ATTRIBUTES.iter().map(|&s| Symbol::intern(s)).collect() + ich::IGNORED_ATTRIBUTES.iter().map(|&s| s).collect() } /// This is the context state available during incr. comp. hashing. It contains diff --git a/src/librustc/ich/mod.rs b/src/librustc/ich/mod.rs index b407b75e68c9a..f3fc7ec8fda15 100644 --- a/src/librustc/ich/mod.rs +++ b/src/librustc/ich/mod.rs @@ -4,6 +4,8 @@ crate use rustc_data_structures::fingerprint::Fingerprint; pub use self::caching_source_map_view::CachingSourceMapView; pub use self::hcx::{StableHashingContextProvider, StableHashingContext, NodeIdHashingMode, hash_stable_trait_impls}; +use syntax::symbol::{Symbol, sym}; + mod caching_source_map_view; mod hcx; @@ -12,16 +14,16 @@ mod impls_misc; mod impls_ty; mod impls_syntax; -pub const ATTR_DIRTY: &str = "rustc_dirty"; -pub const ATTR_CLEAN: &str = "rustc_clean"; -pub const ATTR_IF_THIS_CHANGED: &str = "rustc_if_this_changed"; -pub const ATTR_THEN_THIS_WOULD_NEED: &str = "rustc_then_this_would_need"; -pub const ATTR_PARTITION_REUSED: &str = "rustc_partition_reused"; -pub const ATTR_PARTITION_CODEGENED: &str = "rustc_partition_codegened"; -pub const ATTR_EXPECTED_CGU_REUSE: &str = "rustc_expected_cgu_reuse"; +pub const ATTR_DIRTY: Symbol = sym::rustc_dirty; +pub const ATTR_CLEAN: Symbol = sym::rustc_clean; +pub const ATTR_IF_THIS_CHANGED: Symbol = sym::rustc_if_this_changed; +pub const ATTR_THEN_THIS_WOULD_NEED: Symbol = sym::rustc_then_this_would_need; +pub const ATTR_PARTITION_REUSED: Symbol = sym::rustc_partition_reused; +pub const ATTR_PARTITION_CODEGENED: Symbol = sym::rustc_partition_codegened; +pub const ATTR_EXPECTED_CGU_REUSE: Symbol = sym::rustc_expected_cgu_reuse; -pub const IGNORED_ATTRIBUTES: &[&str] = &[ - "cfg", +pub const IGNORED_ATTRIBUTES: &[Symbol] = &[ + sym::cfg, ATTR_IF_THIS_CHANGED, ATTR_THEN_THIS_WOULD_NEED, ATTR_DIRTY, diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index 2e5bd8add0cdc..a69758e33baba 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -14,7 +14,7 @@ use syntax::ast; use syntax::attr; use syntax::feature_gate; use syntax::source_map::MultiSpan; -use syntax::symbol::Symbol; +use syntax::symbol::{Symbol, sym}; pub struct LintLevelSets { list: Vec, @@ -230,7 +230,7 @@ impl<'a> LintLevelsBuilder<'a> { if !self.sess.features_untracked().lint_reasons { feature_gate::emit_feature_err( &self.sess.parse_sess, - "lint_reasons", + sym::lint_reasons, item.span, feature_gate::GateIssue::Language, "lint reasons are experimental" diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index a0107ed0546dd..2a9928567f4dc 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -19,6 +19,7 @@ use rustc_data_structures::fx::FxHashMap; use syntax::{ast, source_map}; use syntax::attr; +use syntax::symbol::sym; use syntax_pos; // Any local node that may call something in its body block should be @@ -304,22 +305,22 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_, '_, '_>, id: hir::HirId, attrs: &[ast::Attribute]) -> bool { - if attr::contains_name(attrs, "lang") { + if attr::contains_name(attrs, sym::lang) { return true; } // Stable attribute for #[lang = "panic_impl"] - if attr::contains_name(attrs, "panic_handler") { + if attr::contains_name(attrs, sym::panic_handler) { return true; } // (To be) stable attribute for #[lang = "oom"] - if attr::contains_name(attrs, "alloc_error_handler") { + if attr::contains_name(attrs, sym::alloc_error_handler) { return true; } // Don't lint about global allocators - if attr::contains_name(attrs, "global_allocator") { + if attr::contains_name(attrs, sym::global_allocator) { return true; } diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs index df77033ebef3b..e2e76e69dc4ed 100644 --- a/src/librustc/middle/entry.rs +++ b/src/librustc/middle/entry.rs @@ -4,6 +4,7 @@ use crate::session::{config, Session}; use crate::session::config::EntryFnType; use syntax::attr; use syntax::entry::EntryPointType; +use syntax::symbol::sym; use syntax_pos::Span; use crate::hir::{HirId, Item, ItemKind, ImplItem, TraitItem}; use crate::hir::itemlikevisit::ItemLikeVisitor; @@ -58,7 +59,7 @@ fn entry_fn(tcx: TyCtxt<'_, '_, '_>, cnum: CrateNum) -> Option<(DefId, EntryFnTy } // If the user wants no main function at all, then stop here. - if attr::contains_name(&tcx.hir().krate().attrs, "no_main") { + if attr::contains_name(&tcx.hir().krate().attrs, sym::no_main) { return None; } @@ -81,9 +82,9 @@ fn entry_fn(tcx: TyCtxt<'_, '_, '_>, cnum: CrateNum) -> Option<(DefId, EntryFnTy fn entry_point_type(item: &Item, at_root: bool) -> EntryPointType { match item.node { ItemKind::Fn(..) => { - if attr::contains_name(&item.attrs, "start") { + if attr::contains_name(&item.attrs, sym::start) { EntryPointType::Start - } else if attr::contains_name(&item.attrs, "main") { + } else if attr::contains_name(&item.attrs, sym::main) { EntryPointType::MainAttr } else if item.ident.name == "main" { if at_root { diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 0e283ca6b1cf1..103580a598fcd 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -18,7 +18,7 @@ use crate::middle::weak_lang_items; use crate::util::nodemap::FxHashMap; use syntax::ast; -use syntax::symbol::Symbol; +use syntax::symbol::{Symbol, sym}; use syntax_pos::Span; use rustc_macros::HashStable; use crate::hir::itemlikevisit::ItemLikeVisitor; @@ -209,9 +209,9 @@ impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> { /// are also extracted out when found. pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> { attrs.iter().find_map(|attr| Some(match attr { - _ if attr.check_name("lang") => (attr.value_str()?, attr.span), - _ if attr.check_name("panic_handler") => (Symbol::intern("panic_impl"), attr.span), - _ if attr.check_name("alloc_error_handler") => (Symbol::intern("oom"), attr.span), + _ if attr.check_name(sym::lang) => (attr.value_str()?, attr.span), + _ if attr.check_name(sym::panic_handler) => (Symbol::intern("panic_impl"), attr.span), + _ if attr.check_name(sym::alloc_error_handler) => (Symbol::intern("oom"), attr.span), _ => return None, })) } diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index a142b220f31af..cb333b5b0cba2 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -112,7 +112,7 @@ use std::io; use std::rc::Rc; use syntax::ast::{self, NodeId}; use syntax::ptr::P; -use syntax::symbol::keywords; +use syntax::symbol::{keywords, sym}; use syntax_pos::Span; use crate::hir; @@ -362,7 +362,7 @@ fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>, if let FnKind::Method(..) = fk { let parent = ir.tcx.hir().get_parent_item(id); if let Some(Node::Item(i)) = ir.tcx.hir().find_by_hir_id(parent) { - if i.attrs.iter().any(|a| a.check_name("automatically_derived")) { + if i.attrs.iter().any(|a| a.check_name(sym::automatically_derived)) { return; } } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 85c7f43790336..c7f8cf684e6b1 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -72,6 +72,7 @@ use crate::hir::{MutImmutable, MutMutable, PatKind}; use crate::hir::pat_util::EnumerateAndAdjustIterator; use crate::hir; use syntax::ast::{self, Name}; +use syntax::symbol::sym; use syntax_pos::Span; use std::borrow::Cow; @@ -714,7 +715,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { // they also cannot be moved out of. let is_thread_local = self.tcx.get_attrs(def_id)[..] .iter() - .any(|attr| attr.check_name("thread_local")); + .any(|attr| attr.check_name(sym::thread_local)); let cat = if is_thread_local { let re = self.temporary_scope(hir_id.local_id); diff --git a/src/librustc/middle/recursion_limit.rs b/src/librustc/middle/recursion_limit.rs index ea077220e0be3..5f355d17072b8 100644 --- a/src/librustc/middle/recursion_limit.rs +++ b/src/librustc/middle/recursion_limit.rs @@ -7,15 +7,16 @@ use crate::session::Session; use syntax::ast; +use syntax::symbol::{Symbol, sym}; use rustc_data_structures::sync::Once; pub fn update_limits(sess: &Session, krate: &ast::Crate) { - update_limit(krate, &sess.recursion_limit, "recursion_limit", 64); - update_limit(krate, &sess.type_length_limit, "type_length_limit", 1048576); + update_limit(krate, &sess.recursion_limit, sym::recursion_limit, 64); + update_limit(krate, &sess.type_length_limit, sym::type_length_limit, 1048576); } -fn update_limit(krate: &ast::Crate, limit: &Once, name: &str, default: usize) { +fn update_limit(krate: &ast::Crate, limit: &Once, name: Symbol, default: usize) { for attr in &krate.attrs { if !attr.check_name(name) { continue; diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index d835d872d76d7..2402d0eefde48 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -23,7 +23,7 @@ use std::mem::replace; use syntax::ast; use syntax::attr; use syntax::ptr::P; -use syntax::symbol::keywords; +use syntax::symbol::{keywords, sym}; use syntax_pos::Span; use crate::hir::intravisit::{self, NestedVisitorMap, Visitor}; @@ -1285,7 +1285,7 @@ fn compute_object_lifetime_defaults( let result = object_lifetime_defaults_for_item(tcx, generics); // Debugging aid. - if attr::contains_name(&item.attrs, "rustc_object_lifetime_default") { + if attr::contains_name(&item.attrs, sym::rustc_object_lifetime_default) { let object_lifetime_default_reprs: String = result .iter() .map(|set| match *set { diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 5078bd7c59423..c608c72430cbe 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -11,7 +11,7 @@ use crate::hir::intravisit::{self, Visitor, NestedVisitorMap}; use crate::ty::query::Providers; use crate::middle::privacy::AccessLevels; use crate::session::{DiagnosticMessageId, Session}; -use syntax::symbol::Symbol; +use syntax::symbol::{Symbol, sym}; use syntax_pos::{Span, MultiSpan}; use syntax::ast::Attribute; use syntax::errors::Applicability; @@ -669,7 +669,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { match stability { Some(&Stability { level: attr::Unstable { reason, issue }, feature, .. }) => { - if span.allows_unstable(&feature.as_str()) { + if span.allows_unstable(feature) { debug!("stability: skipping span={:?} since it is internal", span); return EvalResult::Allow; } @@ -739,7 +739,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let error_id = (DiagnosticMessageId::StabilityId(issue), span_key, msg.clone()); let fresh = self.sess.one_time_diagnostics.borrow_mut().insert(error_id); if fresh { - emit_feature_err(&self.sess.parse_sess, &feature.as_str(), span, + emit_feature_err(&self.sess.parse_sess, feature, span, GateIssue::Library(Some(issue)), &msg); } } @@ -802,13 +802,13 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { if adt_def.has_dtor(self.tcx) { emit_feature_err(&self.tcx.sess.parse_sess, - "untagged_unions", item.span, GateIssue::Language, + sym::untagged_unions, item.span, GateIssue::Language, "unions with `Drop` implementations are unstable"); } else { let param_env = self.tcx.param_env(def_id); if !param_env.can_type_implement_copy(self.tcx, ty).is_ok() { emit_feature_err(&self.tcx.sess.parse_sess, - "untagged_unions", item.span, GateIssue::Language, + sym::untagged_unions, item.span, GateIssue::Language, "unions with non-`Copy` fields are unstable"); } } diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 0e7b66b744499..2fff4c3f109b1 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -1052,7 +1052,7 @@ rustc_queries! { } Other { - query target_features_whitelist(_: CrateNum) -> Lrc>> { + query target_features_whitelist(_: CrateNum) -> Lrc>> { eval_always desc { "looking up the whitelist of target features" } } diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index e8c7965ab4f45..4d47491661e86 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -29,6 +29,7 @@ use syntax::feature_gate::{self, AttributeType}; use syntax::json::JsonEmitter; use syntax::source_map; use syntax::parse::{self, ParseSess}; +use syntax::symbol::Symbol; use syntax_pos::{MultiSpan, Span}; use crate::util::profiling::SelfProfiler; @@ -86,7 +87,7 @@ pub struct Session { /// in order to avoid redundantly verbose output (Issue #24690, #44953). pub one_time_diagnostics: Lock, String)>>, pub plugin_llvm_passes: OneThread>>, - pub plugin_attributes: Lock>, + pub plugin_attributes: Lock>, pub crate_types: Once>, pub dependency_formats: Once, /// The crate_disambiguator is constructed out of all the `-C metadata` diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 35d8e2beef557..afbce5a4f0a49 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -4,17 +4,16 @@ //! [trait-resolution]: https://rust-lang.github.io/rustc-guide/traits/resolution.html //! [trait-specialization]: https://rust-lang.github.io/rustc-guide/traits/specialization.html -use crate::infer::CombinedSnapshot; +use crate::infer::{CombinedSnapshot, InferOk}; use crate::hir::def_id::{DefId, LOCAL_CRATE}; -use syntax_pos::DUMMY_SP; use crate::traits::{self, Normalized, SelectionContext, Obligation, ObligationCause}; use crate::traits::IntercrateMode; use crate::traits::select::IntercrateAmbiguityCause; use crate::ty::{self, Ty, TyCtxt}; use crate::ty::fold::TypeFoldable; use crate::ty::subst::Subst; - -use crate::infer::{InferOk}; +use syntax::symbol::sym; +use syntax_pos::DUMMY_SP; /// Whether we do the orphan check relative to this crate or /// to some remote crate. @@ -233,7 +232,7 @@ pub fn trait_ref_is_knowable<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, pub fn trait_ref_is_local_or_fundamental<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, trait_ref: ty::TraitRef<'tcx>) -> bool { - trait_ref.def_id.krate == LOCAL_CRATE || tcx.has_attr(trait_ref.def_id, "fundamental") + trait_ref.def_id.krate == LOCAL_CRATE || tcx.has_attr(trait_ref.def_id, sym::fundamental) } pub enum OrphanCheckErr<'tcx> { diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index d9ccbba69d5c0..df26883971022 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -35,6 +35,7 @@ use crate::util::nodemap::{FxHashMap, FxHashSet}; use errors::{Applicability, DiagnosticBuilder}; use std::fmt; use syntax::ast; +use syntax::symbol::sym; use syntax_pos::{DUMMY_SP, Span, ExpnInfo, ExpnFormat}; impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { @@ -329,7 +330,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { return None }; - if tcx.has_attr(impl_def_id, "rustc_on_unimplemented") { + if tcx.has_attr(impl_def_id, sym::rustc_on_unimplemented) { Some(impl_def_id) } else { None diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs index 2b286ee1b97fb..7ba7429f465a6 100644 --- a/src/librustc/traits/on_unimplemented.rs +++ b/src/librustc/traits/on_unimplemented.rs @@ -7,6 +7,7 @@ use crate::util::nodemap::FxHashMap; use syntax::ast::{MetaItem, NestedMetaItem}; use syntax::attr; +use syntax::symbol::sym; use syntax_pos::Span; use syntax_pos::symbol::LocalInternedString; @@ -84,25 +85,25 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective { let mut note = None; let mut subcommands = vec![]; for item in item_iter { - if item.check_name("message") && message.is_none() { + if item.check_name(sym::message) && message.is_none() { if let Some(message_) = item.value_str() { message = Some(OnUnimplementedFormatString::try_parse( tcx, trait_def_id, message_.as_str(), span)?); continue; } - } else if item.check_name("label") && label.is_none() { + } else if item.check_name(sym::label) && label.is_none() { if let Some(label_) = item.value_str() { label = Some(OnUnimplementedFormatString::try_parse( tcx, trait_def_id, label_.as_str(), span)?); continue; } - } else if item.check_name("note") && note.is_none() { + } else if item.check_name(sym::note) && note.is_none() { if let Some(note_) = item.value_str() { note = Some(OnUnimplementedFormatString::try_parse( tcx, trait_def_id, note_.as_str(), span)?); continue; } - } else if item.check_name("on") && is_root && + } else if item.check_name(sym::on) && is_root && message.is_none() && label.is_none() && note.is_none() { if let Some(items) = item.meta_item_list() { @@ -139,7 +140,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective { { let attrs = tcx.get_attrs(impl_def_id); - let attr = if let Some(item) = attr::find_by_name(&attrs, "rustc_on_unimplemented") { + let attr = if let Some(item) = attr::find_by_name(&attrs, sym::rustc_on_unimplemented) { item } else { return Ok(None); diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 15524ca6e930c..c9fee02f66bbd 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -74,7 +74,7 @@ use syntax::ast; use syntax::attr; use syntax::source_map::MultiSpan; use syntax::feature_gate; -use syntax::symbol::{Symbol, keywords, InternedString}; +use syntax::symbol::{Symbol, keywords, InternedString, sym}; use syntax_pos::Span; use crate::hir; @@ -1213,7 +1213,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } span_bug!(attr.span, "no arguments to `rustc_layout_scalar_valid_range` attribute"); }; - (get("rustc_layout_scalar_valid_range_start"), get("rustc_layout_scalar_valid_range_end")) + (get(sym::rustc_layout_scalar_valid_range_start), + get(sym::rustc_layout_scalar_valid_range_end)) } pub fn lift>(self, value: &T) -> Option { @@ -3102,10 +3103,10 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { }; providers.is_panic_runtime = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); - attr::contains_name(tcx.hir().krate_attrs(), "panic_runtime") + attr::contains_name(tcx.hir().krate_attrs(), sym::panic_runtime) }; providers.is_compiler_builtins = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); - attr::contains_name(tcx.hir().krate_attrs(), "compiler_builtins") + attr::contains_name(tcx.hir().krate_attrs(), sym::compiler_builtins) }; } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 7b749957c3ff5..2f71861d4dc0d 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -47,7 +47,7 @@ use std::ops::Range; use syntax::ast::{self, Name, Ident, NodeId}; use syntax::attr; use syntax::ext::hygiene::Mark; -use syntax::symbol::{keywords, Symbol, LocalInternedString, InternedString}; +use syntax::symbol::{keywords, sym, Symbol, LocalInternedString, InternedString}; use syntax_pos::Span; use smallvec; @@ -1875,11 +1875,11 @@ impl<'a, 'gcx, 'tcx> VariantDef { ); let mut flags = VariantFlags::NO_VARIANT_FLAGS; - if adt_kind == AdtKind::Struct && tcx.has_attr(parent_did, "non_exhaustive") { + if adt_kind == AdtKind::Struct && tcx.has_attr(parent_did, sym::non_exhaustive) { debug!("found non-exhaustive field list for {:?}", parent_did); flags = flags | VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE; } else if let Some(variant_did) = variant_did { - if tcx.has_attr(variant_did, "non_exhaustive") { + if tcx.has_attr(variant_did, sym::non_exhaustive) { debug!("found non-exhaustive field list for {:?}", variant_did); flags = flags | VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE; } @@ -2156,7 +2156,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr); let mut flags = AdtFlags::NO_ADT_FLAGS; - if kind == AdtKind::Enum && tcx.has_attr(did, "non_exhaustive") { + if kind == AdtKind::Enum && tcx.has_attr(did, sym::non_exhaustive) { debug!("found non-exhaustive variant list for {:?}", did); flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE; } @@ -2172,7 +2172,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { } let attrs = tcx.get_attrs(did); - if attr::contains_name(&attrs, "fundamental") { + if attr::contains_name(&attrs, sym::fundamental) { flags |= AdtFlags::IS_FUNDAMENTAL; } if Some(did) == tcx.lang_items().phantom_data() { @@ -3030,7 +3030,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } /// Determines whether an item is annotated with an attribute. - pub fn has_attr(self, did: DefId, attr: &str) -> bool { + pub fn has_attr(self, did: DefId, attr: Symbol) -> bool { attr::contains_name(&self.get_attrs(did), attr) } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 4c8ed71a57ca6..926c0f8b94919 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -22,6 +22,7 @@ use rustc_macros::HashStable; use std::{cmp, fmt}; use syntax::ast; use syntax::attr::{self, SignedInt, UnsignedInt}; +use syntax::symbol::sym; use syntax_pos::{Span, DUMMY_SP}; #[derive(Copy, Clone, Debug)] @@ -447,7 +448,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // Such access can be in plain sight (e.g., dereferencing // `*foo.0` of `Foo<'a>(&'a u32)`) or indirectly hidden // (e.g., calling `foo.0.clone()` of `Foo`). - if self.has_attr(dtor, "unsafe_destructor_blind_to_params") { + if self.has_attr(dtor, sym::unsafe_destructor_blind_to_params) { debug!("destructor_constraint({:?}) - blind", def.did); return vec![]; } diff --git a/src/librustc_allocator/expand.rs b/src/librustc_allocator/expand.rs index 758a0d63886b1..0200e6c53b69c 100644 --- a/src/librustc_allocator/expand.rs +++ b/src/librustc_allocator/expand.rs @@ -19,7 +19,7 @@ use syntax::{ mut_visit::{self, MutVisitor}, parse::ParseSess, ptr::P, - symbol::Symbol + symbol::{Symbol, sym} }; use syntax_pos::Span; @@ -58,7 +58,7 @@ impl MutVisitor for ExpandAllocatorDirectives<'_> { fn flat_map_item(&mut self, item: P) -> SmallVec<[P; 1]> { debug!("in submodule {}", self.in_submod); - let name = if attr::contains_name(&item.attrs, "global_allocator") { + let name = if attr::contains_name(&item.attrs, sym::global_allocator) { "global_allocator" } else { return mut_visit::noop_flat_map_item(item, self); diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index b15a64c966b1b..f26684d9ef04a 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -321,12 +321,12 @@ pub fn provide(providers: &mut Providers<'_>) { // rustdoc needs to be able to document functions that use all the features, so // whitelist them all Lrc::new(llvm_util::all_known_features() - .map(|(a, b)| (a.to_string(), b.map(|s| s.to_string()))) + .map(|(a, b)| (a.to_string(), b)) .collect()) } else { Lrc::new(llvm_util::target_feature_whitelist(tcx.sess) .iter() - .map(|&(a, b)| (a.to_string(), b.map(|s| s.to_string()))) + .map(|&(a, b)| (a.to_string(), b)) .collect()) } }; diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index 8c83e9ef538e5..5f47108309fbf 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -14,6 +14,7 @@ use rustc::mir::interpret::{ConstValue, Allocation, read_target_uint, use rustc::hir::Node; use syntax_pos::Span; use rustc_target::abi::HasDataLayout; +use syntax::symbol::sym; use syntax_pos::symbol::LocalInternedString; use rustc::ty::{self, Ty}; use rustc_codegen_ssa::traits::*; @@ -248,7 +249,7 @@ impl CodegenCx<'ll, 'tcx> { debug!("get_static: sym={} attrs={:?}", sym, attrs); for attr in attrs { - if attr.check_name("thread_local") { + if attr.check_name(sym::thread_local) { llvm::set_thread_local_mode(g, self.tls_model); } } diff --git a/src/librustc_codegen_llvm/debuginfo/gdb.rs b/src/librustc_codegen_llvm/debuginfo/gdb.rs index 91496ffbe557a..04c9e93c7a527 100644 --- a/src/librustc_codegen_llvm/debuginfo/gdb.rs +++ b/src/librustc_codegen_llvm/debuginfo/gdb.rs @@ -9,6 +9,7 @@ use rustc::session::config::DebugInfo; use rustc_codegen_ssa::traits::*; use syntax::attr; +use syntax::symbol::sym; /// Inserts a side-effect free instruction sequence that makes sure that the @@ -66,8 +67,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx<'ll, '_>) pub fn needs_gdb_debug_scripts_section(cx: &CodegenCx<'_, '_>) -> bool { let omit_gdb_pretty_printer_section = - attr::contains_name(&cx.tcx.hir().krate_attrs(), - "omit_gdb_pretty_printer_section"); + attr::contains_name(&cx.tcx.hir().krate_attrs(), sym::omit_gdb_pretty_printer_section); !omit_gdb_pretty_printer_section && cx.sess().opts.debuginfo != DebugInfo::None && diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs index f1b8d532eeb76..274c89659628d 100644 --- a/src/librustc_codegen_llvm/llvm_util.rs +++ b/src/librustc_codegen_llvm/llvm_util.rs @@ -7,6 +7,7 @@ use rustc_target::spec::MergeFunctions; use libc::c_int; use std::ffi::CString; use syntax::feature_gate::UnstableFeatures; +use syntax::symbol::sym; use std::str; use std::slice; @@ -93,106 +94,106 @@ unsafe fn configure_llvm(sess: &Session) { // to LLVM or the feature detection code will walk past the end of the feature // array, leading to crashes. -const ARM_WHITELIST: &[(&str, Option<&str>)] = &[ - ("aclass", Some("arm_target_feature")), - ("mclass", Some("arm_target_feature")), - ("rclass", Some("arm_target_feature")), - ("dsp", Some("arm_target_feature")), - ("neon", Some("arm_target_feature")), - ("v5te", Some("arm_target_feature")), - ("v6", Some("arm_target_feature")), - ("v6k", Some("arm_target_feature")), - ("v6t2", Some("arm_target_feature")), - ("v7", Some("arm_target_feature")), - ("v8", Some("arm_target_feature")), - ("vfp2", Some("arm_target_feature")), - ("vfp3", Some("arm_target_feature")), - ("vfp4", Some("arm_target_feature")), +const ARM_WHITELIST: &[(&str, Option)] = &[ + ("aclass", Some(sym::arm_target_feature)), + ("mclass", Some(sym::arm_target_feature)), + ("rclass", Some(sym::arm_target_feature)), + ("dsp", Some(sym::arm_target_feature)), + ("neon", Some(sym::arm_target_feature)), + ("v5te", Some(sym::arm_target_feature)), + ("v6", Some(sym::arm_target_feature)), + ("v6k", Some(sym::arm_target_feature)), + ("v6t2", Some(sym::arm_target_feature)), + ("v7", Some(sym::arm_target_feature)), + ("v8", Some(sym::arm_target_feature)), + ("vfp2", Some(sym::arm_target_feature)), + ("vfp3", Some(sym::arm_target_feature)), + ("vfp4", Some(sym::arm_target_feature)), ]; -const AARCH64_WHITELIST: &[(&str, Option<&str>)] = &[ - ("fp", Some("aarch64_target_feature")), - ("neon", Some("aarch64_target_feature")), - ("sve", Some("aarch64_target_feature")), - ("crc", Some("aarch64_target_feature")), - ("crypto", Some("aarch64_target_feature")), - ("ras", Some("aarch64_target_feature")), - ("lse", Some("aarch64_target_feature")), - ("rdm", Some("aarch64_target_feature")), - ("fp16", Some("aarch64_target_feature")), - ("rcpc", Some("aarch64_target_feature")), - ("dotprod", Some("aarch64_target_feature")), - ("v8.1a", Some("aarch64_target_feature")), - ("v8.2a", Some("aarch64_target_feature")), - ("v8.3a", Some("aarch64_target_feature")), +const AARCH64_WHITELIST: &[(&str, Option)] = &[ + ("fp", Some(sym::aarch64_target_feature)), + ("neon", Some(sym::aarch64_target_feature)), + ("sve", Some(sym::aarch64_target_feature)), + ("crc", Some(sym::aarch64_target_feature)), + ("crypto", Some(sym::aarch64_target_feature)), + ("ras", Some(sym::aarch64_target_feature)), + ("lse", Some(sym::aarch64_target_feature)), + ("rdm", Some(sym::aarch64_target_feature)), + ("fp16", Some(sym::aarch64_target_feature)), + ("rcpc", Some(sym::aarch64_target_feature)), + ("dotprod", Some(sym::aarch64_target_feature)), + ("v8.1a", Some(sym::aarch64_target_feature)), + ("v8.2a", Some(sym::aarch64_target_feature)), + ("v8.3a", Some(sym::aarch64_target_feature)), ]; -const X86_WHITELIST: &[(&str, Option<&str>)] = &[ - ("adx", Some("adx_target_feature")), +const X86_WHITELIST: &[(&str, Option)] = &[ + ("adx", Some(sym::adx_target_feature)), ("aes", None), ("avx", None), ("avx2", None), - ("avx512bw", Some("avx512_target_feature")), - ("avx512cd", Some("avx512_target_feature")), - ("avx512dq", Some("avx512_target_feature")), - ("avx512er", Some("avx512_target_feature")), - ("avx512f", Some("avx512_target_feature")), - ("avx512ifma", Some("avx512_target_feature")), - ("avx512pf", Some("avx512_target_feature")), - ("avx512vbmi", Some("avx512_target_feature")), - ("avx512vl", Some("avx512_target_feature")), - ("avx512vpopcntdq", Some("avx512_target_feature")), + ("avx512bw", Some(sym::avx512_target_feature)), + ("avx512cd", Some(sym::avx512_target_feature)), + ("avx512dq", Some(sym::avx512_target_feature)), + ("avx512er", Some(sym::avx512_target_feature)), + ("avx512f", Some(sym::avx512_target_feature)), + ("avx512ifma", Some(sym::avx512_target_feature)), + ("avx512pf", Some(sym::avx512_target_feature)), + ("avx512vbmi", Some(sym::avx512_target_feature)), + ("avx512vl", Some(sym::avx512_target_feature)), + ("avx512vpopcntdq", Some(sym::avx512_target_feature)), ("bmi1", None), ("bmi2", None), - ("cmpxchg16b", Some("cmpxchg16b_target_feature")), - ("f16c", Some("f16c_target_feature")), + ("cmpxchg16b", Some(sym::cmpxchg16b_target_feature)), + ("f16c", Some(sym::f16c_target_feature)), ("fma", None), ("fxsr", None), ("lzcnt", None), - ("mmx", Some("mmx_target_feature")), - ("movbe", Some("movbe_target_feature")), + ("mmx", Some(sym::mmx_target_feature)), + ("movbe", Some(sym::movbe_target_feature)), ("pclmulqdq", None), ("popcnt", None), ("rdrand", None), ("rdseed", None), - ("rtm", Some("rtm_target_feature")), + ("rtm", Some(sym::rtm_target_feature)), ("sha", None), ("sse", None), ("sse2", None), ("sse3", None), ("sse4.1", None), ("sse4.2", None), - ("sse4a", Some("sse4a_target_feature")), + ("sse4a", Some(sym::sse4a_target_feature)), ("ssse3", None), - ("tbm", Some("tbm_target_feature")), + ("tbm", Some(sym::tbm_target_feature)), ("xsave", None), ("xsavec", None), ("xsaveopt", None), ("xsaves", None), ]; -const HEXAGON_WHITELIST: &[(&str, Option<&str>)] = &[ - ("hvx", Some("hexagon_target_feature")), - ("hvx-double", Some("hexagon_target_feature")), +const HEXAGON_WHITELIST: &[(&str, Option)] = &[ + ("hvx", Some(sym::hexagon_target_feature)), + ("hvx-double", Some(sym::hexagon_target_feature)), ]; -const POWERPC_WHITELIST: &[(&str, Option<&str>)] = &[ - ("altivec", Some("powerpc_target_feature")), - ("power8-altivec", Some("powerpc_target_feature")), - ("power9-altivec", Some("powerpc_target_feature")), - ("power8-vector", Some("powerpc_target_feature")), - ("power9-vector", Some("powerpc_target_feature")), - ("vsx", Some("powerpc_target_feature")), +const POWERPC_WHITELIST: &[(&str, Option)] = &[ + ("altivec", Some(sym::powerpc_target_feature)), + ("power8-altivec", Some(sym::powerpc_target_feature)), + ("power9-altivec", Some(sym::powerpc_target_feature)), + ("power8-vector", Some(sym::powerpc_target_feature)), + ("power9-vector", Some(sym::powerpc_target_feature)), + ("vsx", Some(sym::powerpc_target_feature)), ]; -const MIPS_WHITELIST: &[(&str, Option<&str>)] = &[ - ("fp64", Some("mips_target_feature")), - ("msa", Some("mips_target_feature")), +const MIPS_WHITELIST: &[(&str, Option)] = &[ + ("fp64", Some(sym::mips_target_feature)), + ("msa", Some(sym::mips_target_feature)), ]; -const WASM_WHITELIST: &[(&str, Option<&str>)] = &[ - ("simd128", Some("wasm_target_feature")), - ("atomics", Some("wasm_target_feature")), +const WASM_WHITELIST: &[(&str, Option)] = &[ + ("simd128", Some(sym::wasm_target_feature)), + ("atomics", Some(sym::wasm_target_feature)), ]; /// When rustdoc is running, provide a list of all known features so that all their respective @@ -200,7 +201,7 @@ const WASM_WHITELIST: &[(&str, Option<&str>)] = &[ /// /// IMPORTANT: If you're adding another whitelist to the above lists, make sure to add it to this /// iterator! -pub fn all_known_features() -> impl Iterator)> { +pub fn all_known_features() -> impl Iterator)> { ARM_WHITELIST.iter().cloned() .chain(AARCH64_WHITELIST.iter().cloned()) .chain(X86_WHITELIST.iter().cloned()) @@ -247,7 +248,7 @@ pub fn target_features(sess: &Session) -> Vec { } pub fn target_feature_whitelist(sess: &Session) - -> &'static [(&'static str, Option<&'static str>)] + -> &'static [(&'static str, Option)] { match &*sess.target.target.arch { "arm" => ARM_WHITELIST, diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 576bcc8f38e65..204ca59efc8d3 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -28,7 +28,7 @@ use rustc_target::spec::MergeFunctions; use syntax::attr; use syntax::ext::hygiene::Mark; use syntax_pos::MultiSpan; -use syntax_pos::symbol::Symbol; +use syntax_pos::symbol::{Symbol, sym}; use jobserver::{Client, Acquired}; use std::any::Any; @@ -382,9 +382,9 @@ pub fn start_async_codegen( let sess = tcx.sess; let crate_name = tcx.crate_name(LOCAL_CRATE); let crate_hash = tcx.crate_hash(LOCAL_CRATE); - let no_builtins = attr::contains_name(&tcx.hir().krate().attrs, "no_builtins"); + let no_builtins = attr::contains_name(&tcx.hir().krate().attrs, sym::no_builtins); let subsystem = attr::first_attr_value_str_by_name(&tcx.hir().krate().attrs, - "windows_subsystem"); + sym::windows_subsystem); let windows_subsystem = subsystem.map(|subsystem| { if subsystem != "windows" && subsystem != "console" { tcx.sess.fatal(&format!("invalid windows subsystem `{}`, only \ diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 8d3e64c1aa6c7..586db5cfabea4 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -5,6 +5,7 @@ use rustc::mir; use rustc::middle::lang_items::ExchangeMallocFnLangItem; use rustc_apfloat::{ieee, Float, Status, Round}; use std::{u128, i128}; +use syntax::symbol::sym; use crate::base; use crate::MemFlags; @@ -181,9 +182,8 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::CastKind::Pointer(PointerCast::ReifyFnPointer) => { match operand.layout.ty.sty { ty::FnDef(def_id, substs) => { - if bx.cx().tcx().has_attr(def_id, "rustc_args_required_const") { - bug!("reifying a fn ptr that requires \ - const arguments"); + if bx.cx().tcx().has_attr(def_id, sym::rustc_args_required_const) { + bug!("reifying a fn ptr that requires const arguments"); } OperandValue::Immediate( callee::resolve_and_get_fn(bx.cx(), def_id, substs)) diff --git a/src/librustc_codegen_utils/lib.rs b/src/librustc_codegen_utils/lib.rs index 437515f1e9ab4..b4ba90c61f650 100644 --- a/src/librustc_codegen_utils/lib.rs +++ b/src/librustc_codegen_utils/lib.rs @@ -23,6 +23,7 @@ extern crate rustc; use rustc::ty::TyCtxt; use rustc::hir::def_id::LOCAL_CRATE; +use syntax::symbol::sym; pub mod link; pub mod codegen_backend; @@ -35,7 +36,7 @@ pub mod symbol_names_test; /// reporting an error. pub fn check_for_rustc_errors_attr(tcx: TyCtxt<'_, '_, '_>) { if let Some((def_id, _)) = tcx.entry_fn(LOCAL_CRATE) { - if tcx.has_attr(def_id, "rustc_error") { + if tcx.has_attr(def_id, sym::rustc_error) { tcx.sess.span_fatal(tcx.def_span(def_id), "compilation successful"); } } diff --git a/src/librustc_codegen_utils/link.rs b/src/librustc_codegen_utils/link.rs index f3a1b219f8a84..30f37fefa7cf7 100644 --- a/src/librustc_codegen_utils/link.rs +++ b/src/librustc_codegen_utils/link.rs @@ -2,6 +2,7 @@ use rustc::session::config::{self, OutputFilenames, Input, OutputType}; use rustc::session::Session; use std::path::{Path, PathBuf}; use syntax::{ast, attr}; +use syntax::symbol::sym; use syntax_pos::Span; pub fn out_filename(sess: &Session, @@ -49,7 +50,7 @@ pub fn find_crate_name(sess: Option<&Session>, // as used. After doing this, however, we still prioritize a crate name from // the command line over one found in the #[crate_name] attribute. If we // find both we ensure that they're the same later on as well. - let attr_crate_name = attr::find_by_name(attrs, "crate_name") + let attr_crate_name = attr::find_by_name(attrs, sym::crate_name) .and_then(|at| at.value_str().map(|s| (at, s))); if let Some(sess) = sess { diff --git a/src/librustc_codegen_utils/symbol_names_test.rs b/src/librustc_codegen_utils/symbol_names_test.rs index 6a2b6f1321b88..27ae0b97e5945 100644 --- a/src/librustc_codegen_utils/symbol_names_test.rs +++ b/src/librustc_codegen_utils/symbol_names_test.rs @@ -6,11 +6,11 @@ use rustc::hir; use rustc::ty::TyCtxt; - use rustc_mir::monomorphize::Instance; +use syntax::symbol::{Symbol, sym}; -const SYMBOL_NAME: &'static str = "rustc_symbol_name"; -const DEF_PATH: &'static str = "rustc_def_path"; +const SYMBOL_NAME: Symbol = sym::rustc_symbol_name; +const DEF_PATH: Symbol = sym::rustc_def_path; pub fn report_symbol_names<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { // if the `rustc_attrs` feature is not enabled, then the diff --git a/src/librustc_incremental/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs index 2c83501c86f52..04dad9c5355c5 100644 --- a/src/librustc_incremental/assert_module_sources.rs +++ b/src/librustc_incremental/assert_module_sources.rs @@ -27,12 +27,13 @@ use rustc::mir::mono::CodegenUnitNameBuilder; use rustc::ty::TyCtxt; use std::collections::BTreeSet; use syntax::ast; +use syntax::symbol::{Symbol, sym}; use rustc::ich::{ATTR_PARTITION_REUSED, ATTR_PARTITION_CODEGENED, ATTR_EXPECTED_CGU_REUSE}; -const MODULE: &str = "module"; -const CFG: &str = "cfg"; -const KIND: &str = "kind"; +const MODULE: Symbol = sym::module; +const CFG: Symbol = sym::cfg; +const KIND: Symbol = sym::kind; pub fn assert_module_sources<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { tcx.dep_graph.with_ignore(|| { @@ -146,7 +147,7 @@ impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> { comp_kind); } - fn field(&self, attr: &ast::Attribute, name: &str) -> ast::Name { + fn field(&self, attr: &ast::Attribute, name: Symbol) -> ast::Name { for item in attr.meta_item_list().unwrap_or_else(Vec::new) { if item.check_name(name) { if let Some(value) = item.value_str() { diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index 6f5b411946c2d..f404a4f82e672 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -23,14 +23,15 @@ use rustc::hir::def_id::DefId; use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::intravisit; use rustc::ich::{ATTR_DIRTY, ATTR_CLEAN}; -use syntax::ast::{self, Attribute, NestedMetaItem}; +use rustc::ty::TyCtxt; use rustc_data_structures::fx::FxHashSet; +use syntax::ast::{self, Attribute, NestedMetaItem}; +use syntax::symbol::{Symbol, sym}; use syntax_pos::Span; -use rustc::ty::TyCtxt; -const EXCEPT: &str = "except"; -const LABEL: &str = "label"; -const CFG: &str = "cfg"; +const EXCEPT: Symbol = sym::except; +const LABEL: Symbol = sym::label; +const CFG: Symbol = sym::cfg; // Base and Extra labels to build up the labels @@ -591,7 +592,7 @@ fn expect_associated_value(tcx: TyCtxt<'_, '_, '_>, item: &NestedMetaItem) -> as // nodes. pub struct FindAllAttrs<'a, 'tcx:'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, - attr_names: Vec<&'static str>, + attr_names: Vec, found_attrs: Vec<&'tcx Attribute>, } diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 54b3e73420560..c5ac8860ccd9b 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -230,7 +230,7 @@ impl BoxedResolver { pub struct PluginInfo { syntax_exts: Vec, - attributes: Vec<(String, AttributeType)>, + attributes: Vec<(Symbol, AttributeType)>, } pub fn register_plugins<'a>( diff --git a/src/librustc_interface/proc_macro_decls.rs b/src/librustc_interface/proc_macro_decls.rs index 8ed03efd1a784..e9f2f0410d440 100644 --- a/src/librustc_interface/proc_macro_decls.rs +++ b/src/librustc_interface/proc_macro_decls.rs @@ -4,6 +4,7 @@ use rustc::hir; use rustc::ty::TyCtxt; use rustc::ty::query::Providers; use syntax::attr; +use syntax::symbol::sym; pub fn find<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) -> Option { tcx.proc_macro_decls_static(LOCAL_CRATE) @@ -27,7 +28,7 @@ struct Finder { impl<'v> ItemLikeVisitor<'v> for Finder { fn visit_item(&mut self, item: &hir::Item) { - if attr::contains_name(&item.attrs, "rustc_proc_macro_decls") { + if attr::contains_name(&item.attrs, sym::rustc_proc_macro_decls) { self.decls = Some(item.hir_id); } } diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index 17523aedffb58..2b1a993d1cc2c 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -35,7 +35,7 @@ use syntax::mut_visit::{*, MutVisitor, visit_clobber}; use syntax::ast::BlockCheckMode; use syntax::util::lev_distance::find_best_match_for_name; use syntax::source_map::{FileLoader, RealFileLoader, SourceMap}; -use syntax::symbol::Symbol; +use syntax::symbol::{Symbol, sym}; use syntax::{self, ast, attr}; #[cfg(not(parallel_compiler))] use std::{thread, panic}; @@ -495,7 +495,7 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec = attrs .iter() .filter_map(|a| { - if a.check_name("crate_type") { + if a.check_name(sym::crate_type) { match a.value_str() { Some(ref n) if *n == "rlib" => Some(config::CrateType::Rlib), Some(ref n) if *n == "dylib" => Some(config::CrateType::Dylib), diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index f7a89271ec55f..af4f1b88b0fb0 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -42,7 +42,7 @@ use syntax::edition::Edition; use syntax::feature_gate::{AttributeGate, AttributeTemplate, AttributeType}; use syntax::feature_gate::{Stability, deprecated_attributes}; use syntax_pos::{BytePos, Span, SyntaxContext}; -use syntax::symbol::{Symbol, keywords}; +use syntax::symbol::{Symbol, keywords, sym}; use syntax::errors::{Applicability, DiagnosticBuilder}; use syntax::print::pprust::expr_to_string; use syntax::visit::FnKind; @@ -207,7 +207,7 @@ impl UnsafeCode { impl EarlyLintPass for UnsafeCode { fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) { - if attr.check_name("allow_internal_unsafe") { + if attr.check_name(sym::allow_internal_unsafe) { self.report_unsafe(cx, attr.span, "`allow_internal_unsafe` allows defining \ macros using unsafe without triggering \ the `unsafe_code` lint at their call site"); @@ -285,7 +285,7 @@ pub struct MissingDoc { impl_lint_pass!(MissingDoc => [MISSING_DOCS]); fn has_doc(attr: &ast::Attribute) -> bool { - if !attr.check_name("doc") { + if !attr.check_name(sym::doc) { return false; } @@ -295,7 +295,7 @@ fn has_doc(attr: &ast::Attribute) -> bool { if let Some(list) = attr.meta_item_list() { for meta in list { - if meta.check_name("include") || meta.check_name("hidden") { + if meta.check_name(sym::include) || meta.check_name(sym::hidden) { return true; } } @@ -355,10 +355,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { fn enter_lint_attrs(&mut self, _: &LateContext<'_, '_>, attrs: &[ast::Attribute]) { let doc_hidden = self.doc_hidden() || attrs.iter().any(|attr| { - attr.check_name("doc") && + attr.check_name(sym::doc) && match attr.meta_item_list() { None => false, - Some(l) => attr::list_contains_name(&l, "hidden"), + Some(l) => attr::list_contains_name(&l, sym::hidden), } }); self.doc_hidden_stack.push(doc_hidden); @@ -723,7 +723,7 @@ impl UnusedDocComment { let span = sugared_span.take().unwrap_or_else(|| attr.span); - if attr.check_name("doc") { + if attr.check_name(sym::doc) { let mut err = cx.struct_span_lint(UNUSED_DOC_COMMENTS, span, "unused doc comment"); err.span_label( @@ -829,7 +829,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems { fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) { match it.node { hir::ItemKind::Fn(.., ref generics, _) => { - if let Some(no_mangle_attr) = attr::find_by_name(&it.attrs, "no_mangle") { + if let Some(no_mangle_attr) = attr::find_by_name(&it.attrs, sym::no_mangle) { for param in &generics.params { match param.kind { GenericParamKind::Lifetime { .. } => {} @@ -856,7 +856,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems { } } hir::ItemKind::Const(..) => { - if attr::contains_name(&it.attrs, "no_mangle") { + if attr::contains_name(&it.attrs, sym::no_mangle) { // Const items do not refer to a particular location in memory, and therefore // don't have anything to attach a symbol to let msg = "const items should never be #[no_mangle]"; @@ -947,7 +947,7 @@ declare_lint_pass!( impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnstableFeatures { fn check_attribute(&mut self, ctx: &LateContext<'_, '_>, attr: &ast::Attribute) { - if attr.check_name("feature") { + if attr.check_name(sym::feature) { if let Some(items) = attr.meta_item_list() { for item in items { ctx.span_lint(UNSTABLE_FEATURES, item.span(), "unstable feature"); @@ -1382,7 +1382,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnameableTestItems { return; } - if let Some(attr) = attr::find_by_name(&it.attrs, "rustc_test_marker") { + if let Some(attr) = attr::find_by_name(&it.attrs, sym::rustc_test_marker) { cx.struct_span_lint( UNNAMEABLE_TEST_ITEMS, attr.span, diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs index 7a003d14b2bf0..551eded9858a3 100644 --- a/src/librustc_lint/nonstandard_style.rs +++ b/src/librustc_lint/nonstandard_style.rs @@ -9,6 +9,7 @@ use lint::{EarlyLintPass, LintPass, LateLintPass}; use syntax::ast; use syntax::attr; use syntax::errors::Applicability; +use syntax::symbol::sym; use syntax_pos::{BytePos, symbol::Ident, Span}; #[derive(PartialEq)] @@ -253,7 +254,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { let crate_ident = if let Some(name) = &cx.tcx.sess.opts.crate_name { Some(Ident::from_str(name)) } else { - attr::find_by_name(&cx.tcx.hir().attrs_by_hir_id(hir::CRATE_HIR_ID), "crate_name") + attr::find_by_name(&cx.tcx.hir().attrs_by_hir_id(hir::CRATE_HIR_ID), sym::crate_name) .and_then(|attr| attr.meta()) .and_then(|meta| { meta.name_value_literal().and_then(|lit| { @@ -315,7 +316,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { } FnKind::ItemFn(ident, _, header, _, attrs) => { // Skip foreign-ABI #[no_mangle] functions (Issue #31924) - if header.abi != Abi::Rust && attr::contains_name(attrs, "no_mangle") { + if header.abi != Abi::Rust && attr::contains_name(attrs, sym::no_mangle) { return; } self.check_snake_case(cx, "function", ident); @@ -390,7 +391,7 @@ impl NonUpperCaseGlobals { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonUpperCaseGlobals { fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) { match it.node { - hir::ItemKind::Static(..) if !attr::contains_name(&it.attrs, "no_mangle") => { + hir::ItemKind::Static(..) if !attr::contains_name(&it.attrs, sym::no_mangle) => { NonUpperCaseGlobals::check_upper_case(cx, "static variable", &it.ident); } hir::ItemKind::Const(..) => { diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 92508ad51f104..93af7a1cd8f28 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -12,7 +12,7 @@ use syntax::attr; use syntax::errors::Applicability; use syntax::feature_gate::{AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; use syntax::print::pprust; -use syntax::symbol::keywords; +use syntax::symbol::{keywords, sym}; use syntax::symbol::Symbol; use syntax::util::parser; use syntax_pos::Span; @@ -170,7 +170,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { descr_post_path: &str, ) -> bool { for attr in cx.tcx.get_attrs(def_id).iter() { - if attr.check_name("must_use") { + if attr.check_name(sym::must_use) { let msg = format!("unused {}`{}`{} that must be used", descr_pre_path, cx.tcx.def_path_str(def_id), descr_post_path); let mut err = cx.struct_span_lint(UNUSED_MUST_USE, sp, &msg); @@ -243,8 +243,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes { } let plugin_attributes = cx.sess().plugin_attributes.borrow_mut(); - for &(ref name, ty) in plugin_attributes.iter() { - if ty == AttributeType::Whitelisted && attr.check_name(&**name) { + for &(name, ty) in plugin_attributes.iter() { + if ty == AttributeType::Whitelisted && attr.check_name(name) { debug!("{:?} (plugin attr) is whitelisted with ty {:?}", name, ty); break; } diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index c47d7d85a3769..20caad70f2b57 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -27,7 +27,7 @@ use std::{cmp, fs}; use syntax::ast; use syntax::attr; use syntax::ext::base::SyntaxExtension; -use syntax::symbol::Symbol; +use syntax::symbol::{Symbol, sym}; use syntax::visit; use syntax::{span_err, span_fatal}; use syntax_pos::{Span, DUMMY_SP}; @@ -704,7 +704,7 @@ impl<'a> CrateLoader<'a> { let desired_strategy = self.sess.panic_strategy(); let mut runtime_found = false; let mut needs_panic_runtime = attr::contains_name(&krate.attrs, - "needs_panic_runtime"); + sym::needs_panic_runtime); self.cstore.iter_crate_data(|cnum, data| { needs_panic_runtime = needs_panic_runtime || @@ -898,7 +898,7 @@ impl<'a> CrateLoader<'a> { // about through the `#![needs_allocator]` attribute and is typically // written down in liballoc. let mut needs_allocator = attr::contains_name(&krate.attrs, - "needs_allocator"); + sym::needs_allocator); self.cstore.iter_crate_data(|_, data| { needs_allocator = needs_allocator || data.root.needs_allocator; }); @@ -964,7 +964,7 @@ impl<'a> CrateLoader<'a> { // allocator. At this point our allocator request is typically fulfilled // by the standard library, denoted by the `#![default_lib_allocator]` // attribute. - let mut has_default = attr::contains_name(&krate.attrs, "default_lib_allocator"); + let mut has_default = attr::contains_name(&krate.attrs, sym::default_lib_allocator); self.cstore.iter_crate_data(|_, data| { if data.root.has_default_lib_allocator { has_default = true; @@ -987,7 +987,7 @@ impl<'a> CrateLoader<'a> { impl<'ast> visit::Visitor<'ast> for Finder { fn visit_item(&mut self, i: &'ast ast::Item) { - if attr::contains_name(&i.attrs, "global_allocator") { + if attr::contains_name(&i.attrs, sym::global_allocator) { self.0 = true; } visit::walk_item(self, i) @@ -1065,7 +1065,7 @@ impl<'a> CrateLoader<'a> { } None => item.ident.name, }; - let dep_kind = if attr::contains_name(&item.attrs, "no_link") { + let dep_kind = if attr::contains_name(&item.attrs, sym::no_link) { DepKind::UnexportedMacrosOnly } else { DepKind::Explicit diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 4b9db466da843..e950c2815e9b4 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -29,7 +29,7 @@ use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque}; use syntax::attr; use syntax::ast::{self, Ident}; use syntax::source_map; -use syntax::symbol::InternedString; +use syntax::symbol::{InternedString, sym}; use syntax::ext::base::{MacroKind, SyntaxExtension}; use syntax::ext::hygiene::Mark; use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, NO_EXPANSION}; @@ -841,7 +841,7 @@ impl<'a, 'tcx> CrateMetadata { // for other constructors correct visibilities // were already encoded in metadata. let attrs = self.get_item_attrs(def_id.index, sess); - if attr::contains_name(&attrs, "non_exhaustive") { + if attr::contains_name(&attrs, sym::non_exhaustive) { let crate_def_id = self.local_def_id(CRATE_DEF_INDEX); vis = ty::Visibility::Restricted(crate_def_id); } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 0946dad53203d..0ac03526832b7 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -33,7 +33,7 @@ use std::u32; use syntax::ast; use syntax::attr; use syntax::source_map::Spanned; -use syntax::symbol::keywords; +use syntax::symbol::{keywords, sym}; use syntax_pos::{self, hygiene, FileName, SourceFile, Span}; use log::{debug, trace}; @@ -469,7 +469,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let attrs = tcx.hir().krate_attrs(); let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro); - let has_default_lib_allocator = attr::contains_name(&attrs, "default_lib_allocator"); + let has_default_lib_allocator = attr::contains_name(&attrs, sym::default_lib_allocator); let has_global_allocator = *tcx.sess.has_global_allocator.get(); let has_panic_handler = *tcx.sess.has_panic_handler.try_get().unwrap_or(&false); @@ -496,13 +496,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } else { None }, - compiler_builtins: attr::contains_name(&attrs, "compiler_builtins"), - needs_allocator: attr::contains_name(&attrs, "needs_allocator"), - needs_panic_runtime: attr::contains_name(&attrs, "needs_panic_runtime"), - no_builtins: attr::contains_name(&attrs, "no_builtins"), - panic_runtime: attr::contains_name(&attrs, "panic_runtime"), - profiler_runtime: attr::contains_name(&attrs, "profiler_runtime"), - sanitizer_runtime: attr::contains_name(&attrs, "sanitizer_runtime"), + compiler_builtins: attr::contains_name(&attrs, sym::compiler_builtins), + needs_allocator: attr::contains_name(&attrs, sym::needs_allocator), + needs_panic_runtime: attr::contains_name(&attrs, sym::needs_panic_runtime), + no_builtins: attr::contains_name(&attrs, sym::no_builtins), + panic_runtime: attr::contains_name(&attrs, sym::panic_runtime), + profiler_runtime: attr::contains_name(&attrs, sym::profiler_runtime), + sanitizer_runtime: attr::contains_name(&attrs, sym::sanitizer_runtime), crate_deps, dylib_dependency_formats, diff --git a/src/librustc_metadata/link_args.rs b/src/librustc_metadata/link_args.rs index 6741b5235db36..cd5951f0e0e3c 100644 --- a/src/librustc_metadata/link_args.rs +++ b/src/librustc_metadata/link_args.rs @@ -2,6 +2,7 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir; use rustc::ty::TyCtxt; use rustc_target::spec::abi::Abi; +use syntax::symbol::sym; pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Vec { let mut collector = Collector { @@ -37,7 +38,7 @@ impl<'tcx> ItemLikeVisitor<'tcx> for Collector { } // First, add all of the custom #[link_args] attributes - for m in it.attrs.iter().filter(|a| a.check_name("link_args")) { + for m in it.attrs.iter().filter(|a| a.check_name(sym::link_args)) { if let Some(linkarg) = m.value_str() { self.add_link_args(&linkarg.as_str()); } diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs index e0665127c0fb0..3e7e740a15c04 100644 --- a/src/librustc_metadata/native_libs.rs +++ b/src/librustc_metadata/native_libs.rs @@ -8,7 +8,7 @@ use rustc_target::spec::abi::Abi; use syntax::attr; use syntax::source_map::Span; use syntax::feature_gate::{self, GateIssue}; -use syntax::symbol::Symbol; +use syntax::symbol::{Symbol, sym}; use syntax::{span_err, struct_span_err}; pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Vec { @@ -47,7 +47,7 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for Collector<'a, 'tcx> { } // Process all of the #[link(..)]-style arguments - for m in it.attrs.iter().filter(|a| a.check_name("link")) { + for m in it.attrs.iter().filter(|a| a.check_name(sym::link)) { let items = match m.meta_item_list() { Some(item) => item, None => continue, @@ -62,7 +62,7 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for Collector<'a, 'tcx> { let mut kind_specified = false; for item in items.iter() { - if item.check_name("kind") { + if item.check_name(sym::kind) { kind_specified = true; let kind = match item.value_str() { Some(name) => name, @@ -81,9 +81,9 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for Collector<'a, 'tcx> { cstore::NativeUnknown } }; - } else if item.check_name("name") { + } else if item.check_name(sym::name) { lib.name = item.value_str(); - } else if item.check_name("cfg") { + } else if item.check_name(sym::cfg) { let cfg = match item.meta_item_list() { Some(list) => list, None => continue, // skip like historical compilers @@ -98,7 +98,7 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for Collector<'a, 'tcx> { } else { self.tcx.sess.span_err(cfg[0].span(), "invalid argument for `cfg(..)`"); } - } else if item.check_name("wasm_import_module") { + } else if item.check_name(sym::wasm_import_module) { match item.value_str() { Some(s) => lib.wasm_import_module = Some(s), None => { @@ -156,7 +156,7 @@ impl<'a, 'tcx> Collector<'a, 'tcx> { } if lib.cfg.is_some() && !self.tcx.features().link_cfg { feature_gate::emit_feature_err(&self.tcx.sess.parse_sess, - "link_cfg", + sym::link_cfg, span.unwrap(), GateIssue::Language, "is feature gated"); @@ -164,7 +164,7 @@ impl<'a, 'tcx> Collector<'a, 'tcx> { if lib.kind == cstore::NativeStaticNobundle && !self.tcx.features().static_nobundle { feature_gate::emit_feature_err(&self.tcx.sess.parse_sess, - "static_nobundle", + sym::static_nobundle, span.unwrap_or_else(|| syntax_pos::DUMMY_SP), GateIssue::Language, "kind=\"static-nobundle\" is feature gated"); diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 8aa6456ebe77b..1068305a1134c 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -20,6 +20,7 @@ use rustc_data_structures::indexed_vec::Idx; use rustc_errors::{Applicability, DiagnosticBuilder}; use syntax_pos::Span; use syntax::source_map::CompilerDesugaringKind; +use syntax::symbol::sym; use super::borrow_set::BorrowData; use super::{MirBorrowckCtxt}; @@ -1839,7 +1840,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. }) ) = place { let attrs = self.infcx.tcx.get_attrs(*def_id); - let is_thread_local = attrs.iter().any(|attr| attr.check_name("thread_local")); + let is_thread_local = attrs.iter().any(|attr| attr.check_name(sym::thread_local)); debug!( "is_place_thread_local: attrs={:?} is_thread_local={:?}", diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index ad43c8ef66f42..fa490c108c896 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -20,6 +20,7 @@ use std::io; use std::path::PathBuf; use std::rc::Rc; use std::str::FromStr; +use syntax::symbol::sym; use self::mir_util::PassWhere; use polonius_engine::{Algorithm, Output}; @@ -280,7 +281,7 @@ fn dump_annotation<'a, 'gcx, 'tcx>( ) { let tcx = infcx.tcx; let base_def_id = tcx.closure_base_def_id(mir_def_id); - if !tcx.has_attr(base_def_id, "rustc_regions") { + if !tcx.has_attr(base_def_id, sym::rustc_regions) { return; } diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index 83221aca6c5b3..a9d23a0afeabc 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -1,4 +1,5 @@ use syntax::ast::{self, MetaItem}; +use syntax::symbol::{Symbol, sym}; use rustc_data_structures::bit_set::{BitSet, BitSetOperator, HybridBitSet}; use rustc_data_structures::indexed_vec::Idx; @@ -100,9 +101,9 @@ where fn propagate(&mut self) { self.flow_state.propagate(); } } -pub(crate) fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option { +pub(crate) fn has_rustc_mir_with(attrs: &[ast::Attribute], name: Symbol) -> Option { for attr in attrs { - if attr.check_name("rustc_mir") { + if attr.check_name(sym::rustc_mir) { let items = attr.meta_item_list(); for item in items.iter().flat_map(|l| l.iter()) { match item.meta_item() { @@ -158,10 +159,8 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitD return None; }; - let print_preflow_to = - name_found(tcx.sess, attributes, "borrowck_graphviz_preflow"); - let print_postflow_to = - name_found(tcx.sess, attributes, "borrowck_graphviz_postflow"); + let print_preflow_to = name_found(tcx.sess, attributes, sym::borrowck_graphviz_preflow); + let print_postflow_to = name_found(tcx.sess, attributes, sym::borrowck_graphviz_postflow); let mut mbcx = DataflowBuilder { def_id, diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 7aed0bace8c0b..e8070b21bb8c7 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -16,7 +16,7 @@ use rustc::ty::subst::{Kind, InternalSubsts}; use rustc::ty::layout::VariantIdx; use syntax::ast; use syntax::attr; -use syntax::symbol::Symbol; +use syntax::symbol::{Symbol, sym}; use rustc::hir; use crate::hair::constant::{lit_to_const, LitToConstError}; @@ -67,7 +67,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { // Some functions always have overflow checks enabled, // however, they may not get codegen'd, depending on // the settings for the crate they are codegened in. - let mut check_overflow = attr::contains_name(attrs, "rustc_inherit_overflow_checks"); + let mut check_overflow = attr::contains_name(attrs, sym::rustc_inherit_overflow_checks); // Respect -C overflow-checks. check_overflow |= tcx.sess.overflow_checks(); diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 01b1780a2054f..0576bb53d8f42 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -27,6 +27,7 @@ use std::cmp::Ordering; use std::fmt; use syntax::ast; use syntax::ptr::P; +use syntax::symbol::sym; use syntax_pos::Span; #[derive(Clone, Debug)] @@ -978,7 +979,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { self.tcx.sess.span_err(span, "cannot use unions in constant patterns"); PatternKind::Wild } - ty::Adt(adt_def, _) if !self.tcx.has_attr(adt_def.did, "structural_match") => { + ty::Adt(adt_def, _) if !self.tcx.has_attr(adt_def.did, sym::structural_match) => { let path = self.tcx.def_path_str(adt_def.did); let msg = format!( "to use a constant of type `{}` in a pattern, \ @@ -990,7 +991,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { PatternKind::Wild } ty::Ref(_, ty::TyS { sty: ty::Adt(adt_def, _), .. }, _) - if !self.tcx.has_attr(adt_def.did, "structural_match") => { + if !self.tcx.has_attr(adt_def.did, sym::structural_match) => { // HACK(estebank): Side-step ICE #53708, but anything other than erroring here // would be wrong. Returnging `PatternKind::Wild` is not technically correct. let path = self.tcx.def_path_str(adt_def.did); diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 58e474658ead5..2512525b4bb7e 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -2,6 +2,7 @@ use rustc::ty::{self, Ty, TypeAndMut}; use rustc::ty::layout::{self, TyLayout, Size}; use rustc::ty::adjustment::{PointerCast}; use syntax::ast::{FloatTy, IntTy, UintTy}; +use syntax::symbol::sym; use rustc_apfloat::ieee::{Single, Double}; use rustc::mir::interpret::{ @@ -76,9 +77,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> // The src operand does not matter, just its type match src.layout.ty.sty { ty::FnDef(def_id, substs) => { - if self.tcx.has_attr(def_id, "rustc_args_required_const") { - bug!("reifying a fn ptr that requires \ - const arguments"); + if self.tcx.has_attr(def_id, sym::rustc_args_required_const) { + bug!("reifying a fn ptr that requires const arguments"); } let instance: EvalResult<'tcx, _> = ty::Instance::resolve( *self.tcx, diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 078b347fb3f6b..fab07a2290eb5 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -12,7 +12,7 @@ use rustc::lint::builtin::{SAFE_EXTERN_STATICS, SAFE_PACKED_BORROWS, UNUSED_UNSA use rustc::mir::*; use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext}; -use syntax::symbol::Symbol; +use syntax::symbol::{Symbol, sym}; use std::ops::Bound; @@ -612,7 +612,7 @@ fn report_unused_unsafe(tcx: TyCtxt<'_, '_, '_>, fn builtin_derive_def_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Option { debug!("builtin_derive_def_id({:?})", def_id); if let Some(impl_def_id) = tcx.impl_of_method(def_id) { - if tcx.has_attr(impl_def_id, "automatically_derived") { + if tcx.has_attr(impl_def_id, sym::automatically_derived) { debug!("builtin_derive_def_id({:?}) - is {:?}", def_id, impl_def_id); Some(impl_def_id) } else { diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 9a39e07172114..579f75ba51657 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -22,6 +22,7 @@ use rustc::middle::lang_items; use rustc::session::config::nightly_options; use syntax::ast::LitKind; use syntax::feature_gate::{emit_feature_err, GateIssue}; +use syntax::symbol::sym; use syntax_pos::{Span, DUMMY_SP}; use std::fmt; @@ -380,8 +381,8 @@ impl Qualif for IsNotPromotable { !allowed || cx.tcx.get_attrs(def_id).iter().any( - |attr| attr.check_name("thread_local" - )) + |attr| attr.check_name(sym::thread_local) + ) } } } @@ -939,7 +940,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { if self.tcx .get_attrs(def_id) .iter() - .any(|attr| attr.check_name("thread_local")) { + .any(|attr| attr.check_name(sym::thread_local)) { if self.mode != Mode::Fn { span_err!(self.tcx.sess, self.span, E0625, "thread-local statics cannot be \ @@ -994,7 +995,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { if let ty::RawPtr(_) = base_ty.sty { if !self.tcx.features().const_raw_ptr_deref { emit_feature_err( - &self.tcx.sess.parse_sess, "const_raw_ptr_deref", + &self.tcx.sess.parse_sess, sym::const_raw_ptr_deref, self.span, GateIssue::Language, &format!( "dereferencing raw pointers in {}s is unstable", @@ -1018,7 +1019,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { Mode::ConstFn => { if !self.tcx.features().const_fn_union { emit_feature_err( - &self.tcx.sess.parse_sess, "const_fn_union", + &self.tcx.sess.parse_sess, sym::const_fn_union, self.span, GateIssue::Language, "unions in const fn are unstable", ); @@ -1123,7 +1124,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { // in const fn and constants require the feature gate // FIXME: make it unsafe inside const fn and constants emit_feature_err( - &self.tcx.sess.parse_sess, "const_raw_ptr_to_usize_cast", + &self.tcx.sess.parse_sess, sym::const_raw_ptr_to_usize_cast, self.span, GateIssue::Language, &format!( "casting pointers to integers in {}s is unstable", @@ -1149,7 +1150,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { // FIXME: make it unsafe to use these operations emit_feature_err( &self.tcx.sess.parse_sess, - "const_compare_raw_pointers", + sym::const_compare_raw_pointers, self.span, GateIssue::Language, &format!("comparing raw pointers inside {}", self.mode), @@ -1210,7 +1211,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { // const eval transmute calls only with the feature gate if !self.tcx.features().const_transmute { emit_feature_err( - &self.tcx.sess.parse_sess, "const_transmute", + &self.tcx.sess.parse_sess, sym::const_transmute, self.span, GateIssue::Language, &format!("The use of std::mem::transmute() \ is gated in {}s", self.mode)); @@ -1249,7 +1250,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { // Don't allow panics in constants without the feature gate. emit_feature_err( &self.tcx.sess.parse_sess, - "const_panic", + sym::const_panic, self.span, GateIssue::Language, &format!("panicking in {}s is unstable", self.mode), @@ -1260,7 +1261,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { // Check `#[unstable]` const fns or `#[rustc_const_unstable]` // functions without the feature gate active in this crate in // order to report a better error message than the one below. - if !self.span.allows_unstable(&feature.as_str()) { + if !self.span.allows_unstable(feature) { let mut err = self.tcx.sess.struct_span_err(self.span, &format!("`{}` is not yet stable as a const fn", self.tcx.def_path_str(def_id))); @@ -1592,7 +1593,7 @@ impl MirPass for QualifyAndPromoteConstants { if mode == Mode::Static { // `#[thread_local]` statics don't have to be `Sync`. for attr in &tcx.get_attrs(def_id)[..] { - if attr.check_name("thread_local") { + if attr.check_name(sym::thread_local) { return; } } @@ -1616,7 +1617,7 @@ impl MirPass for QualifyAndPromoteConstants { fn args_required_const(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Option> { let attrs = tcx.get_attrs(def_id); - let attr = attrs.iter().find(|a| a.check_name("rustc_args_required_const"))?; + let attr = attrs.iter().find(|a| a.check_name(sym::rustc_args_required_const))?; let mut ret = FxHashSet::default(); for meta in attr.meta_item_list()? { match meta.literal()?.node { diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index 246f876235d71..815821f6ff033 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -1,5 +1,6 @@ use rustc_target::spec::abi::{Abi}; use syntax::ast; +use syntax::symbol::sym; use syntax_pos::Span; use rustc::ty::{self, TyCtxt}; @@ -27,7 +28,7 @@ impl MirPass for SanityCheck { fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource<'tcx>, mir: &mut Mir<'tcx>) { let def_id = src.def_id(); - if !tcx.has_attr(def_id, "rustc_mir") { + if !tcx.has_attr(def_id, sym::rustc_mir) { debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); return; } else { @@ -52,16 +53,16 @@ impl MirPass for SanityCheck { DefinitelyInitializedPlaces::new(tcx, mir, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i])); - if has_rustc_mir_with(&attributes, "rustc_peek_maybe_init").is_some() { + if has_rustc_mir_with(&attributes, sym::rustc_peek_maybe_init).is_some() { sanity_check_via_rustc_peek(tcx, mir, def_id, &attributes, &flow_inits); } - if has_rustc_mir_with(&attributes, "rustc_peek_maybe_uninit").is_some() { + if has_rustc_mir_with(&attributes, sym::rustc_peek_maybe_uninit).is_some() { sanity_check_via_rustc_peek(tcx, mir, def_id, &attributes, &flow_uninits); } - if has_rustc_mir_with(&attributes, "rustc_peek_definite_init").is_some() { + if has_rustc_mir_with(&attributes, sym::rustc_peek_definite_init).is_some() { sanity_check_via_rustc_peek(tcx, mir, def_id, &attributes, &flow_def_inits); } - if has_rustc_mir_with(&attributes, "stop_after_dataflow").is_some() { + if has_rustc_mir_with(&attributes, sym::stop_after_dataflow).is_some() { tcx.sess.fatal("stop_after_dataflow ended compilation"); } } diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 6cb3161382af2..7adf0af31c661 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -15,7 +15,7 @@ use rustc_data_structures::fx::FxHashMap; use syntax::ast::*; use syntax::attr; use syntax::source_map::Spanned; -use syntax::symbol::keywords; +use syntax::symbol::{keywords, sym}; use syntax::ptr::P; use syntax::visit::{self, Visitor}; use syntax::{span_err, struct_span_err, walk_list}; @@ -565,7 +565,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.has_proc_macro_decls = true; } - if attr::contains_name(&item.attrs, "global_allocator") { + if attr::contains_name(&item.attrs, sym::global_allocator) { self.has_global_allocator = true; } @@ -676,8 +676,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } ItemKind::Mod(_) => { // Ensure that `path` attributes on modules are recorded as used (cf. issue #35584). - attr::first_attr_value_str_by_name(&item.attrs, "path"); - if attr::contains_name(&item.attrs, "warn_directory_ownership") { + attr::first_attr_value_str_by_name(&item.attrs, sym::path); + if attr::contains_name(&item.attrs, sym::warn_directory_ownership) { let lint = lint::builtin::LEGACY_DIRECTORY_OWNERSHIP; let msg = "cannot declare a new module at this location"; self.session.buffer_lint(lint, item.id, item.span, msg); diff --git a/src/librustc_passes/layout_test.rs b/src/librustc_passes/layout_test.rs index 7041a5593abbf..c865845b5e367 100644 --- a/src/librustc_passes/layout_test.rs +++ b/src/librustc_passes/layout_test.rs @@ -12,6 +12,7 @@ use rustc::ty::ParamEnv; use rustc::ty::Ty; use rustc::ty::TyCtxt; use syntax::ast::Attribute; +use syntax::symbol::sym; pub fn test_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { if tcx.features().rustc_attrs { @@ -32,7 +33,7 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for VarianceTest<'a, 'tcx> { if let ItemKind::Ty(..) = item.node { for attr in self.tcx.get_attrs(item_def_id).iter() { - if attr.check_name("rustc_layout") { + if attr.check_name(sym::rustc_layout) { self.dump_layout_of(item_def_id, item, attr); } } diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index 2d35a0de7953f..37917aaa4a80f 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -25,6 +25,7 @@ use rustc::ty::query::Providers; use rustc::ty::subst::{InternalSubsts, SubstsRef}; use rustc::util::nodemap::{ItemLocalSet, HirIdSet}; use rustc::hir; +use syntax::symbol::sym; use syntax_pos::{Span, DUMMY_SP}; use log::debug; use Promotability::*; @@ -335,7 +336,7 @@ fn check_expr_kind<'a, 'tcx>( if v.in_static { for attr in &v.tcx.get_attrs(did)[..] { - if attr.check_name("thread_local") { + if attr.check_name(sym::thread_local) { debug!("Reference to Static(id={:?}) is unpromotable \ due to a #[thread_local] attribute", did); return NotPromotable; diff --git a/src/librustc_plugin/build.rs b/src/librustc_plugin/build.rs index 31018a7cd7a3c..8259419c64aeb 100644 --- a/src/librustc_plugin/build.rs +++ b/src/librustc_plugin/build.rs @@ -1,6 +1,7 @@ //! Used by `rustc` when compiling a plugin crate. use syntax::attr; +use syntax::symbol::sym; use syntax_pos::Span; use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir; @@ -15,8 +16,7 @@ struct RegistrarFinder { impl<'v> ItemLikeVisitor<'v> for RegistrarFinder { fn visit_item(&mut self, item: &hir::Item) { if let hir::ItemKind::Fn(..) = item.node { - if attr::contains_name(&item.attrs, - "plugin_registrar") { + if attr::contains_name(&item.attrs, sym::plugin_registrar) { self.registrars.push((item.hir_id, item.span)); } } diff --git a/src/librustc_plugin/load.rs b/src/librustc_plugin/load.rs index 8b86bddb29f4e..43eddbb653fee 100644 --- a/src/librustc_plugin/load.rs +++ b/src/librustc_plugin/load.rs @@ -11,6 +11,7 @@ use std::mem; use std::path::PathBuf; use syntax::ast; use syntax::span_err; +use syntax::symbol::sym; use syntax_pos::{Span, DUMMY_SP}; /// Pointer to a registrar function. @@ -45,7 +46,7 @@ pub fn load_plugins(sess: &Session, // the feature enabled will result in an error later... if sess.features_untracked().plugin { for attr in &krate.attrs { - if !attr.check_name("plugin") { + if !attr.check_name(sym::plugin) { continue; } diff --git a/src/librustc_plugin/registry.rs b/src/librustc_plugin/registry.rs index 5c5b6f232b271..913657b2934e4 100644 --- a/src/librustc_plugin/registry.rs +++ b/src/librustc_plugin/registry.rs @@ -49,7 +49,7 @@ pub struct Registry<'a> { pub llvm_passes: Vec, #[doc(hidden)] - pub attributes: Vec<(String, AttributeType)>, + pub attributes: Vec<(Symbol, AttributeType)>, } impl<'a> Registry<'a> { @@ -169,7 +169,7 @@ impl<'a> Registry<'a> { /// Registered attributes will bypass the `custom_attribute` feature gate. /// `Whitelisted` attributes will additionally not trigger the `unused_attribute` /// lint. `CrateLevel` attributes will not be allowed on anything other than a crate. - pub fn register_attribute(&mut self, name: String, ty: AttributeType) { + pub fn register_attribute(&mut self, name: Symbol, ty: AttributeType) { self.attributes.push((name, ty)); } } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index e561b387389e7..cd21713cddf97 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -27,7 +27,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; use syntax::ast::Ident; use syntax::attr; -use syntax::symbol::keywords; +use syntax::symbol::{keywords, sym}; use syntax_pos::Span; use std::{cmp, fmt, mem}; @@ -260,7 +260,8 @@ fn def_id_visibility<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) ctor_vis = ty::Visibility::Restricted( DefId::local(CRATE_DEF_INDEX)); let attrs = tcx.get_attrs(variant.def_id); - span = attr::find_by_name(&attrs, "non_exhaustive").unwrap().span; + span = attr::find_by_name(&attrs, sym::non_exhaustive) + .unwrap().span; descr = "crate-visible"; } @@ -291,7 +292,7 @@ fn def_id_visibility<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) if adt_def.non_enum_variant().is_field_list_non_exhaustive() { ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)); - span = attr::find_by_name(&item.attrs, "non_exhaustive") + span = attr::find_by_name(&item.attrs, sym::non_exhaustive) .unwrap().span; descr = "crate-visible"; } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 3c5760c746fc3..cf09e31bb6282 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -37,7 +37,7 @@ use syntax::feature_gate::is_builtin_attr; use syntax::parse::token::{self, Token}; use syntax::span_err; use syntax::std_inject::injected_crate_name; -use syntax::symbol::keywords; +use syntax::symbol::{keywords, sym}; use syntax::visit::{self, Visitor}; use syntax_pos::{Span, DUMMY_SP}; @@ -257,7 +257,7 @@ impl<'a> Resolver<'a> { } ast::UseTreeKind::Glob => { let subclass = GlobImport { - is_prelude: attr::contains_name(&item.attrs, "prelude_import"), + is_prelude: attr::contains_name(&item.attrs, sym::prelude_import), max_vis: Cell::new(ty::Visibility::Invisible), }; self.add_import_directive( @@ -427,7 +427,7 @@ impl<'a> Resolver<'a> { let module_kind = ModuleKind::Def(DefKind::Mod, def_id, ident.name); let module = self.arenas.alloc_module(ModuleData { no_implicit_prelude: parent.no_implicit_prelude || { - attr::contains_name(&item.attrs, "no_implicit_prelude") + attr::contains_name(&item.attrs, sym::no_implicit_prelude) }, ..ModuleData::new(Some(parent), module_kind, def_id, expansion, item.span) }); @@ -456,12 +456,12 @@ impl<'a> Resolver<'a> { // Functions introducing procedural macros reserve a slot // in the macro namespace as well (see #52225). - if attr::contains_name(&item.attrs, "proc_macro") || - attr::contains_name(&item.attrs, "proc_macro_attribute") { + if attr::contains_name(&item.attrs, sym::proc_macro) || + attr::contains_name(&item.attrs, sym::proc_macro_attribute) { let res = Res::Def(DefKind::Macro(MacroKind::ProcMacroStub), res.def_id()); self.define(parent, ident, MacroNS, (res, vis, sp, expansion)); } - if let Some(attr) = attr::find_by_name(&item.attrs, "proc_macro_derive") { + if let Some(attr) = attr::find_by_name(&item.attrs, sym::proc_macro_derive) { if let Some(trait_attr) = attr.meta_item_list().and_then(|list| list.get(0).cloned()) { if let Some(ident) = trait_attr.ident() { @@ -518,7 +518,7 @@ impl<'a> Resolver<'a> { let mut ctor_vis = vis; - let has_non_exhaustive = attr::contains_name(&item.attrs, "non_exhaustive"); + let has_non_exhaustive = attr::contains_name(&item.attrs, sym::non_exhaustive); // If the structure is marked as non_exhaustive then lower the visibility // to within the crate. @@ -599,7 +599,7 @@ impl<'a> Resolver<'a> { // If the variant is marked as non_exhaustive then lower the visibility to within the // crate. let mut ctor_vis = vis; - let has_non_exhaustive = attr::contains_name(&variant.node.attrs, "non_exhaustive"); + let has_non_exhaustive = attr::contains_name(&variant.node.attrs, sym::non_exhaustive); if has_non_exhaustive && vis == ty::Visibility::Public { ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)); } @@ -825,7 +825,7 @@ impl<'a> Resolver<'a> { let mut import_all = None; let mut single_imports = Vec::new(); for attr in &item.attrs { - if attr.check_name("macro_use") { + if attr.check_name(sym::macro_use) { if self.current_module.parent.is_some() { span_err!(self.session, item.span, E0468, "an `extern crate` loading macros must be at the crate root"); @@ -908,7 +908,7 @@ impl<'a> Resolver<'a> { /// Returns `true` if this attribute list contains `macro_use`. fn contains_macro_use(&mut self, attrs: &[ast::Attribute]) -> bool { for attr in attrs { - if attr.check_name("macro_escape") { + if attr.check_name(sym::macro_escape) { let msg = "macro_escape is a deprecated synonym for macro_use"; let mut err = self.session.struct_span_warn(attr.span, msg); if let ast::AttrStyle::Inner = attr.style { @@ -916,7 +916,7 @@ impl<'a> Resolver<'a> { } else { err.emit(); } - } else if !attr.check_name("macro_use") { + } else if !attr.check_name(sym::macro_use) { continue; } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 18da89b9099a5..0dd6f378730f9 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -43,7 +43,7 @@ use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy}; use syntax::ext::base::SyntaxExtension; use syntax::ext::base::Determinacy::{self, Determined, Undetermined}; use syntax::ext::base::MacroKind; -use syntax::symbol::{Symbol, keywords}; +use syntax::symbol::{Symbol, keywords, sym}; use syntax::util::lev_distance::find_best_match_for_name; use syntax::visit::{self, FnKind, Visitor}; @@ -1964,7 +1964,7 @@ impl<'a> Resolver<'a> { keywords::Invalid.name(), ); let graph_root = arenas.alloc_module(ModuleData { - no_implicit_prelude: attr::contains_name(&krate.attrs, "no_implicit_prelude"), + no_implicit_prelude: attr::contains_name(&krate.attrs, sym::no_implicit_prelude), ..ModuleData::new(None, root_module_kind, root_def_id, Mark::root(), krate.span) }); let mut module_map = FxHashMap::default(); @@ -1978,9 +1978,9 @@ impl<'a> Resolver<'a> { session.opts.externs.iter().map(|kv| (Ident::from_str(kv.0), Default::default())) .collect(); - if !attr::contains_name(&krate.attrs, "no_core") { + if !attr::contains_name(&krate.attrs, sym::no_core) { extern_prelude.insert(Ident::from_str("core"), Default::default()); - if !attr::contains_name(&krate.attrs, "no_std") { + if !attr::contains_name(&krate.attrs, sym::no_std) { extern_prelude.insert(Ident::from_str("std"), Default::default()); if session.rust_2018() { extern_prelude.insert(Ident::from_str("meta"), Default::default()); diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 79a92d595c2ed..62f2768888ad7 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -22,7 +22,7 @@ use syntax::ext::tt::macro_rules; use syntax::feature_gate::{ feature_err, is_builtin_attr_name, AttributeGate, GateIssue, Stability, BUILTIN_ATTRIBUTES, }; -use syntax::symbol::{Symbol, keywords}; +use syntax::symbol::{Symbol, keywords, sym}; use syntax::visit::Visitor; use syntax::util::lev_distance::find_best_match_for_name; use syntax_pos::{Span, DUMMY_SP}; @@ -313,7 +313,8 @@ impl<'a> Resolver<'a> { if !features.rustc_attrs { let msg = "unless otherwise specified, attributes with the prefix \ `rustc_` are reserved for internal compiler diagnostics"; - self.report_unknown_attribute(path.span, &name, msg, "rustc_attrs"); + self.report_unknown_attribute(path.span, &name, msg, + sym::rustc_attrs); } } else if !features.custom_attribute { let msg = format!("The attribute `{}` is currently unknown to the \ @@ -323,7 +324,7 @@ impl<'a> Resolver<'a> { path.span, &name, &msg, - "custom_attribute", + sym::custom_attribute, ); } } @@ -345,7 +346,7 @@ impl<'a> Resolver<'a> { Ok((res, self.get_macro(res))) } - fn report_unknown_attribute(&self, span: Span, name: &str, msg: &str, feature: &str) { + fn report_unknown_attribute(&self, span: Span, name: &str, msg: &str, feature: Symbol) { let mut err = feature_err( &self.session.parse_sess, feature, @@ -693,7 +694,7 @@ impl<'a> Resolver<'a> { WhereToResolve::LegacyPluginHelpers => { if (use_prelude || rust_2015) && self.session.plugin_attributes.borrow().iter() - .any(|(name, _)| ident.name == &**name) { + .any(|(name, _)| ident.name == *name) { let binding = (Res::NonMacroAttr(NonMacroAttrKind::LegacyPluginHelper), ty::Visibility::Public, DUMMY_SP, Mark::root()) .to_name_binding(self.arenas); @@ -1106,7 +1107,7 @@ impl<'a> Resolver<'a> { let ident = ident.modern(); self.macro_names.insert(ident); let res = Res::Def(DefKind::Macro(MacroKind::Bang), def_id); - let is_macro_export = attr::contains_name(&item.attrs, "macro_export"); + let is_macro_export = attr::contains_name(&item.attrs, sym::macro_export); let vis = if is_macro_export { ty::Visibility::Public } else { @@ -1124,7 +1125,7 @@ impl<'a> Resolver<'a> { self.define(module, ident, MacroNS, (res, vis, item.span, expansion, IsMacroExport)); } else { - if !attr::contains_name(&item.attrs, "rustc_doc_only_macro") { + if !attr::contains_name(&item.attrs, sym::rustc_doc_only_macro) { self.check_reserved_macro_name(ident, MacroNS); } self.unused_macros.insert(def_id); diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index f3e0fb32ec2dc..cb2454aa4b56e 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -879,7 +879,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let mut result = String::new(); for attr in attrs { - if attr.check_name("doc") { + if attr.check_name(sym::doc) { if let Some(val) = attr.value_str() { if attr.is_sugared_doc { result.push_str(&strip_doc_comment_decoration(&val.as_str())); @@ -889,10 +889,10 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { result.push('\n'); } else if let Some(meta_list) = attr.meta_item_list() { meta_list.into_iter() - .filter(|it| it.check_name("include")) + .filter(|it| it.check_name(sym::include)) .filter_map(|it| it.meta_item_list().map(|l| l.to_owned())) .flat_map(|it| it) - .filter(|meta| meta.check_name("contents")) + .filter(|meta| meta.check_name(sym::contents)) .filter_map(|meta| meta.value_str()) .for_each(|val| { result.push_str(&val.as_str()); diff --git a/src/librustc_traits/lowering/mod.rs b/src/librustc_traits/lowering/mod.rs index 50c2130263295..580b1571e52bb 100644 --- a/src/librustc_traits/lowering/mod.rs +++ b/src/librustc_traits/lowering/mod.rs @@ -21,6 +21,7 @@ use rustc::ty::query::Providers; use rustc::ty::{self, List, TyCtxt}; use rustc::ty::subst::{Subst, InternalSubsts}; use syntax::ast; +use syntax::symbol::sym; use std::iter; @@ -640,11 +641,11 @@ impl<'a, 'tcx> ClauseDumper<'a, 'tcx> { for attr in attrs { let mut clauses = None; - if attr.check_name("rustc_dump_program_clauses") { + if attr.check_name(sym::rustc_dump_program_clauses) { clauses = Some(self.tcx.program_clauses_for(def_id)); } - if attr.check_name("rustc_dump_env_program_clauses") { + if attr.check_name(sym::rustc_dump_env_program_clauses) { let environment = self.tcx.environment(def_id); clauses = Some(self.tcx.program_clauses_for_env(environment)); } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index da47ccf38a026..caefe12421155 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -25,6 +25,7 @@ use syntax::ast; use syntax::feature_gate::{GateIssue, emit_feature_err}; use syntax::ptr::P; use syntax::util::lev_distance::find_best_match_for_name; +use syntax::symbol::sym; use syntax_pos::{DUMMY_SP, Span, MultiSpan}; use crate::util::common::ErrorReported; use crate::util::nodemap::FxHashMap; @@ -802,7 +803,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } else { "parenthetical notation is only stable when used with `Fn`-family traits" }; - emit_feature_err(&self.tcx().sess.parse_sess, "unboxed_closures", + emit_feature_err(&self.tcx().sess.parse_sess, sym::unboxed_closures, span, GateIssue::Language, msg); } diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 008975068e581..90b2643d165be 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -68,6 +68,7 @@ use smallvec::{smallvec, SmallVec}; use std::ops::Deref; use syntax::feature_gate; use syntax::ptr::P; +use syntax::symbol::sym; use syntax_pos; struct Coerce<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { @@ -620,7 +621,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion { feature_gate::emit_feature_err(&self.tcx.sess.parse_sess, - "unsized_tuple_coercion", + sym::unsized_tuple_coercion, self.cause.span, feature_gate::GateIssue::Language, feature_gate::EXPLAIN_UNSIZED_TUPLE_COERCION); diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 1699447886aef..8d68179b495c6 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -2,6 +2,7 @@ use crate::check::FnCtxt; use rustc::infer::InferOk; use rustc::traits::{self, ObligationCause, ObligationCauseCode}; +use syntax::symbol::sym; use syntax::util::parser::PREC_POSTFIX; use syntax_pos::Span; use rustc::hir; @@ -197,7 +198,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // // FIXME? Other potential candidate methods: `as_ref` and // `as_mut`? - .find(|a| a.check_name("rustc_conversion_suggestion")).is_some() + .find(|a| a.check_name(sym::rustc_conversion_suggestion)).is_some() }); methods diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index dc73ada1506c8..a184a2daeb6ad 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -123,7 +123,7 @@ use syntax::attr; use syntax::feature_gate::{GateIssue, emit_feature_err}; use syntax::ptr::P; use syntax::source_map::{DUMMY_SP, original_sp}; -use syntax::symbol::{Symbol, LocalInternedString, keywords}; +use syntax::symbol::{Symbol, LocalInternedString, keywords, sym}; use syntax::util::lev_distance::find_best_match_for_name; use std::cell::{Cell, RefCell, Ref, RefMut}; @@ -1840,7 +1840,7 @@ pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if vs.is_empty() { let attributes = tcx.get_attrs(def_id); - if let Some(attr) = attr::find_by_name(&attributes, "repr") { + if let Some(attr) = attr::find_by_name(&attributes, sym::repr) { struct_span_err!( tcx.sess, attr.span, E0084, "unsupported representation for zero-variant enum") @@ -1853,7 +1853,7 @@ pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if repr_type_ty == tcx.types.i128 || repr_type_ty == tcx.types.u128 { if !tcx.features().repr128 { emit_feature_err(&tcx.sess.parse_sess, - "repr128", + sym::repr128, sp, GateIssue::Language, "repr with 128-bit type is unstable"); @@ -5499,7 +5499,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { span: Span) { // We're only interested in functions tagged with // #[rustc_args_required_const], so ignore anything that's not. - if !self.tcx.has_attr(def_id, "rustc_args_required_const") { + if !self.tcx.has_attr(def_id, sym::rustc_args_required_const) { return } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index fd7d6fe694ccd..b009c8ea6dce1 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -13,6 +13,7 @@ use rustc::infer::opaque_types::may_define_existential_type; use syntax::ast; use syntax::feature_gate::{self, GateIssue}; use syntax_pos::Span; +use syntax::symbol::sym; use errors::{DiagnosticBuilder, DiagnosticId}; use rustc::hir::itemlikevisit::ParItemLikeVisitor; @@ -796,7 +797,7 @@ fn check_method_receiver<'fcx, 'gcx, 'tcx>(fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, // report error, would have worked with arbitrary_self_types feature_gate::feature_err( &fcx.tcx.sess.parse_sess, - "arbitrary_self_types", + sym::arbitrary_self_types, span, GateIssue::Language, &format!( diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index bf978352faee9..ecb8e09ec2461 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -16,6 +16,7 @@ use rustc::mir::interpret::ConstValue; use rustc::util::nodemap::DefIdSet; use rustc_data_structures::sync::Lrc; use std::mem; +use syntax::symbol::sym; use syntax_pos::Span; /////////////////////////////////////////////////////////////////////////// @@ -36,8 +37,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let item_def_id = self.tcx.hir().local_def_id(item_id); // This attribute causes us to dump some writeback information - // in the form of errors, which is used for unit tests. - let rustc_dump_user_substs = self.tcx.has_attr(item_def_id, "rustc_dump_user_substs"); + // in the form of errors, which is uSymbolfor unit tests. + let rustc_dump_user_substs = self.tcx.has_attr(item_def_id, sym::rustc_dump_user_substs); let mut wbcx = WritebackCx::new(self, body, rustc_dump_user_substs); for arg in &body.arguments { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 4185999fdd6d7..29b4708940955 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -39,7 +39,7 @@ use syntax::ast::{Ident, MetaItemKind}; use syntax::attr::{InlineAttr, OptimizeAttr, list_contains_name, mark_used}; use syntax::source_map::Spanned; use syntax::feature_gate; -use syntax::symbol::{keywords, Symbol}; +use syntax::symbol::{keywords, Symbol, sym}; use syntax_pos::{Span, DUMMY_SP}; use rustc::hir::def::{CtorKind, Res, DefKind}; @@ -750,7 +750,7 @@ fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty:: _ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"), }; - let paren_sugar = tcx.has_attr(def_id, "rustc_paren_sugar"); + let paren_sugar = tcx.has_attr(def_id, sym::rustc_paren_sugar); if paren_sugar && !tcx.features().unboxed_closures { let mut err = tcx.sess.struct_span_err( item.span, @@ -765,7 +765,7 @@ fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty:: err.emit(); } - let is_marker = tcx.has_attr(def_id, "marker"); + let is_marker = tcx.has_attr(def_id, sym::marker); let def_path_hash = tcx.def_path_hash(def_id); let def = ty::TraitDef::new(def_id, unsafety, paren_sugar, is_auto, is_marker, def_path_hash); tcx.alloc_trait_def(def) @@ -2382,7 +2382,7 @@ fn from_target_feature( tcx: TyCtxt<'_, '_, '_>, id: DefId, attr: &ast::Attribute, - whitelist: &FxHashMap>, + whitelist: &FxHashMap>, target_features: &mut Vec, ) { let list = match attr.meta_item_list() { @@ -2392,7 +2392,7 @@ fn from_target_feature( let rust_features = tcx.features(); for item in list { // Only `enable = ...` is accepted in the meta item list - if !item.check_name("enable") { + if !item.check_name(sym::enable) { let msg = "#[target_feature(..)] only accepts sub-keys of `enable` \ currently"; tcx.sess.span_err(item.span(), &msg); @@ -2435,29 +2435,29 @@ fn from_target_feature( }; // Only allow features whose feature gates have been enabled - let allowed = match feature_gate.as_ref().map(|s| &**s) { - Some("arm_target_feature") => rust_features.arm_target_feature, - Some("aarch64_target_feature") => rust_features.aarch64_target_feature, - Some("hexagon_target_feature") => rust_features.hexagon_target_feature, - Some("powerpc_target_feature") => rust_features.powerpc_target_feature, - Some("mips_target_feature") => rust_features.mips_target_feature, - Some("avx512_target_feature") => rust_features.avx512_target_feature, - Some("mmx_target_feature") => rust_features.mmx_target_feature, - Some("sse4a_target_feature") => rust_features.sse4a_target_feature, - Some("tbm_target_feature") => rust_features.tbm_target_feature, - Some("wasm_target_feature") => rust_features.wasm_target_feature, - Some("cmpxchg16b_target_feature") => rust_features.cmpxchg16b_target_feature, - Some("adx_target_feature") => rust_features.adx_target_feature, - Some("movbe_target_feature") => rust_features.movbe_target_feature, - Some("rtm_target_feature") => rust_features.rtm_target_feature, - Some("f16c_target_feature") => rust_features.f16c_target_feature, + let allowed = match feature_gate.as_ref().map(|s| *s) { + Some(sym::arm_target_feature) => rust_features.arm_target_feature, + Some(sym::aarch64_target_feature) => rust_features.aarch64_target_feature, + Some(sym::hexagon_target_feature) => rust_features.hexagon_target_feature, + Some(sym::powerpc_target_feature) => rust_features.powerpc_target_feature, + Some(sym::mips_target_feature) => rust_features.mips_target_feature, + Some(sym::avx512_target_feature) => rust_features.avx512_target_feature, + Some(sym::mmx_target_feature) => rust_features.mmx_target_feature, + Some(sym::sse4a_target_feature) => rust_features.sse4a_target_feature, + Some(sym::tbm_target_feature) => rust_features.tbm_target_feature, + Some(sym::wasm_target_feature) => rust_features.wasm_target_feature, + Some(sym::cmpxchg16b_target_feature) => rust_features.cmpxchg16b_target_feature, + Some(sym::adx_target_feature) => rust_features.adx_target_feature, + Some(sym::movbe_target_feature) => rust_features.movbe_target_feature, + Some(sym::rtm_target_feature) => rust_features.rtm_target_feature, + Some(sym::f16c_target_feature) => rust_features.f16c_target_feature, Some(name) => bug!("unknown target feature gate {}", name), None => true, }; if !allowed && id.is_local() { feature_gate::emit_feature_err( &tcx.sess.parse_sess, - feature_gate.as_ref().unwrap(), + feature_gate.unwrap(), item.span(), feature_gate::GateIssue::Language, &format!("the target feature `{}` is currently unstable", feature), @@ -2512,13 +2512,13 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen let mut inline_span = None; for attr in attrs.iter() { - if attr.check_name("cold") { + if attr.check_name(sym::cold) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD; - } else if attr.check_name("allocator") { + } else if attr.check_name(sym::allocator) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR; - } else if attr.check_name("unwind") { + } else if attr.check_name(sym::unwind) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::UNWIND; - } else if attr.check_name("ffi_returns_twice") { + } else if attr.check_name(sym::ffi_returns_twice) { if tcx.is_foreign_item(id) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE; } else { @@ -2530,21 +2530,21 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen "`#[ffi_returns_twice]` may only be used on foreign functions" ).emit(); } - } else if attr.check_name("rustc_allocator_nounwind") { + } else if attr.check_name(sym::rustc_allocator_nounwind) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND; - } else if attr.check_name("naked") { + } else if attr.check_name(sym::naked) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED; - } else if attr.check_name("no_mangle") { + } else if attr.check_name(sym::no_mangle) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE; - } else if attr.check_name("rustc_std_internal_symbol") { + } else if attr.check_name(sym::rustc_std_internal_symbol) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL; - } else if attr.check_name("no_debug") { + } else if attr.check_name(sym::no_debug) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_DEBUG; - } else if attr.check_name("used") { + } else if attr.check_name(sym::used) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED; - } else if attr.check_name("thread_local") { + } else if attr.check_name(sym::thread_local) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL; - } else if attr.check_name("export_name") { + } else if attr.check_name(sym::export_name) { if let Some(s) = attr.value_str() { if s.as_str().contains("\0") { // `#[export_name = ...]` will be converted to a null-terminated string, @@ -2558,7 +2558,7 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen } codegen_fn_attrs.export_name = Some(s); } - } else if attr.check_name("target_feature") { + } else if attr.check_name(sym::target_feature) { if tcx.fn_sig(id).unsafety() == Unsafety::Normal { let msg = "#[target_feature(..)] can only be applied to \ `unsafe` function"; @@ -2571,11 +2571,11 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen &whitelist, &mut codegen_fn_attrs.target_features, ); - } else if attr.check_name("linkage") { + } else if attr.check_name(sym::linkage) { if let Some(val) = attr.value_str() { codegen_fn_attrs.linkage = Some(linkage_by_name(tcx, id, &val.as_str())); } - } else if attr.check_name("link_section") { + } else if attr.check_name(sym::link_section) { if let Some(val) = attr.value_str() { if val.as_str().bytes().any(|b| b == 0) { let msg = format!( @@ -2588,7 +2588,7 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen codegen_fn_attrs.link_section = Some(val); } } - } else if attr.check_name("link_name") { + } else if attr.check_name(sym::link_name) { codegen_fn_attrs.link_name = attr.value_str(); } } @@ -2613,9 +2613,9 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen "expected one argument" ); InlineAttr::None - } else if list_contains_name(&items[..], "always") { + } else if list_contains_name(&items[..], sym::always) { InlineAttr::Always - } else if list_contains_name(&items[..], "never") { + } else if list_contains_name(&items[..], sym::never) { InlineAttr::Never } else { span_err!( @@ -2649,9 +2649,9 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen if items.len() != 1 { err(attr.span, "expected one argument"); OptimizeAttr::None - } else if list_contains_name(&items[..], "size") { + } else if list_contains_name(&items[..], sym::size) { OptimizeAttr::Size - } else if list_contains_name(&items[..], "speed") { + } else if list_contains_name(&items[..], sym::speed) { OptimizeAttr::Speed } else { err(items[0].span(), "invalid argument"); diff --git a/src/librustc_typeck/outlives/mod.rs b/src/librustc_typeck/outlives/mod.rs index e3e2fe7106a08..a6b5b99982ec6 100644 --- a/src/librustc_typeck/outlives/mod.rs +++ b/src/librustc_typeck/outlives/mod.rs @@ -5,6 +5,7 @@ use rustc::ty::query::Providers; use rustc::ty::subst::UnpackedKind; use rustc::ty::{self, CratePredicatesMap, TyCtxt}; use rustc_data_structures::sync::Lrc; +use syntax::symbol::sym; mod explicit; mod implicit_infer; @@ -40,7 +41,7 @@ fn inferred_outlives_of<'a, 'tcx>( .map(|p| *p) .unwrap_or(&[]); - if tcx.has_attr(item_def_id, "rustc_outlives") { + if tcx.has_attr(item_def_id, sym::rustc_outlives) { let mut pred: Vec = predicates .iter() .map(|out_pred| match out_pred { diff --git a/src/librustc_typeck/outlives/test.rs b/src/librustc_typeck/outlives/test.rs index e10c836120718..54fd4fad1d195 100644 --- a/src/librustc_typeck/outlives/test.rs +++ b/src/librustc_typeck/outlives/test.rs @@ -1,6 +1,7 @@ use rustc::hir; use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::ty::TyCtxt; +use syntax::symbol::sym; pub fn test_inferred_outlives<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { tcx.hir() @@ -18,7 +19,7 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for OutlivesTest<'a, 'tcx> { // For unit testing: check for a special "rustc_outlives" // attribute and report an error with various results if found. - if self.tcx.has_attr(item_def_id, "rustc_outlives") { + if self.tcx.has_attr(item_def_id, sym::rustc_outlives) { let inferred_outlives_of = self.tcx.inferred_outlives_of(item_def_id); span_err!( self.tcx.sess, diff --git a/src/librustc_typeck/variance/test.rs b/src/librustc_typeck/variance/test.rs index d04b1b276a2cc..b5195826b8631 100644 --- a/src/librustc_typeck/variance/test.rs +++ b/src/librustc_typeck/variance/test.rs @@ -1,6 +1,7 @@ use rustc::hir; use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::ty::TyCtxt; +use syntax::symbol::sym; pub fn test_variance<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { tcx.hir().krate().visit_all_item_likes(&mut VarianceTest { tcx }); @@ -16,7 +17,7 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for VarianceTest<'a, 'tcx> { // For unit testing: check for a special "rustc_variance" // attribute and report an error with various results if found. - if self.tcx.has_attr(item_def_id, "rustc_variance") { + if self.tcx.has_attr(item_def_id, sym::rustc_variance) { let variances_of = self.tcx.variances_of(item_def_id); span_err!(self.tcx.sess, item.span, diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index d9d6b8e07e994..15108a7dbb91c 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -4,6 +4,7 @@ use std::iter::once; use syntax::ast; use syntax::ext::base::{MacroKind, SyntaxExtension}; +use syntax::symbol::sym; use syntax_pos::Span; use rustc::hir; @@ -186,7 +187,7 @@ pub fn build_external_trait(cx: &DocContext<'_>, did: DefId) -> clean::Trait { let generics = (cx.tcx.generics_of(did), &predicates).clean(cx); let generics = filter_non_trait_generics(did, generics); let (generics, supertrait_bounds) = separate_supertrait_bounds(generics); - let is_spotlight = load_attrs(cx, did).has_doc_flag("spotlight"); + let is_spotlight = load_attrs(cx, did).has_doc_flag(sym::spotlight); let is_auto = cx.tcx.trait_is_auto(did); clean::Trait { auto: auto_trait, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 3a260db806520..6790b13dbf8d5 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -32,6 +32,7 @@ use syntax::ext::base::MacroKind; use syntax::source_map::{dummy_spanned, Spanned}; use syntax::ptr::P; use syntax::symbol::keywords::{self, Keyword}; +use syntax::symbol::{Symbol, sym}; use syntax::symbol::InternedString; use syntax_pos::{self, Pos, FileName}; @@ -170,7 +171,7 @@ impl<'a, 'tcx> Clean for visit_ast::RustdocVisitor<'a, 'tcx> { // `compiler_builtins` should be masked too, but we can't apply // `#[doc(masked)]` to the injected `extern crate` because it's unstable. if it.is_extern_crate() - && (it.attrs.has_doc_flag("masked") + && (it.attrs.has_doc_flag(sym::masked) || self.cx.tcx.is_compiler_builtins(it.def_id.krate)) { masked_crates.insert(it.def_id.krate); @@ -261,9 +262,9 @@ impl Clean for CrateNum { if let Res::Def(DefKind::Mod, def_id) = res { let attrs = cx.tcx.get_attrs(def_id).clean(cx); let mut prim = None; - for attr in attrs.lists("doc") { + for attr in attrs.lists(sym::doc) { if let Some(v) = attr.value_str() { - if attr.check_name("primitive") { + if attr.check_name(sym::primitive) { prim = PrimitiveType::from_str(&v.as_str()); if prim.is_some() { break; @@ -305,9 +306,9 @@ impl Clean for CrateNum { if let Res::Def(DefKind::Mod, def_id) = res { let attrs = cx.tcx.get_attrs(def_id).clean(cx); let mut keyword = None; - for attr in attrs.lists("doc") { + for attr in attrs.lists(sym::doc) { if let Some(v) = attr.value_str() { - if attr.check_name("keyword") { + if attr.check_name(sym::keyword) { keyword = Keyword::from_str(&v.as_str()).ok() .map(|x| x.name().to_string()); if keyword.is_some() { @@ -501,7 +502,7 @@ impl Item { pub fn is_non_exhaustive(&self) -> bool { self.attrs.other_attrs.iter() - .any(|a| a.check_name("non_exhaustive")) + .any(|a| a.check_name(sym::non_exhaustive)) } /// Returns a documentation-level item type from the item. @@ -669,7 +670,7 @@ impl Clean for doctree::Module { pub struct ListAttributesIter<'a> { attrs: slice::Iter<'a, ast::Attribute>, current_list: vec::IntoIter, - name: &'a str + name: Symbol, } impl<'a> Iterator for ListAttributesIter<'a> { @@ -702,11 +703,11 @@ impl<'a> Iterator for ListAttributesIter<'a> { pub trait AttributesExt { /// Finds an attribute as List and returns the list of attributes nested inside. - fn lists<'a>(&'a self, name: &'a str) -> ListAttributesIter<'a>; + fn lists<'a>(&'a self, name: Symbol) -> ListAttributesIter<'a>; } impl AttributesExt for [ast::Attribute] { - fn lists<'a>(&'a self, name: &'a str) -> ListAttributesIter<'a> { + fn lists<'a>(&'a self, name: Symbol) -> ListAttributesIter<'a> { ListAttributesIter { attrs: self.iter(), current_list: Vec::new().into_iter(), @@ -717,11 +718,11 @@ impl AttributesExt for [ast::Attribute] { pub trait NestedAttributesExt { /// Returns `true` if the attribute list contains a specific `Word` - fn has_word(self, word: &str) -> bool; + fn has_word(self, word: Symbol) -> bool; } impl> NestedAttributesExt for I { - fn has_word(self, word: &str) -> bool { + fn has_word(self, word: Symbol) -> bool { self.into_iter().any(|attr| attr.is_word() && attr.check_name(word)) } } @@ -803,7 +804,7 @@ impl Attributes { if let ast::MetaItemKind::List(ref nmis) = mi.node { if nmis.len() == 1 { if let MetaItem(ref cfg_mi) = nmis[0] { - if cfg_mi.check_name("cfg") { + if cfg_mi.check_name(sym::cfg) { if let ast::MetaItemKind::List(ref cfg_nmis) = cfg_mi.node { if cfg_nmis.len() == 1 { if let MetaItem(ref content_mi) = cfg_nmis[0] { @@ -827,7 +828,7 @@ impl Attributes { { mi.meta_item_list().and_then(|list| { for meta in list { - if meta.check_name("include") { + if meta.check_name(sym::include) { // the actual compiled `#[doc(include="filename")]` gets expanded to // `#[doc(include(file="filename", contents="file contents")]` so we need to // look for that instead @@ -836,11 +837,11 @@ impl Attributes { let mut contents: Option = None; for it in list { - if it.check_name("file") { + if it.check_name(sym::file) { if let Some(name) = it.value_str() { filename = Some(name.to_string()); } - } else if it.check_name("contents") { + } else if it.check_name(sym::contents) { if let Some(docs) = it.value_str() { contents = Some(docs.to_string()); } @@ -860,9 +861,9 @@ impl Attributes { }) } - pub fn has_doc_flag(&self, flag: &str) -> bool { + pub fn has_doc_flag(&self, flag: Symbol) -> bool { for attr in &self.other_attrs { - if !attr.check_name("doc") { continue; } + if !attr.check_name(sym::doc) { continue; } if let Some(items) = attr.meta_item_list() { if items.iter().filter_map(|i| i.meta_item()).any(|it| it.check_name(flag)) { @@ -883,7 +884,7 @@ impl Attributes { let other_attrs = attrs.iter().filter_map(|attr| { attr.with_desugared_doc(|attr| { - if attr.check_name("doc") { + if attr.check_name(sym::doc) { if let Some(mi) = attr.meta() { if let Some(value) = mi.value_str() { // Extracted #[doc = "..."] @@ -925,8 +926,8 @@ impl Attributes { // treat #[target_feature(enable = "feat")] attributes as if they were // #[doc(cfg(target_feature = "feat"))] attributes as well - for attr in attrs.lists("target_feature") { - if attr.check_name("enable") { + for attr in attrs.lists(sym::target_feature) { + if attr.check_name(sym::enable) { if let Some(feat) = attr.value_str() { let meta = attr::mk_name_value_item_str(Ident::from_str("target_feature"), dummy_spanned(feat)); @@ -938,7 +939,7 @@ impl Attributes { } let inner_docs = attrs.iter() - .filter(|a| a.check_name("doc")) + .filter(|a| a.check_name(sym::doc)) .next() .map_or(true, |a| a.style == AttrStyle::Inner); @@ -1039,7 +1040,7 @@ impl Hash for Attributes { } impl AttributesExt for Attributes { - fn lists<'a>(&'a self, name: &'a str) -> ListAttributesIter<'a> { + fn lists<'a>(&'a self, name: Symbol) -> ListAttributesIter<'a> { self.other_attrs.lists(name) } } @@ -2133,7 +2134,7 @@ pub struct Trait { impl Clean for doctree::Trait { fn clean(&self, cx: &DocContext<'_>) -> Item { let attrs = self.attrs.clean(cx); - let is_spotlight = attrs.has_doc_flag("spotlight"); + let is_spotlight = attrs.has_doc_flag(sym::spotlight); Item { name: Some(self.name.clean(cx)), attrs: attrs, @@ -3893,8 +3894,8 @@ impl Clean> for doctree::ExternCrate { fn clean(&self, cx: &DocContext<'_>) -> Vec { let please_inline = self.vis.node.is_pub() && self.attrs.iter().any(|a| { - a.check_name("doc") && match a.meta_item_list() { - Some(l) => attr::list_contains_name(&l, "inline"), + a.check_name(sym::doc) && match a.meta_item_list() { + Some(l) => attr::list_contains_name(&l, sym::inline), None => false, } }); @@ -3935,15 +3936,15 @@ impl Clean> for doctree::Import { // #[doc(no_inline)] attribute is present. // Don't inline doc(hidden) imports so they can be stripped at a later stage. let mut denied = !self.vis.node.is_pub() || self.attrs.iter().any(|a| { - a.check_name("doc") && match a.meta_item_list() { - Some(l) => attr::list_contains_name(&l, "no_inline") || - attr::list_contains_name(&l, "hidden"), + a.check_name(sym::doc) && match a.meta_item_list() { + Some(l) => attr::list_contains_name(&l, sym::no_inline) || + attr::list_contains_name(&l, sym::hidden), None => false, } }); // Also check whether imports were asked to be inlined, in case we're trying to re-export a // crate in Rust 2018+ - let please_inline = self.attrs.lists("doc").has_word("inline"); + let please_inline = self.attrs.lists(sym::doc).has_word(sym::inline); let path = self.path.clean(cx); let inner = if self.glob { if !denied { diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index e91e3a029dacf..1b099fbd91d1e 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -18,6 +18,7 @@ use rustc_target::spec::TargetTriple; use syntax::source_map; use syntax::feature_gate::UnstableFeatures; use syntax::json::JsonEmitter; +use syntax::symbol::sym; use errors; use errors::emitter::{Emitter, EmitterWriter}; use parking_lot::ReentrantMutex; @@ -415,7 +416,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt // Process all of the crate attributes, extracting plugin metadata along // with the passes which we are supposed to run. - for attr in krate.module.as_ref().unwrap().attrs.lists("doc") { + for attr in krate.module.as_ref().unwrap().attrs.lists(sym::doc) { let diag = ctxt.sess().diagnostic(); let name = attr.name_or_empty(); diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 472192a646492..cbaa911eccca5 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -50,6 +50,7 @@ use syntax::ast; use syntax::ext::base::MacroKind; use syntax::source_map::FileName; use syntax::feature_gate::UnstableFeatures; +use syntax::symbol::sym; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId}; use rustc::middle::privacy::AccessLevels; use rustc::middle::stability; @@ -571,7 +572,7 @@ pub fn run(mut krate: clean::Crate, // Crawl the crate attributes looking for attributes which control how we're // going to emit HTML if let Some(attrs) = krate.module.as_ref().map(|m| &m.attrs) { - for attr in attrs.lists("doc") { + for attr in attrs.lists(sym::doc) { match (attr.name_or_empty().get(), attr.value_str()) { ("html_favicon_url", Some(s)) => { scx.layout.favicon = s.to_string(); @@ -1388,8 +1389,8 @@ fn extern_location(e: &clean::ExternalCrate, extern_url: Option<&str>, dst: &Pat // Failing that, see if there's an attribute specifying where to find this // external crate - e.attrs.lists("doc") - .filter(|a| a.check_name("html_root_url")) + e.attrs.lists(sym::doc) + .filter(|a| a.check_name(sym::html_root_url)) .filter_map(|a| a.value_str()) .map(|url| { let mut url = url.to_string(); @@ -1779,8 +1780,8 @@ impl<'a> Cache { let path = self.paths.get(&item.def_id) .map(|p| p.0[..p.0.len() - 1].join("::")) .unwrap_or("std".to_owned()); - for alias in item.attrs.lists("doc") - .filter(|a| a.check_name("alias")) + for alias in item.attrs.lists(sym::doc) + .filter(|a| a.check_name(sym::alias)) .filter_map(|a| a.value_str() .map(|s| s.to_string().replace("\"", ""))) .filter(|v| !v.is_empty()) diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index fe407fa24d93e..4ee09f7096b61 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -5,6 +5,7 @@ use crate::passes::Pass; use syntax::attr; use syntax_pos::FileName; +use syntax::symbol::sym; use std::collections::BTreeMap; use std::ops; @@ -131,7 +132,7 @@ impl fold::DocFolder for CoverageCalculator { return Some(i); } clean::ImplItem(ref impl_) - if attr::contains_name(&i.attrs.other_attrs, "automatically_derived") + if attr::contains_name(&i.attrs.other_attrs, sym::automatically_derived) || impl_.synthetic || impl_.blanket_impl.is_some() => { // built-in derives get the `#[automatically_derived]` attribute, and diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 8d33cd72e29aa..70cd4b72199bc 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -5,6 +5,7 @@ use super::Pass; use rustc::util::nodemap::FxHashSet; use rustc::hir::def_id::DefId; +use syntax::symbol::sym; pub const COLLECT_TRAIT_IMPLS: Pass = Pass { name: "collect-trait-impls", @@ -68,7 +69,7 @@ pub fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate { inline::build_impl(cx, def_id, &mut new_items); // FIXME(eddyb) is this `doc(hidden)` check needed? - if !cx.tcx.get_attrs(def_id).lists("doc").has_word("hidden") { + if !cx.tcx.get_attrs(def_id).lists(sym::doc).has_word(sym::hidden) { let self_ty = cx.tcx.type_of(def_id); let impls = get_auto_trait_and_blanket_impls(cx, self_ty, def_id); let mut renderinfo = cx.renderinfo.borrow_mut(); @@ -154,7 +155,7 @@ impl<'a, 'tcx> DocFolder for SyntheticImplCollector<'a, 'tcx> { fn fold_item(&mut self, i: Item) -> Option { if i.is_struct() || i.is_enum() || i.is_union() { // FIXME(eddyb) is this `doc(hidden)` check needed? - if !self.cx.tcx.get_attrs(i.def_id).lists("doc").has_word("hidden") { + if !self.cx.tcx.get_attrs(i.def_id).lists(sym::doc).has_word(sym::hidden) { self.impls.extend(get_auto_trait_and_blanket_impls( self.cx, self.cx.tcx.type_of(i.def_id), diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index 240299c212abc..da8977544f64b 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -1,5 +1,6 @@ use rustc::util::nodemap::DefIdSet; use std::mem; +use syntax::symbol::sym; use crate::clean::{self, AttributesExt, NestedAttributesExt}; use crate::clean::Item; @@ -37,7 +38,7 @@ struct Stripper<'a> { impl<'a> DocFolder for Stripper<'a> { fn fold_item(&mut self, i: Item) -> Option { - if i.attrs.lists("doc").has_word("hidden") { + if i.attrs.lists(sym::doc).has_word(sym::hidden) { debug!("strip_hidden: stripping {} {:?}", i.type_(), i.name); // use a dedicated hidden item for given item type if any match i.inner { diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 5c0a4da1cd7ef..e40dbe52ffe64 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -11,10 +11,6 @@ use syntax::ast; use syntax::source_map::SourceMap; use syntax::edition::Edition; use syntax::feature_gate::UnstableFeatures; -use syntax_pos::{BytePos, DUMMY_SP, Pos, Span, FileName}; -use tempfile::Builder as TempFileBuilder; -use testing; - use std::env; use std::io::prelude::*; use std::io; @@ -23,6 +19,10 @@ use std::path::PathBuf; use std::process::Command; use std::str; use std::sync::{Arc, Mutex}; +use syntax::symbol::sym; +use syntax_pos::{BytePos, DUMMY_SP, Pos, Span, FileName}; +use tempfile::Builder as TempFileBuilder; +use testing; use crate::clean::Attributes; use crate::config::Options; @@ -137,17 +137,17 @@ fn scrape_test_config(krate: &::rustc::hir::Crate) -> TestOptions { }; let test_attrs: Vec<_> = krate.attrs.iter() - .filter(|a| a.check_name("doc")) + .filter(|a| a.check_name(sym::doc)) .flat_map(|a| a.meta_item_list().unwrap_or_else(Vec::new)) - .filter(|a| a.check_name("test")) + .filter(|a| a.check_name(sym::test)) .collect(); let attrs = test_attrs.iter().flat_map(|a| a.meta_item_list().unwrap_or(&[])); for attr in attrs { - if attr.check_name("no_crate_inject") { + if attr.check_name(sym::no_crate_inject) { opts.no_crate_inject = true; } - if attr.check_name("attr") { + if attr.check_name(sym::attr) { if let Some(l) = attr.meta_item_list() { for item in l { opts.attrs.push(pprust::meta_list_item_to_string(item)); diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 94d2d7ffdb8c2..eb9de43e38861 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -10,6 +10,7 @@ use syntax::ast; use syntax::attr; use syntax::ext::base::MacroKind; use syntax::source_map::Spanned; +use syntax::symbol::sym; use syntax_pos::{self, Span}; use std::mem; @@ -165,11 +166,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { body: hir::BodyId) { debug!("Visiting fn"); let macro_kind = item.attrs.iter().filter_map(|a| { - if a.check_name("proc_macro") { + if a.check_name(sym::proc_macro) { Some(MacroKind::Bang) - } else if a.check_name("proc_macro_derive") { + } else if a.check_name(sym::proc_macro_derive) { Some(MacroKind::Derive) - } else if a.check_name("proc_macro_attribute") { + } else if a.check_name(sym::proc_macro_attribute) { Some(MacroKind::Attr) } else { None @@ -178,7 +179,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { match macro_kind { Some(kind) => { let name = if kind == MacroKind::Derive { - item.attrs.lists("proc_macro_derive") + item.attrs.lists(sym::proc_macro_derive) .filter_map(|mi| mi.ident()) .next() .expect("proc-macro derives require a name") @@ -188,8 +189,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { }; let mut helpers = Vec::new(); - for mi in item.attrs.lists("proc_macro_derive") { - if !mi.check_name("attributes") { + for mi in item.attrs.lists(sym::proc_macro_derive) { + if !mi.check_name(sym::attributes) { continue; } @@ -274,7 +275,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { fn inherits_doc_hidden(cx: &core::DocContext<'_>, mut node: hir::HirId) -> bool { while let Some(id) = cx.tcx.hir().get_enclosing_scope(node) { node = id; - if cx.tcx.hir().attrs_by_hir_id(node).lists("doc").has_word("hidden") { + if cx.tcx.hir().attrs_by_hir_id(node) + .lists(sym::doc).has_word(sym::hidden) { return true; } if node == hir::CRATE_HIR_ID { @@ -295,8 +297,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { let use_attrs = tcx.hir().attrs_by_hir_id(id); // Don't inline `doc(hidden)` imports so they can be stripped at a later stage. - let is_no_inline = use_attrs.lists("doc").has_word("no_inline") || - use_attrs.lists("doc").has_word("hidden"); + let is_no_inline = use_attrs.lists(sym::doc).has_word(sym::no_inline) || + use_attrs.lists(sym::doc).has_word(sym::hidden); // For cross-crate impl inlining we need to know whether items are // reachable in documentation -- a previously nonreachable item can be @@ -304,7 +306,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { // (this is done here because we need to know this upfront). if !res_did.is_local() && !is_no_inline { let attrs = clean::inline::load_attrs(self.cx, res_did); - let self_is_hidden = attrs.lists("doc").has_word("hidden"); + let self_is_hidden = attrs.lists(sym::doc).has_word(sym::hidden); match res { Res::Def(DefKind::Trait, did) | Res::Def(DefKind::Struct, did) | @@ -432,8 +434,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { if item.vis.node.is_pub() && self.inside_public_path { let please_inline = item.attrs.iter().any(|item| { match item.meta_item_list() { - Some(ref list) if item.check_name("doc") => { - list.iter().any(|i| i.check_name("inline")) + Some(ref list) if item.check_name(sym::doc) => { + list.iter().any(|i| i.check_name(sym::inline)) } _ => false, } diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs index 326c9a10f7df8..2547e3a06e9ef 100644 --- a/src/librustdoc/visit_lib.rs +++ b/src/librustdoc/visit_lib.rs @@ -3,6 +3,7 @@ use rustc::hir::def::{Res, DefKind}; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId}; use rustc::ty::Visibility; use rustc::util::nodemap::FxHashSet; +use syntax::symbol::sym; use std::cell::RefMut; @@ -42,7 +43,7 @@ impl<'a, 'tcx> LibEmbargoVisitor<'a, 'tcx> { // Updates node level and returns the updated level fn update(&mut self, did: DefId, level: Option) -> Option { - let is_hidden = self.cx.tcx.get_attrs(did).lists("doc").has_word("hidden"); + let is_hidden = self.cx.tcx.get_attrs(did).lists(sym::doc).has_word(sym::hidden); let old_level = self.access_levels.map.get(&did).cloned(); // Accessibility levels can only grow diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs index db821f4e5369d..a8310c48b9627 100644 --- a/src/libsyntax/attr/builtin.rs +++ b/src/libsyntax/attr/builtin.rs @@ -5,7 +5,7 @@ use crate::feature_gate::{Features, GatedCfg}; use crate::parse::ParseSess; use errors::{Applicability, Handler}; -use syntax_pos::{symbol::Symbol, Span}; +use syntax_pos::{symbol::Symbol, symbol::sym, Span}; use super::{mark_used, MetaItemKind}; @@ -80,13 +80,13 @@ pub enum UnwindAttr { /// Determine what `#[unwind]` attribute is present in `attrs`, if any. pub fn find_unwind_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> Option { attrs.iter().fold(None, |ia, attr| { - if attr.check_name("unwind") { + if attr.check_name(sym::unwind) { if let Some(meta) = attr.meta() { if let MetaItemKind::List(items) = meta.node { if items.len() == 1 { - if items[0].check_name("allowed") { + if items[0].check_name(sym::allowed) { return Some(UnwindAttr::Allowed); - } else if items[0].check_name("aborts") { + } else if items[0].check_name(sym::aborts) { return Some(UnwindAttr::Aborts); } } @@ -153,9 +153,9 @@ pub struct RustcDeprecation { /// Checks if `attrs` contains an attribute like `#![feature(feature_name)]`. /// This will not perform any "sanity checks" on the form of the attributes. -pub fn contains_feature_attr(attrs: &[Attribute], feature_name: &str) -> bool { +pub fn contains_feature_attr(attrs: &[Attribute], feature_name: Symbol) -> bool { attrs.iter().any(|item| { - item.check_name("feature") && + item.check_name(sym::feature) && item.meta_item_list().map(|list| { list.iter().any(|mi| mi.is_word() && mi.check_name(feature_name)) }).unwrap_or(false) @@ -482,7 +482,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, } pub fn find_crate_name(attrs: &[Attribute]) -> Option { - super::first_attr_value_str_by_name(attrs, "crate_name") + super::first_attr_value_str_by_name(attrs, sym::crate_name) } /// Tests if a cfg-pattern matches the cfg set @@ -593,7 +593,7 @@ fn find_deprecation_generic<'a, I>(sess: &ParseSess, let diagnostic = &sess.span_diagnostic; 'outer: for attr in attrs_iter { - if !attr.check_name("deprecated") { + if !attr.check_name(sym::deprecated) { continue; } @@ -790,7 +790,7 @@ pub fn find_repr_attrs(sess: &ParseSess, attr: &Attribute) -> Vec { } } else { if let Some(meta_item) = item.meta_item() { - if meta_item.check_name("align") { + if meta_item.check_name(sym::align) { if let MetaItemKind::NameValue(ref value) = meta_item.node { recognised = true; let mut err = struct_span_err!(diagnostic, item.span(), E0693, diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index 07e4bbf78ffdf..c0defa1c6e019 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -81,10 +81,7 @@ impl NestedMetaItem { } /// Returns `true` if this list item is a MetaItem with a name of `name`. - pub fn check_name(&self, name: T) -> bool - where - Path: PartialEq, - { + pub fn check_name(&self, name: Symbol) -> bool { self.meta_item().map_or(false, |meta_item| meta_item.check_name(name)) } @@ -154,10 +151,7 @@ impl Attribute { /// attribute is marked as used. /// /// To check the attribute name without marking it used, use the `path` field directly. - pub fn check_name(&self, name: T) -> bool - where - Path: PartialEq, - { + pub fn check_name(&self, name: Symbol) -> bool { let matches = self.path == name; if matches { mark_used(self); @@ -250,10 +244,7 @@ impl MetaItem { } } - pub fn check_name(&self, name: T) -> bool - where - Path: PartialEq, - { + pub fn check_name(&self, name: Symbol) -> bool { self.path == name } @@ -430,28 +421,28 @@ pub fn mk_sugared_doc_attr(id: AttrId, text: Symbol, span: Span) -> Attribute { } } -pub fn list_contains_name(items: &[NestedMetaItem], name: &str) -> bool { +pub fn list_contains_name(items: &[NestedMetaItem], name: Symbol) -> bool { items.iter().any(|item| { item.check_name(name) }) } -pub fn contains_name(attrs: &[Attribute], name: &str) -> bool { +pub fn contains_name(attrs: &[Attribute], name: Symbol) -> bool { attrs.iter().any(|item| { item.check_name(name) }) } -pub fn find_by_name<'a>(attrs: &'a [Attribute], name: &str) -> Option<&'a Attribute> { +pub fn find_by_name<'a>(attrs: &'a [Attribute], name: Symbol) -> Option<&'a Attribute> { attrs.iter().find(|attr| attr.check_name(name)) } -pub fn filter_by_name<'a>(attrs: &'a [Attribute], name: &'a str) +pub fn filter_by_name<'a>(attrs: &'a [Attribute], name: Symbol) -> impl Iterator { attrs.iter().filter(move |attr| attr.check_name(name)) } -pub fn first_attr_value_str_by_name(attrs: &[Attribute], name: &str) -> Option { +pub fn first_attr_value_str_by_name(attrs: &[Attribute], name: Symbol) -> Option { attrs.iter() .find(|at| at.check_name(name)) .and_then(|at| at.value_str()) diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 18173628a2602..c82936afa3d9f 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -12,6 +12,7 @@ use crate::edition::Edition; use crate::mut_visit::*; use crate::parse::{token, ParseSess}; use crate::ptr::P; +use crate::symbol::sym; use crate::util::map_in_place::MapInPlace; use errors::Applicability; @@ -90,7 +91,7 @@ impl<'a> StripUnconfigured<'a> { /// is in the original source file. Gives a compiler error if the syntax of /// the attribute is incorrect. fn process_cfg_attr(&mut self, attr: ast::Attribute) -> Vec { - if !attr.check_name("cfg_attr") { + if !attr.check_name(sym::cfg_attr) { return vec![attr]; } @@ -205,7 +206,7 @@ impl<'a> StripUnconfigured<'a> { pub fn maybe_emit_expr_attr_err(&self, attr: &ast::Attribute) { if !self.features.map(|features| features.stmt_expr_attributes).unwrap_or(true) { let mut err = feature_err(self.sess, - "stmt_expr_attributes", + sym::stmt_expr_attributes, attr.span, GateIssue::Language, EXPLAIN_STMT_ATTR_SYNTAX); @@ -285,9 +286,9 @@ impl<'a> StripUnconfigured<'a> { /// See issue #51279. pub fn disallow_cfg_on_generic_param(&mut self, param: &ast::GenericParam) { for attr in param.attrs() { - let offending_attr = if attr.check_name("cfg") { + let offending_attr = if attr.check_name(sym::cfg) { "cfg" - } else if attr.check_name("cfg_attr") { + } else if attr.check_name(sym::cfg_attr) { "cfg_attr" } else { continue; @@ -350,5 +351,5 @@ impl<'a> MutVisitor for StripUnconfigured<'a> { } fn is_cfg(attr: &ast::Attribute) -> bool { - attr.check_name("cfg") + attr.check_name(sym::cfg) } diff --git a/src/libsyntax/entry.rs b/src/libsyntax/entry.rs index 09e26e29d86a8..267f863ce35e4 100644 --- a/src/libsyntax/entry.rs +++ b/src/libsyntax/entry.rs @@ -1,5 +1,6 @@ use crate::attr; use crate::ast::{Item, ItemKind}; +use crate::symbol::sym; pub enum EntryPointType { None, @@ -14,9 +15,9 @@ pub enum EntryPointType { pub fn entry_point_type(item: &Item, depth: usize) -> EntryPointType { match item.node { ItemKind::Fn(..) => { - if attr::contains_name(&item.attrs, "start") { + if attr::contains_name(&item.attrs, sym::start) { EntryPointType::Start - } else if attr::contains_name(&item.attrs, "main") { + } else if attr::contains_name(&item.attrs, sym::main) { EntryPointType::MainAttr } else if item.ident.name == "main" { if depth == 1 { diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 82358679c0e82..7ebfcfd176adb 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -14,7 +14,7 @@ use crate::parse::token::{self, Token}; use crate::parse::parser::Parser; use crate::ptr::P; use crate::symbol::Symbol; -use crate::symbol::keywords; +use crate::symbol::{keywords, sym}; use crate::tokenstream::{TokenStream, TokenTree}; use crate::visit::{self, Visitor}; use crate::util::map_in_place::MapInPlace; @@ -356,7 +356,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.collect_invocations(fragment, &[]) } else if let InvocationKind::Attr { attr: None, traits, item, .. } = invoc.kind { if !item.derive_allowed() { - let attr = attr::find_by_name(item.attrs(), "derive") + let attr = attr::find_by_name(item.attrs(), sym::derive) .expect("`derive` attribute should exist"); let span = attr.span; let mut err = self.cx.mut_span_err(span, @@ -510,7 +510,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { if invoc.fragment_kind == AstFragmentKind::ForeignItems && !self.cx.ecfg.macros_in_extern_enabled() { if let SyntaxExtension::NonMacroAttr { .. } = *ext {} else { - emit_feature_err(&self.cx.parse_sess, "macros_in_extern", + emit_feature_err(&self.cx.parse_sess, sym::macros_in_extern, invoc.span(), GateIssue::Language, "macro invocations in `extern {}` blocks are experimental"); } @@ -636,7 +636,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { Annotatable::Item(ref item) => { match item.node { ItemKind::Mod(_) if self.cx.ecfg.proc_macro_hygiene() => return, - ItemKind::Mod(_) => ("modules", "proc_macro_hygiene"), + ItemKind::Mod(_) => ("modules", sym::proc_macro_hygiene), _ => return, } } @@ -645,8 +645,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { Annotatable::ForeignItem(_) => return, Annotatable::Stmt(_) | Annotatable::Expr(_) if self.cx.ecfg.proc_macro_hygiene() => return, - Annotatable::Stmt(_) => ("statements", "proc_macro_hygiene"), - Annotatable::Expr(_) => ("expressions", "proc_macro_hygiene"), + Annotatable::Stmt(_) => ("statements", sym::proc_macro_hygiene), + Annotatable::Expr(_) => ("expressions", sym::proc_macro_hygiene), }; emit_feature_err( self.cx.parse_sess, @@ -681,7 +681,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { if let ast::ItemKind::MacroDef(_) = i.node { emit_feature_err( self.parse_sess, - "proc_macro_hygiene", + sym::proc_macro_hygiene, self.span, GateIssue::Language, "procedural macros cannot expand to macro definitions", @@ -724,13 +724,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> { // don't stability-check macros in the same crate // (the only time this is null is for syntax extensions registered as macros) if def_site_span.map_or(false, |def_span| !crate_span.contains(def_span)) - && !span.allows_unstable(&feature.as_str()) + && !span.allows_unstable(feature) && this.cx.ecfg.features.map_or(true, |feats| { // macro features will count as lib features !feats.declared_lib_features.iter().any(|&(feat, _)| feat == feature) }) { let explain = format!("macro {}! is unstable", path); - emit_feature_err(this.cx.parse_sess, &*feature.as_str(), span, + emit_feature_err(this.cx.parse_sess, feature, span, GateIssue::Library(Some(issue)), &explain); this.cx.trace_macros_diag(); } @@ -885,7 +885,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } emit_feature_err( self.cx.parse_sess, - "proc_macro_hygiene", + sym::proc_macro_hygiene, span, GateIssue::Language, &format!("procedural macros cannot be expanded to {}", kind), @@ -1118,7 +1118,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { if let Some(attr) = &attr { if !self.cx.ecfg.enable_custom_inner_attributes() && attr.style == ast::AttrStyle::Inner && attr.path != "test" { - emit_feature_err(&self.cx.parse_sess, "custom_inner_attributes", + emit_feature_err(&self.cx.parse_sess, sym::custom_inner_attributes, attr.span, GateIssue::Language, "non-builtin inner attributes are unstable"); } @@ -1352,7 +1352,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { let inline_module = item.span.contains(inner) || inner.is_dummy(); if inline_module { - if let Some(path) = attr::first_attr_value_str_by_name(&item.attrs, "path") { + if let Some(path) = attr::first_attr_value_str_by_name(&item.attrs, sym::path) { self.cx.current_expansion.directory_ownership = DirectoryOwnership::Owned { relative: None }; module.directory.push(&*path.as_str()); @@ -1485,19 +1485,19 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { fn visit_attribute(&mut self, at: &mut ast::Attribute) { // turn `#[doc(include="filename")]` attributes into `#[doc(include(file="filename", // contents="file contents")]` attributes - if !at.check_name("doc") { + if !at.check_name(sym::doc) { return noop_visit_attribute(at, self); } if let Some(list) = at.meta_item_list() { - if !list.iter().any(|it| it.check_name("include")) { + if !list.iter().any(|it| it.check_name(sym::include)) { return noop_visit_attribute(at, self); } let mut items = vec![]; for mut it in list { - if !it.check_name("include") { + if !it.check_name(sym::include) { items.push({ noop_visit_meta_list_item(&mut it, self); it }); continue; } diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index 549de1628eb55..e1cb90d9e71d6 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -4,7 +4,7 @@ use crate::ext::build::AstBuilder; use crate::parse::{self, token, DirectoryOwnership}; use crate::print::pprust; use crate::ptr::P; -use crate::symbol::Symbol; +use crate::symbol::{Symbol, sym}; use crate::tokenstream; use smallvec::SmallVec; @@ -44,7 +44,7 @@ pub fn expand_column(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTr /* __rust_unstable_column!(): expands to the current column number */ pub fn expand_column_gated(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree]) -> Box { - if sp.allows_unstable("__rust_unstable_column") { + if sp.allows_unstable(sym::__rust_unstable_column) { expand_column(cx, sp, tts) } else { cx.span_fatal(sp, "the __rust_unstable_column macro is unstable"); diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index a53cc2fe66173..5559621009369 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -13,7 +13,7 @@ use crate::parse::{Directory, ParseSess}; use crate::parse::parser::Parser; use crate::parse::token::{self, NtTT}; use crate::parse::token::Token::*; -use crate::symbol::Symbol; +use crate::symbol::{Symbol, sym}; use crate::tokenstream::{DelimSpan, TokenStream, TokenTree}; use errors::FatalError; @@ -376,7 +376,7 @@ pub fn compile( }); if body.legacy { - let allow_internal_unstable = attr::find_by_name(&def.attrs, "allow_internal_unstable") + let allow_internal_unstable = attr::find_by_name(&def.attrs, sym::allow_internal_unstable) .map(|attr| attr .meta_item_list() .map(|list| list.iter() @@ -399,11 +399,11 @@ pub fn compile( vec![Symbol::intern("allow_internal_unstable_backcompat_hack")].into() }) ); - let allow_internal_unsafe = attr::contains_name(&def.attrs, "allow_internal_unsafe"); + let allow_internal_unsafe = attr::contains_name(&def.attrs, sym::allow_internal_unsafe); let mut local_inner_macros = false; - if let Some(macro_export) = attr::find_by_name(&def.attrs, "macro_export") { + if let Some(macro_export) = attr::find_by_name(&def.attrs, sym::macro_export) { if let Some(l) = macro_export.meta_item_list() { - local_inner_macros = attr::list_contains_name(&l, "local_inner_macros"); + local_inner_macros = attr::list_contains_name(&l, sym::local_inner_macros); } } @@ -426,7 +426,7 @@ pub fn compile( edition, } } else { - let is_transparent = attr::contains_name(&def.attrs, "rustc_transparent_macro"); + let is_transparent = attr::contains_name(&def.attrs, sym::rustc_transparent_macro); SyntaxExtension::DeclMacro { expander, diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index c4977f9240238..53ecb0762ab44 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -48,8 +48,8 @@ macro_rules! declare_features { /// Represents active features that are currently being implemented or /// currently being considered for addition/removal. const ACTIVE_FEATURES: - &[(&str, &str, Option, Option, fn(&mut Features, Span))] = - &[$((stringify!($feature), $ver, $issue, $edition, set!($feature))),+]; + &[(Symbol, &str, Option, Option, fn(&mut Features, Span))] = + &[$((sym::$feature, $ver, $issue, $edition, set!($feature))),+]; /// A set of features to be used by later passes. #[derive(Clone)] @@ -80,22 +80,22 @@ macro_rules! declare_features { ($((removed, $feature: ident, $ver: expr, $issue: expr, None, $reason: expr),)+) => { /// Represents unstable features which have since been removed (it was once Active) - const REMOVED_FEATURES: &[(&str, &str, Option, Option<&str>)] = &[ - $((stringify!($feature), $ver, $issue, $reason)),+ + const REMOVED_FEATURES: &[(Symbol, &str, Option, Option<&str>)] = &[ + $((sym::$feature, $ver, $issue, $reason)),+ ]; }; ($((stable_removed, $feature: ident, $ver: expr, $issue: expr, None),)+) => { /// Represents stable features which have since been removed (it was once Accepted) - const STABLE_REMOVED_FEATURES: &[(&str, &str, Option, Option<&str>)] = &[ - $((stringify!($feature), $ver, $issue, None)),+ + const STABLE_REMOVED_FEATURES: &[(Symbol, &str, Option, Option<&str>)] = &[ + $((sym::$feature, $ver, $issue, None)),+ ]; }; ($((accepted, $feature: ident, $ver: expr, $issue: expr, None),)+) => { /// Those language feature has since been Accepted (it was once Active) - const ACCEPTED_FEATURES: &[(&str, &str, Option, Option<&str>)] = &[ - $((stringify!($feature), $ver, $issue, None)),+ + const ACCEPTED_FEATURES: &[(Symbol, &str, Option, Option<&str>)] = &[ + $((sym::$feature, $ver, $issue, None)),+ ]; } } @@ -860,7 +860,7 @@ pub enum AttributeType { pub enum AttributeGate { /// Is gated by a given feature gate, reason /// and function to check if enabled - Gated(Stability, &'static str, &'static str, fn(&Features) -> bool), + Gated(Stability, Symbol, &'static str, fn(&Features) -> bool), /// Ungated attribute, can be used on all release channels Ungated, @@ -1010,7 +1010,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ (sym::no_implicit_prelude, Normal, template!(Word), Ungated), (sym::reexport_test_harness_main, Normal, template!(NameValueStr: "name"), Ungated), (sym::link_args, Normal, template!(NameValueStr: "args"), Gated(Stability::Unstable, - "link_args", + sym::link_args, "the `link_args` attribute is experimental and not \ portable across platforms, it is recommended to \ use `#[link(name = \"foo\")] instead", @@ -1019,46 +1019,46 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // RFC #1445. (sym::structural_match, Whitelisted, template!(Word), Gated(Stability::Unstable, - "structural_match", + sym::structural_match, "the semantics of constant patterns is \ not yet settled", cfg_fn!(structural_match))), // RFC #2008 (sym::non_exhaustive, Whitelisted, template!(Word), Gated(Stability::Unstable, - "non_exhaustive", + sym::non_exhaustive, "non exhaustive is an experimental feature", cfg_fn!(non_exhaustive))), // RFC #1268 (sym::marker, Normal, template!(Word), Gated(Stability::Unstable, - "marker_trait_attr", + sym::marker_trait_attr, "marker traits is an experimental feature", cfg_fn!(marker_trait_attr))), (sym::plugin, CrateLevel, template!(List: "name|name(args)"), Gated(Stability::Unstable, - "plugin", + sym::plugin, "compiler plugins are experimental \ and possibly buggy", cfg_fn!(plugin))), (sym::no_std, CrateLevel, template!(Word), Ungated), (sym::no_core, CrateLevel, template!(Word), Gated(Stability::Unstable, - "no_core", + sym::no_core, "no_core is experimental", cfg_fn!(no_core))), (sym::lang, Normal, template!(NameValueStr: "name"), Gated(Stability::Unstable, - "lang_items", + sym::lang_items, "language items are subject to change", cfg_fn!(lang_items))), (sym::linkage, Whitelisted, template!(NameValueStr: "external|internal|..."), Gated(Stability::Unstable, - "linkage", + sym::linkage, "the `linkage` attribute is experimental \ and not portable across platforms", cfg_fn!(linkage))), (sym::thread_local, Whitelisted, template!(Word), Gated(Stability::Unstable, - "thread_local", + sym::thread_local, "`#[thread_local]` is an experimental feature, and does \ not currently handle destructors", cfg_fn!(thread_local))), @@ -1067,100 +1067,100 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#, NameValueStr: "message"), Gated(Stability::Unstable, - "on_unimplemented", + sym::on_unimplemented, "the `#[rustc_on_unimplemented]` attribute \ is an experimental feature", cfg_fn!(on_unimplemented))), (sym::rustc_const_unstable, Normal, template!(List: r#"feature = "name""#), Gated(Stability::Unstable, - "rustc_const_unstable", + sym::rustc_const_unstable, "the `#[rustc_const_unstable]` attribute \ is an internal feature", cfg_fn!(rustc_const_unstable))), (sym::global_allocator, Normal, template!(Word), Ungated), (sym::default_lib_allocator, Whitelisted, template!(Word), Gated(Stability::Unstable, - "allocator_internals", + sym::allocator_internals, "the `#[default_lib_allocator]` \ attribute is an experimental feature", cfg_fn!(allocator_internals))), (sym::needs_allocator, Normal, template!(Word), Gated(Stability::Unstable, - "allocator_internals", + sym::allocator_internals, "the `#[needs_allocator]` \ attribute is an experimental \ feature", cfg_fn!(allocator_internals))), (sym::panic_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, - "panic_runtime", + sym::panic_runtime, "the `#[panic_runtime]` attribute is \ an experimental feature", cfg_fn!(panic_runtime))), (sym::needs_panic_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, - "needs_panic_runtime", + sym::needs_panic_runtime, "the `#[needs_panic_runtime]` \ attribute is an experimental \ feature", cfg_fn!(needs_panic_runtime))), (sym::rustc_outlives, Normal, template!(Word), Gated(Stability::Unstable, - "rustc_attrs", + sym::rustc_attrs, "the `#[rustc_outlives]` attribute \ is just used for rustc unit tests \ and will never be stable", cfg_fn!(rustc_attrs))), (sym::rustc_variance, Normal, template!(Word), Gated(Stability::Unstable, - "rustc_attrs", + sym::rustc_attrs, "the `#[rustc_variance]` attribute \ is just used for rustc unit tests \ and will never be stable", cfg_fn!(rustc_attrs))), (sym::rustc_layout, Normal, template!(List: "field1, field2, ..."), Gated(Stability::Unstable, - "rustc_attrs", + sym::rustc_attrs, "the `#[rustc_layout]` attribute \ is just used for rustc unit tests \ and will never be stable", cfg_fn!(rustc_attrs))), (sym::rustc_layout_scalar_valid_range_start, Whitelisted, template!(List: "value"), Gated(Stability::Unstable, - "rustc_attrs", + sym::rustc_attrs, "the `#[rustc_layout_scalar_valid_range_start]` attribute \ is just used to enable niche optimizations in libcore \ and will never be stable", cfg_fn!(rustc_attrs))), (sym::rustc_layout_scalar_valid_range_end, Whitelisted, template!(List: "value"), Gated(Stability::Unstable, - "rustc_attrs", + sym::rustc_attrs, "the `#[rustc_layout_scalar_valid_range_end]` attribute \ is just used to enable niche optimizations in libcore \ and will never be stable", cfg_fn!(rustc_attrs))), (sym::rustc_regions, Normal, template!(Word), Gated(Stability::Unstable, - "rustc_attrs", + sym::rustc_attrs, "the `#[rustc_regions]` attribute \ is just used for rustc unit tests \ and will never be stable", cfg_fn!(rustc_attrs))), (sym::rustc_error, Whitelisted, template!(Word), Gated(Stability::Unstable, - "rustc_attrs", + sym::rustc_attrs, "the `#[rustc_error]` attribute \ is just used for rustc unit tests \ and will never be stable", cfg_fn!(rustc_attrs))), (sym::rustc_dump_user_substs, Whitelisted, template!(Word), Gated(Stability::Unstable, - "rustc_attrs", + sym::rustc_attrs, "this attribute \ is just used for rustc unit tests \ and will never be stable", cfg_fn!(rustc_attrs))), (sym::rustc_if_this_changed, Whitelisted, template!(Word, List: "DepNode"), Gated(Stability::Unstable, - "rustc_attrs", + sym::rustc_attrs, "the `#[rustc_if_this_changed]` attribute \ is just used for rustc unit tests \ and will never be stable", cfg_fn!(rustc_attrs))), (sym::rustc_then_this_would_need, Whitelisted, template!(List: "DepNode"), Gated(Stability::Unstable, - "rustc_attrs", + sym::rustc_attrs, "the `#[rustc_if_this_changed]` attribute \ is just used for rustc unit tests \ and will never be stable", @@ -1168,7 +1168,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ (sym::rustc_dirty, Whitelisted, template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#), Gated(Stability::Unstable, - "rustc_attrs", + sym::rustc_attrs, "the `#[rustc_dirty]` attribute \ is just used for rustc unit tests \ and will never be stable", @@ -1176,7 +1176,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ (sym::rustc_clean, Whitelisted, template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#), Gated(Stability::Unstable, - "rustc_attrs", + sym::rustc_attrs, "the `#[rustc_clean]` attribute \ is just used for rustc unit tests \ and will never be stable", @@ -1187,7 +1187,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ template!(List: r#"cfg = "...", module = "...""#), Gated( Stability::Unstable, - "rustc_attrs", + sym::rustc_attrs, "this attribute \ is just used for rustc unit tests \ and will never be stable", @@ -1200,7 +1200,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ template!(List: r#"cfg = "...", module = "...""#), Gated( Stability::Unstable, - "rustc_attrs", + sym::rustc_attrs, "this attribute \ is just used for rustc unit tests \ and will never be stable", @@ -1210,27 +1210,27 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ (sym::rustc_expected_cgu_reuse, Whitelisted, template!(List: r#"cfg = "...", module = "...", kind = "...""#), Gated(Stability::Unstable, - "rustc_attrs", + sym::rustc_attrs, "this attribute \ is just used for rustc unit tests \ and will never be stable", cfg_fn!(rustc_attrs))), (sym::rustc_synthetic, Whitelisted, template!(Word), Gated(Stability::Unstable, - "rustc_attrs", + sym::rustc_attrs, "this attribute \ is just used for rustc unit tests \ and will never be stable", cfg_fn!(rustc_attrs))), (sym::rustc_symbol_name, Whitelisted, template!(Word), Gated(Stability::Unstable, - "rustc_attrs", + sym::rustc_attrs, "internal rustc attributes will never be stable", cfg_fn!(rustc_attrs))), (sym::rustc_def_path, Whitelisted, template!(Word), Gated(Stability::Unstable, - "rustc_attrs", + sym::rustc_attrs, "internal rustc attributes will never be stable", cfg_fn!(rustc_attrs))), (sym::rustc_mir, Whitelisted, template!(List: "arg1, arg2, ..."), Gated(Stability::Unstable, - "rustc_attrs", + sym::rustc_attrs, "the `#[rustc_mir]` attribute \ is just used for rustc unit tests \ and will never be stable", @@ -1241,7 +1241,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ template!(Word), Gated( Stability::Unstable, - "rustc_attrs", + sym::rustc_attrs, "the `#[rustc_inherit_overflow_checks]` \ attribute is just used to control \ overflow checking behavior of several \ @@ -1252,35 +1252,35 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), (sym::rustc_dump_program_clauses, Whitelisted, template!(Word), Gated(Stability::Unstable, - "rustc_attrs", + sym::rustc_attrs, "the `#[rustc_dump_program_clauses]` \ attribute is just used for rustc unit \ tests and will never be stable", cfg_fn!(rustc_attrs))), (sym::rustc_test_marker, Normal, template!(Word), Gated(Stability::Unstable, - "rustc_attrs", + sym::rustc_attrs, "the `#[rustc_test_marker]` attribute \ is used internally to track tests", cfg_fn!(rustc_attrs))), (sym::rustc_transparent_macro, Whitelisted, template!(Word), Gated(Stability::Unstable, - "rustc_attrs", + sym::rustc_attrs, "used internally for testing macro hygiene", cfg_fn!(rustc_attrs))), (sym::compiler_builtins, Whitelisted, template!(Word), Gated(Stability::Unstable, - "compiler_builtins", + sym::compiler_builtins, "the `#[compiler_builtins]` attribute is used to \ identify the `compiler_builtins` crate which \ contains compiler-rt intrinsics and will never be \ stable", cfg_fn!(compiler_builtins))), (sym::sanitizer_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, - "sanitizer_runtime", + sym::sanitizer_runtime, "the `#[sanitizer_runtime]` attribute is used to \ identify crates that contain the runtime of a \ sanitizer and will never be stable", cfg_fn!(sanitizer_runtime))), (sym::profiler_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, - "profiler_runtime", + sym::profiler_runtime, "the `#[profiler_runtime]` attribute is used to \ identify the `profiler_builtins` crate which \ contains the profiler runtime and will never be \ @@ -1289,17 +1289,17 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ (sym::allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), Gated(Stability::Unstable, - "allow_internal_unstable", + sym::allow_internal_unstable, EXPLAIN_ALLOW_INTERNAL_UNSTABLE, cfg_fn!(allow_internal_unstable))), (sym::allow_internal_unsafe, Normal, template!(Word), Gated(Stability::Unstable, - "allow_internal_unsafe", + sym::allow_internal_unsafe, EXPLAIN_ALLOW_INTERNAL_UNSAFE, cfg_fn!(allow_internal_unsafe))), (sym::fundamental, Whitelisted, template!(Word), Gated(Stability::Unstable, - "fundamental", + sym::fundamental, "the `#[fundamental]` attribute \ is an experimental feature", cfg_fn!(fundamental))), @@ -1309,7 +1309,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ Ungated), (sym::rustc_copy_clone_marker, Whitelisted, template!(Word), Gated(Stability::Unstable, - "rustc_attrs", + sym::rustc_attrs, "internal implementation detail", cfg_fn!(rustc_attrs))), @@ -1325,12 +1325,12 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // lint pass (sym::cold, Whitelisted, template!(Word), Ungated), (sym::naked, Whitelisted, template!(Word), Gated(Stability::Unstable, - "naked_functions", + sym::naked_functions, "the `#[naked]` attribute \ is an experimental feature", cfg_fn!(naked_functions))), (sym::ffi_returns_twice, Whitelisted, template!(Word), Gated(Stability::Unstable, - "ffi_returns_twice", + sym::ffi_returns_twice, "the `#[ffi_returns_twice]` attribute \ is an experimental feature", cfg_fn!(ffi_returns_twice))), @@ -1344,7 +1344,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ (sym::no_builtins, Whitelisted, template!(Word), Ungated), (sym::no_debug, Whitelisted, template!(Word), Gated( Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721", None), - "no_debug", + sym::no_debug, "the `#[no_debug]` attribute was an experimental feature that has been \ deprecated due to lack of demand", cfg_fn!(no_debug))), @@ -1354,7 +1354,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ template!(Word), Gated( Stability::Unstable, - "omit_gdb_pretty_printer_section", + sym::omit_gdb_pretty_printer_section, "the `#[omit_gdb_pretty_printer_section]` \ attribute is just used for the Rust test \ suite", @@ -1366,7 +1366,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ template!(Word), Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761", Some("replace this attribute with `#[may_dangle]`")), - "dropck_parametricity", + sym::dropck_parametricity, "unsafe_destructor_blind_to_params has been replaced by \ may_dangle and will be removed in the future", cfg_fn!(dropck_parametricity))), @@ -1374,18 +1374,18 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ Normal, template!(Word), Gated(Stability::Unstable, - "dropck_eyepatch", + sym::dropck_eyepatch, "may_dangle has unstable semantics and may be removed in the future", cfg_fn!(dropck_eyepatch))), (sym::unwind, Whitelisted, template!(List: "allowed|aborts"), Gated(Stability::Unstable, - "unwind_attributes", + sym::unwind_attributes, "#[unwind] is experimental", cfg_fn!(unwind_attributes))), (sym::used, Whitelisted, template!(Word), Ungated), // used in resolve (sym::prelude_import, Whitelisted, template!(Word), Gated(Stability::Unstable, - "prelude_import", + sym::prelude_import, "`#[prelude_import]` is for use by rustc only", cfg_fn!(prelude_import))), @@ -1421,7 +1421,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), (sym::rustc_paren_sugar, Normal, template!(Word), Gated(Stability::Unstable, - "unboxed_closures", + sym::unboxed_closures, "unboxed_closures are still evolving", cfg_fn!(unboxed_closures))), @@ -1431,24 +1431,24 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ (sym::proc_macro, Normal, template!(Word), Ungated), (sym::rustc_proc_macro_decls, Normal, template!(Word), Gated(Stability::Unstable, - "rustc_attrs", + sym::rustc_attrs, "used internally by rustc", cfg_fn!(rustc_attrs))), (sym::allow_fail, Normal, template!(Word), Gated(Stability::Unstable, - "allow_fail", + sym::allow_fail, "allow_fail attribute is currently unstable", cfg_fn!(allow_fail))), (sym::rustc_std_internal_symbol, Whitelisted, template!(Word), Gated(Stability::Unstable, - "rustc_attrs", + sym::rustc_attrs, "this is an internal attribute that will \ never be stable", cfg_fn!(rustc_attrs))), // whitelists "identity-like" conversion methods to suggest on type mismatch (sym::rustc_conversion_suggestion, Whitelisted, template!(Word), Gated(Stability::Unstable, - "rustc_attrs", + sym::rustc_attrs, "this is an internal attribute that will \ never be stable", cfg_fn!(rustc_attrs))), @@ -1457,19 +1457,20 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ sym::rustc_args_required_const, Whitelisted, template!(List: "N"), - Gated(Stability::Unstable, "rustc_attrs", "never will be stable", cfg_fn!(rustc_attrs)) + Gated(Stability::Unstable, sym::rustc_attrs, "never will be stable", + cfg_fn!(rustc_attrs)) ), // RFC 2070 (sym::panic_handler, Normal, template!(Word), Ungated), (sym::alloc_error_handler, Normal, template!(Word), Gated(Stability::Unstable, - "alloc_error_handler", + sym::alloc_error_handler, "#[alloc_error_handler] is an unstable feature", cfg_fn!(alloc_error_handler))), // RFC 2412 (sym::optimize, Whitelisted, template!(List: "size|speed"), Gated(Stability::Unstable, - "optimize_attribute", + sym::optimize_attribute, "#[optimize] attribute is an unstable feature", cfg_fn!(optimize_attribute))), @@ -1483,7 +1484,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ (sym::recursion_limit, CrateLevel, template!(NameValueStr: "N"), Ungated), (sym::type_length_limit, CrateLevel, template!(NameValueStr: "N"), Ungated), (sym::test_runner, CrateLevel, template!(List: "path"), Gated(Stability::Unstable, - "custom_test_frameworks", + sym::custom_test_frameworks, EXPLAIN_CUSTOM_TEST_FRAMEWORKS, cfg_fn!(custom_test_frameworks))), ]; @@ -1503,11 +1504,11 @@ lazy_static! { } // cfg(...)'s that are feature gated -const GATED_CFGS: &[(&str, &str, fn(&Features) -> bool)] = &[ +const GATED_CFGS: &[(Symbol, Symbol, fn(&Features) -> bool)] = &[ // (name in cfg, feature, function to check if the feature is enabled) - ("target_thread_local", "cfg_target_thread_local", cfg_fn!(cfg_target_thread_local)), - ("target_has_atomic", "cfg_target_has_atomic", cfg_fn!(cfg_target_has_atomic)), - ("rustdoc", "doc_cfg", cfg_fn!(doc_cfg)), + (sym::target_thread_local, sym::cfg_target_thread_local, cfg_fn!(cfg_target_thread_local)), + (sym::target_has_atomic, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)), + (sym::rustdoc, sym::doc_cfg, cfg_fn!(doc_cfg)), ]; #[derive(Debug)] @@ -1540,7 +1541,7 @@ impl GatedCfg { struct Context<'a> { features: &'a Features, parse_sess: &'a ParseSess, - plugin_attributes: &'a [(String, AttributeType)], + plugin_attributes: &'a [(Symbol, AttributeType)], } macro_rules! gate_feature_fn { @@ -1559,11 +1560,11 @@ macro_rules! gate_feature_fn { macro_rules! gate_feature { ($cx: expr, $feature: ident, $span: expr, $explain: expr) => { gate_feature_fn!($cx, |x:&Features| x.$feature, $span, - stringify!($feature), $explain, GateStrength::Hard) + sym::$feature, $explain, GateStrength::Hard) }; ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => { gate_feature_fn!($cx, |x:&Features| x.$feature, $span, - stringify!($feature), $explain, $level) + sym::$feature, $explain, $level) }; } @@ -1594,8 +1595,8 @@ impl<'a> Context<'a> { debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage); return; } - for &(ref n, ref ty) in self.plugin_attributes { - if attr.path == &**n { + for &(n, ty) in self.plugin_attributes { + if attr.path == n { // Plugins can't gate attributes, so we don't check for it // unlike the code above; we only use this loop to // short-circuit to avoid the checks below. @@ -1629,7 +1630,7 @@ pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: ); } -fn find_lang_feature_issue(feature: &str) -> Option { +fn find_lang_feature_issue(feature: Symbol) -> Option { if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.0 == feature) { let issue = info.2; // FIXME (#28244): enforce that active features have issue numbers @@ -1661,7 +1662,7 @@ pub enum GateStrength { pub fn emit_feature_err( sess: &ParseSess, - feature: &str, + feature: Symbol, span: Span, issue: GateIssue, explain: &str, @@ -1671,7 +1672,7 @@ pub fn emit_feature_err( pub fn feature_err<'a>( sess: &'a ParseSess, - feature: &str, + feature: Symbol, span: Span, issue: GateIssue, explain: &str, @@ -1681,7 +1682,7 @@ pub fn feature_err<'a>( fn leveled_feature_err<'a>( sess: &'a ParseSess, - feature: &str, + feature: Symbol, span: Span, issue: GateIssue, explain: &str, @@ -1769,13 +1770,13 @@ struct PostExpansionVisitor<'a> { macro_rules! gate_feature_post { ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{ let (cx, span) = ($cx, $span); - if !span.allows_unstable(stringify!($feature)) { + if !span.allows_unstable(sym::$feature) { gate_feature!(cx.context, $feature, span, $explain) } }}; ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {{ let (cx, span) = ($cx, $span); - if !span.allows_unstable(stringify!($feature)) { + if !span.allows_unstable(sym::$feature) { gate_feature!(cx.context, $feature, span, $explain, $level) } }} @@ -1957,17 +1958,17 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } ast::ItemKind::Fn(..) => { - if attr::contains_name(&i.attrs[..], "plugin_registrar") { + if attr::contains_name(&i.attrs[..], sym::plugin_registrar) { gate_feature_post!(&self, plugin_registrar, i.span, "compiler plugins are experimental and possibly buggy"); } - if attr::contains_name(&i.attrs[..], "start") { + if attr::contains_name(&i.attrs[..], sym::start) { gate_feature_post!(&self, start, i.span, "a #[start] function is an experimental \ feature whose signature may change \ over time"); } - if attr::contains_name(&i.attrs[..], "main") { + if attr::contains_name(&i.attrs[..], sym::main) { gate_feature_post!(&self, main, i.span, "declaration of a nonstandard #[main] \ function may change over time, for now \ @@ -1976,7 +1977,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } ast::ItemKind::Struct(..) => { - for attr in attr::filter_by_name(&i.attrs[..], "repr") { + for attr in attr::filter_by_name(&i.attrs[..], sym::repr) { for item in attr.meta_item_list().unwrap_or_else(Vec::new) { if item.check_name(sym::simd) { gate_feature_post!(&self, repr_simd, attr.span, @@ -1987,7 +1988,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } ast::ItemKind::Enum(..) => { - for attr in attr::filter_by_name(&i.attrs[..], "repr") { + for attr in attr::filter_by_name(&i.attrs[..], sym::repr) { for item in attr.meta_item_list().unwrap_or_else(Vec::new) { if item.check_name(sym::align) { gate_feature_post!(&self, repr_align_enum, attr.span, @@ -2051,7 +2052,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { match i.node { ast::ForeignItemKind::Fn(..) | ast::ForeignItemKind::Static(..) => { - let link_name = attr::first_attr_value_str_by_name(&i.attrs, "link_name"); + let link_name = attr::first_attr_value_str_by_name(&i.attrs, sym::link_name); let links_to_llvm = match link_name { Some(val) => val.as_str().starts_with("llvm."), _ => false @@ -2311,7 +2312,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], if let Some(f_edition) = f_edition { if f_edition <= crate_edition { set(&mut features, DUMMY_SP); - edition_enabled_features.insert(Symbol::intern(name), crate_edition); + edition_enabled_features.insert(name, crate_edition); } } } @@ -2355,7 +2356,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], // FIXME(Manishearth) there is currently no way to set // lib features by edition set(&mut features, DUMMY_SP); - edition_enabled_features.insert(Symbol::intern(name), *edition); + edition_enabled_features.insert(name, *edition); } } } @@ -2438,7 +2439,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], pub fn check_crate(krate: &ast::Crate, sess: &ParseSess, features: &Features, - plugin_attributes: &[(String, AttributeType)], + plugin_attributes: &[(Symbol, AttributeType)], unstable: UnstableFeatures) { maybe_stage_features(&sess.span_diagnostic, krate, unstable); let ctx = Context { diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 526143b28755f..64f3704e8083f 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -575,13 +575,15 @@ mod tests { #[test] fn crlf_doc_comments() { with_globals(|| { + use crate::symbol::sym; + let sess = ParseSess::new(FilePathMapping::empty()); let name_1 = FileName::Custom("crlf_source_1".to_string()); let source = "/// doc comment\r\nfn foo() {}".to_string(); let item = parse_item_from_source_str(name_1, source, &sess) .unwrap().unwrap(); - let doc = first_attr_value_str_by_name(&item.attrs, "doc").unwrap(); + let doc = first_attr_value_str_by_name(&item.attrs, sym::doc).unwrap(); assert_eq!(doc, "/// doc comment"); let name_2 = FileName::Custom("crlf_source_2".to_string()); @@ -596,7 +598,7 @@ mod tests { let name_3 = FileName::Custom("clrf_source_3".to_string()); let source = "/** doc comment\r\n * with CRLF */\r\nfn foo() {}".to_string(); let item = parse_item_from_source_str(name_3, source, &sess).unwrap().unwrap(); - let doc = first_attr_value_str_by_name(&item.attrs, "doc").unwrap(); + let doc = first_attr_value_str_by_name(&item.attrs, sym::doc).unwrap(); assert_eq!(doc, "/** doc comment\n * with CRLF */"); }); } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index f95981680b940..d3dd6bb1e01a9 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -46,7 +46,7 @@ use crate::ptr::P; use crate::parse::PResult; use crate::ThinVec; use crate::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint}; -use crate::symbol::{keywords, Symbol}; +use crate::symbol::{keywords, sym, Symbol}; use errors::{Applicability, DiagnosticBuilder, DiagnosticId, FatalError}; use rustc_target::spec::abi::{self, Abi}; @@ -7263,7 +7263,7 @@ impl<'a> Parser<'a> { } fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) { - if let Some(path) = attr::first_attr_value_str_by_name(attrs, "path") { + if let Some(path) = attr::first_attr_value_str_by_name(attrs, sym::path) { self.directory.path.to_mut().push(&path.as_str()); self.directory.ownership = DirectoryOwnership::Owned { relative: None }; } else { @@ -7283,7 +7283,7 @@ impl<'a> Parser<'a> { } pub fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option { - if let Some(s) = attr::first_attr_value_str_by_name(attrs, "path") { + if let Some(s) = attr::first_attr_value_str_by_name(attrs, sym::path) { let s = s.as_str(); // On windows, the base path might have the form diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index b9758bd655c15..42ca8b7c23cb0 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -2,7 +2,7 @@ use crate::ast; use crate::attr; use crate::edition::Edition; use crate::ext::hygiene::{Mark, SyntaxContext}; -use crate::symbol::{Symbol, keywords}; +use crate::symbol::{Symbol, keywords, sym}; use crate::source_map::{ExpnInfo, MacroAttribute, dummy_spanned, hygiene, respan}; use crate::ptr::P; use crate::tokenstream::TokenStream; @@ -46,10 +46,10 @@ pub fn maybe_inject_crates_ref( let rust_2018 = edition >= Edition::Edition2018; // the first name in this list is the crate name of the crate with the prelude - let names: &[&str] = if attr::contains_name(&krate.attrs, "no_core") { + let names: &[&str] = if attr::contains_name(&krate.attrs, sym::no_core) { return krate; - } else if attr::contains_name(&krate.attrs, "no_std") { - if attr::contains_name(&krate.attrs, "compiler_builtins") { + } else if attr::contains_name(&krate.attrs, sym::no_std) { + if attr::contains_name(&krate.attrs, sym::compiler_builtins) { &["core"] } else { &["core", "compiler_builtins"] diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 03d0eff266e75..8e5e594ce9aa5 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -29,7 +29,7 @@ use crate::parse::{token, ParseSess}; use crate::print::pprust; use crate::ast::{self, Ident}; use crate::ptr::P; -use crate::symbol::{self, Symbol, keywords}; +use crate::symbol::{self, Symbol, keywords, sym}; use crate::ThinVec; struct Test { @@ -65,8 +65,7 @@ pub fn modify_for_testing(sess: &ParseSess, // unconditional, so that the attribute is still marked as used in // non-test builds. let reexport_test_harness_main = - attr::first_attr_value_str_by_name(&krate.attrs, - "reexport_test_harness_main"); + attr::first_attr_value_str_by_name(&krate.attrs, sym::reexport_test_harness_main); // Do this here so that the test_runner crate attribute gets marked as used // even in non-test builds @@ -185,7 +184,7 @@ impl MutVisitor for EntryPointCleaner { ident, attrs: attrs.into_iter() .filter(|attr| { - !attr.check_name("main") && !attr.check_name("start") + !attr.check_name(sym::main) && !attr.check_name(sym::start) }) .chain(iter::once(allow_dead_code)) .collect(), @@ -428,11 +427,11 @@ fn visible_path(cx: &TestCtxt<'_>, path: &[Ident]) -> Vec{ } fn is_test_case(i: &ast::Item) -> bool { - attr::contains_name(&i.attrs, "rustc_test_marker") + attr::contains_name(&i.attrs, sym::rustc_test_marker) } fn get_test_runner(sd: &errors::Handler, krate: &ast::Crate) -> Option { - let test_attr = attr::find_by_name(&krate.attrs, "test_runner")?; + let test_attr = attr::find_by_name(&krate.attrs, sym::test_runner)?; test_attr.meta_item_list().map(|meta_list| { if meta_list.len() != 1 { sd.span_fatal(test_attr.span, diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs index 8edd0e1ae3884..6213736ed5f46 100644 --- a/src/libsyntax_ext/asm.rs +++ b/src/libsyntax_ext/asm.rs @@ -11,7 +11,7 @@ use syntax::ext::base::{self, *}; use syntax::feature_gate; use syntax::parse::{self, token}; use syntax::ptr::P; -use syntax::symbol::Symbol; +use syntax::symbol::{Symbol, sym}; use syntax::ast::AsmDialect; use syntax_pos::Span; use syntax::tokenstream; @@ -47,7 +47,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt<'_>, -> Box { if !cx.ecfg.enable_asm() { feature_gate::emit_feature_err(&cx.parse_sess, - "asm", + sym::asm, sp, feature_gate::GateIssue::Language, feature_gate::EXPLAIN_ASM); diff --git a/src/libsyntax_ext/concat_idents.rs b/src/libsyntax_ext/concat_idents.rs index 8c9eb4bf2d8ff..77c53f402cc9f 100644 --- a/src/libsyntax_ext/concat_idents.rs +++ b/src/libsyntax_ext/concat_idents.rs @@ -6,7 +6,7 @@ use syntax::feature_gate; use syntax::parse::token; use syntax::ptr::P; use syntax_pos::Span; -use syntax_pos::symbol::Symbol; +use syntax_pos::symbol::{Symbol, sym}; use syntax::tokenstream::TokenTree; pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt<'_>, @@ -15,7 +15,7 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt<'_>, -> Box { if !cx.ecfg.enable_concat_idents() { feature_gate::emit_feature_err(&cx.parse_sess, - "concat_idents", + sym::concat_idents, sp, feature_gate::GateIssue::Language, feature_gate::EXPLAIN_CONCAT_IDENTS); diff --git a/src/libsyntax_ext/deriving/clone.rs b/src/libsyntax_ext/deriving/clone.rs index b347092e1bc4c..1b0d572324a79 100644 --- a/src/libsyntax_ext/deriving/clone.rs +++ b/src/libsyntax_ext/deriving/clone.rs @@ -7,7 +7,7 @@ use syntax::attr; use syntax::ext::base::{Annotatable, ExtCtxt}; use syntax::ext::build::AstBuilder; use syntax::ptr::P; -use syntax::symbol::{Symbol, keywords}; +use syntax::symbol::{Symbol, keywords, sym}; use syntax_pos::Span; pub fn expand_deriving_clone(cx: &mut ExtCtxt<'_>, @@ -37,7 +37,7 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt<'_>, match annitem.node { ItemKind::Struct(_, Generics { ref params, .. }) | ItemKind::Enum(_, Generics { ref params, .. }) => { - if attr::contains_name(&annitem.attrs, "rustc_copy_clone_marker") && + if attr::contains_name(&annitem.attrs, sym::rustc_copy_clone_marker) && !params.iter().any(|param| match param.kind { ast::GenericParamKind::Type { .. } => true, _ => false, diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index e5939e396e5c1..228862c830fd8 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -191,7 +191,7 @@ use syntax::ext::build::AstBuilder; use syntax::source_map::{self, respan}; use syntax::util::map_in_place::MapInPlace; use syntax::ptr::P; -use syntax::symbol::{Symbol, keywords}; +use syntax::symbol::{Symbol, keywords, sym}; use syntax::parse::ParseSess; use syntax_pos::{DUMMY_SP, Span}; @@ -426,7 +426,7 @@ impl<'a> TraitDef<'a> { } }; let is_always_copy = - attr::contains_name(&item.attrs, "rustc_copy_clone_marker") && + attr::contains_name(&item.attrs, sym::rustc_copy_clone_marker) && has_no_type_params; let use_temporaries = is_packed && is_always_copy; diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 24fbc9b6caf3f..9e54c0634b666 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -12,7 +12,7 @@ use syntax::ext::build::AstBuilder; use syntax::feature_gate; use syntax::parse::token; use syntax::ptr::P; -use syntax::symbol::Symbol; +use syntax::symbol::{Symbol, sym}; use syntax::tokenstream; use syntax_pos::{MultiSpan, Span, DUMMY_SP}; @@ -711,12 +711,12 @@ pub fn expand_format_args_nl<'cx>( //if !ecx.ecfg.enable_allow_internal_unstable() { // For some reason, the only one that actually works for `println` is the first check - if !sp.allows_unstable("format_args_nl") // the span is marked as `#[allow_insternal_unsable]` + if !sp.allows_unstable(sym::format_args_nl) // the span is marked `#[allow_insternal_unsable]` && !ecx.ecfg.enable_allow_internal_unstable() // NOTE: when is this enabled? && !ecx.ecfg.enable_format_args_nl() // enabled using `#[feature(format_args_nl]` { feature_gate::emit_feature_err(&ecx.parse_sess, - "format_args_nl", + sym::format_args_nl, sp, feature_gate::GateIssue::Language, feature_gate::EXPLAIN_FORMAT_ARGS_NL); diff --git a/src/libsyntax_ext/global_asm.rs b/src/libsyntax_ext/global_asm.rs index 2baf530aedae7..3f2853e4b0e20 100644 --- a/src/libsyntax_ext/global_asm.rs +++ b/src/libsyntax_ext/global_asm.rs @@ -16,12 +16,12 @@ use syntax::ext::base::{self, *}; use syntax::feature_gate; use syntax::parse::token; use syntax::ptr::P; -use syntax::symbol::Symbol; +use syntax::symbol::{Symbol, sym}; use syntax_pos::Span; use syntax::tokenstream; use smallvec::smallvec; -pub const MACRO: &str = "global_asm"; +pub const MACRO: Symbol = sym::global_asm; pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, diff --git a/src/libsyntax_ext/log_syntax.rs b/src/libsyntax_ext/log_syntax.rs index 658ce98d26884..1be3990837cfe 100644 --- a/src/libsyntax_ext/log_syntax.rs +++ b/src/libsyntax_ext/log_syntax.rs @@ -2,6 +2,7 @@ use syntax::ext::base; use syntax::feature_gate; use syntax::print; use syntax::tokenstream; +use syntax::symbol::sym; use syntax_pos; pub fn expand_syntax_ext<'cx>(cx: &'cx mut base::ExtCtxt<'_>, @@ -10,7 +11,7 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut base::ExtCtxt<'_>, -> Box { if !cx.ecfg.enable_log_syntax() { feature_gate::emit_feature_err(&cx.parse_sess, - "log_syntax", + sym::log_syntax, sp, feature_gate::GateIssue::Language, feature_gate::EXPLAIN_LOG_SYNTAX); diff --git a/src/libsyntax_ext/proc_macro_decls.rs b/src/libsyntax_ext/proc_macro_decls.rs index f0390ba3d40cb..5ced1400acb0e 100644 --- a/src/libsyntax_ext/proc_macro_decls.rs +++ b/src/libsyntax_ext/proc_macro_decls.rs @@ -13,12 +13,16 @@ use syntax::mut_visit::MutVisitor; use syntax::parse::ParseSess; use syntax::ptr::P; use syntax::symbol::Symbol; -use syntax::symbol::keywords; +use syntax::symbol::{keywords, sym}; use syntax::visit::{self, Visitor}; use syntax_pos::{Span, DUMMY_SP}; -const PROC_MACRO_KINDS: [&str; 3] = ["proc_macro_derive", "proc_macro_attribute", "proc_macro"]; +const PROC_MACRO_KINDS: [Symbol; 3] = [ + sym::proc_macro_derive, + sym::proc_macro_attribute, + sym::proc_macro +]; struct ProcMacroDerive { trait_name: ast::Name, @@ -139,7 +143,7 @@ impl<'a> CollectProcMacros<'a> { let attributes_attr = list.get(1); let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr { - if !attr.check_name("attributes") { + if !attr.check_name(sym::attributes) { self.handler.span_err(attr.span(), "second argument must be `attributes`") } attr.meta_item_list().unwrap_or_else(|| { @@ -231,7 +235,7 @@ impl<'a> CollectProcMacros<'a> { impl<'a> Visitor<'a> for CollectProcMacros<'a> { fn visit_item(&mut self, item: &'a ast::Item) { if let ast::ItemKind::MacroDef(..) = item.node { - if self.is_proc_macro_crate && attr::contains_name(&item.attrs, "macro_export") { + if self.is_proc_macro_crate && attr::contains_name(&item.attrs, sym::macro_export) { let msg = "cannot export macro_rules! macros from a `proc-macro` crate type currently"; self.handler.span_err(item.span, msg); @@ -304,11 +308,11 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { return; } - if attr.check_name("proc_macro_derive") { + if attr.check_name(sym::proc_macro_derive) { self.collect_custom_derive(item, attr); - } else if attr.check_name("proc_macro_attribute") { + } else if attr.check_name(sym::proc_macro_attribute) { self.collect_attr_proc_macro(item); - } else if attr.check_name("proc_macro") { + } else if attr.check_name(sym::proc_macro) { self.collect_bang_proc_macro(item); }; diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs index 0fa5cd64360c0..86ae6ab5fece5 100644 --- a/src/libsyntax_ext/test.rs +++ b/src/libsyntax_ext/test.rs @@ -7,7 +7,7 @@ use syntax::ext::hygiene::{self, Mark, SyntaxContext}; use syntax::attr; use syntax::ast; use syntax::print::pprust; -use syntax::symbol::Symbol; +use syntax::symbol::{Symbol, sym}; use syntax_pos::{DUMMY_SP, Span}; use syntax::source_map::{ExpnInfo, MacroAttribute}; use std::iter; @@ -206,15 +206,15 @@ enum ShouldPanic { } fn should_ignore(i: &ast::Item) -> bool { - attr::contains_name(&i.attrs, "ignore") + attr::contains_name(&i.attrs, sym::ignore) } fn should_fail(i: &ast::Item) -> bool { - attr::contains_name(&i.attrs, "allow_fail") + attr::contains_name(&i.attrs, sym::allow_fail) } fn should_panic(cx: &ExtCtxt<'_>, i: &ast::Item) -> ShouldPanic { - match attr::find_by_name(&i.attrs, "should_panic") { + match attr::find_by_name(&i.attrs, sym::should_panic) { Some(attr) => { let ref sd = cx.parse_sess.span_diagnostic; @@ -222,7 +222,7 @@ fn should_panic(cx: &ExtCtxt<'_>, i: &ast::Item) -> ShouldPanic { // Handle #[should_panic(expected = "foo")] Some(list) => { let msg = list.iter() - .find(|mi| mi.check_name("expected")) + .find(|mi| mi.check_name(sym::expected)) .and_then(|mi| mi.meta_item()) .and_then(|mi| mi.value_str()); if list.len() != 1 || msg.is_none() { @@ -247,7 +247,7 @@ fn should_panic(cx: &ExtCtxt<'_>, i: &ast::Item) -> ShouldPanic { } fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool { - let has_should_panic_attr = attr::contains_name(&i.attrs, "should_panic"); + let has_should_panic_attr = attr::contains_name(&i.attrs, sym::should_panic); let ref sd = cx.parse_sess.span_diagnostic; if let ast::ItemKind::Fn(ref decl, ref header, ref generics, _) = i.node { if header.unsafety == ast::Unsafety::Unsafe { diff --git a/src/libsyntax_ext/test_case.rs b/src/libsyntax_ext/test_case.rs index 1ed1ab0a07b96..802037f6d22bb 100644 --- a/src/libsyntax_ext/test_case.rs +++ b/src/libsyntax_ext/test_case.rs @@ -14,7 +14,7 @@ use syntax::ext::build::AstBuilder; use syntax::ext::hygiene::{self, Mark, SyntaxContext}; use syntax::ast; use syntax::source_map::respan; -use syntax::symbol::Symbol; +use syntax::symbol::{Symbol, sym}; use syntax_pos::{DUMMY_SP, Span}; use syntax::source_map::{ExpnInfo, MacroAttribute}; use syntax::feature_gate; @@ -27,7 +27,7 @@ pub fn expand( ) -> Vec { if !ecx.ecfg.enable_custom_test_frameworks() { feature_gate::emit_feature_err(&ecx.parse_sess, - "custom_test_frameworks", + sym::custom_test_frameworks, attr_sp, feature_gate::GateIssue::Language, feature_gate::EXPLAIN_CUSTOM_TEST_FRAMEWORKS); diff --git a/src/libsyntax_ext/trace_macros.rs b/src/libsyntax_ext/trace_macros.rs index 4d35daf3de998..eca658cb5473e 100644 --- a/src/libsyntax_ext/trace_macros.rs +++ b/src/libsyntax_ext/trace_macros.rs @@ -1,6 +1,6 @@ use syntax::ext::base::{self, ExtCtxt}; use syntax::feature_gate; -use syntax::symbol::keywords; +use syntax::symbol::{keywords, sym}; use syntax_pos::Span; use syntax::tokenstream::TokenTree; @@ -10,7 +10,7 @@ pub fn expand_trace_macros(cx: &mut ExtCtxt<'_>, -> Box { if !cx.ecfg.enable_trace_macros() { feature_gate::emit_feature_err(&cx.parse_sess, - "trace_macros", + sym::trace_macros, sp, feature_gate::GateIssue::Language, feature_gate::EXPLAIN_TRACE_MACROS); diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index d690a39199625..c5d6da74eb618 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -33,7 +33,7 @@ mod span_encoding; pub use span_encoding::{Span, DUMMY_SP}; pub mod symbol; -pub use symbol::sym; +pub use symbol::{Symbol, sym}; mod analyze_source_file; @@ -388,7 +388,7 @@ impl Span { /// Checks if a span is "internal" to a macro in which `#[unstable]` /// items can be used (that is, a macro marked with /// `#[allow_internal_unstable]`). - pub fn allows_unstable(&self, feature: &str) -> bool { + pub fn allows_unstable(&self, feature: Symbol) -> bool { match self.ctxt().outer().expn_info() { Some(info) => info .allow_internal_unstable diff --git a/src/test/run-pass-fulldeps/auxiliary/custom-derive-plugin-attr.rs b/src/test/run-pass-fulldeps/auxiliary/custom-derive-plugin-attr.rs index 699972c9a85bd..c6b33fbc75ee2 100644 --- a/src/test/run-pass-fulldeps/auxiliary/custom-derive-plugin-attr.rs +++ b/src/test/run-pass-fulldeps/auxiliary/custom-derive-plugin-attr.rs @@ -14,7 +14,7 @@ use syntax::ast; use syntax::attr; use syntax::ext::base::{MultiDecorator, ExtCtxt, Annotatable}; use syntax::ext::build::AstBuilder; -use syntax::symbol::Symbol; +use syntax::symbol::{Symbol, sym}; use syntax::ptr::P; use syntax_ext::deriving::generic::{TraitDef, MethodDef, combine_substructure}; use syntax_ext::deriving::generic::{Substructure, Struct, EnumMatching}; @@ -71,7 +71,7 @@ fn totalsum_substructure(cx: &mut ExtCtxt, trait_span: Span, }; fields.iter().fold(cx.expr_isize(trait_span, 0), |acc, ref item| { - if attr::contains_name(&item.attrs, "ignore") { + if attr::contains_name(&item.attrs, sym::ignore) { acc } else { cx.expr_binary(item.span, ast::BinOpKind::Add, acc, diff --git a/src/test/run-pass-fulldeps/auxiliary/issue-40001-plugin.rs b/src/test/run-pass-fulldeps/auxiliary/issue-40001-plugin.rs index 76d0906f97c9a..40e0115c623ee 100644 --- a/src/test/run-pass-fulldeps/auxiliary/issue-40001-plugin.rs +++ b/src/test/run-pass-fulldeps/auxiliary/issue-40001-plugin.rs @@ -23,7 +23,7 @@ use syntax::{ast, source_map}; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box MissingWhitelistedAttrPass); - reg.register_attribute("whitelisted_attr".to_string(), Whitelisted); + reg.register_attribute(Symbol::intern("whitelisted_attr"), Whitelisted); } declare_lint! { @@ -48,7 +48,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingWhitelistedAttrPass { _ => cx.tcx.hir().expect_item_by_hir_id(cx.tcx.hir().get_parent_item(id)), }; - if !attr::contains_name(&item.attrs, "whitelisted_attr") { + if !attr::contains_name(&item.attrs, Symbol::intern("whitelisted_attr")) { cx.span_lint(MISSING_WHITELISTED_ATTR, span, "Missing 'whitelisted_attr' attribute"); } diff --git a/src/test/run-pass-fulldeps/auxiliary/lint-for-crate.rs b/src/test/run-pass-fulldeps/auxiliary/lint-for-crate.rs index f34e10218d455..8c7bd7222e73c 100644 --- a/src/test/run-pass-fulldeps/auxiliary/lint-for-crate.rs +++ b/src/test/run-pass-fulldeps/auxiliary/lint-for-crate.rs @@ -11,6 +11,7 @@ use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LateLintPass use rustc_plugin::Registry; use rustc::hir; use syntax::attr; +use syntax::symbol::Symbol; macro_rules! fake_lint_pass { ($struct:ident, $lints:expr, $($attr:expr),*) => { @@ -49,19 +50,19 @@ declare_lint!(CRATE_NOT_GREEN, Warn, "crate not marked with #![crate_green]"); fake_lint_pass! { PassOkay, lint_array!(CRATE_NOT_OKAY), // Single lint - "rustc_crate_okay" + Symbol::intern("rustc_crate_okay") } fake_lint_pass! { PassRedBlue, lint_array!(CRATE_NOT_RED, CRATE_NOT_BLUE), // Multiple lints - "rustc_crate_red", "rustc_crate_blue" + Symbol::intern("rustc_crate_red"), Symbol::intern("rustc_crate_blue") } fake_lint_pass! { PassGreyGreen, lint_array!(CRATE_NOT_GREY, CRATE_NOT_GREEN, ), // Trailing comma - "rustc_crate_grey", "rustc_crate_green" + Symbol::intern("rustc_crate_grey"), Symbol::intern("rustc_crate_green") } #[plugin_registrar] diff --git a/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs index c83e7bdb9983e..039124f31ff42 100644 --- a/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs +++ b/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs @@ -8,14 +8,14 @@ extern crate syntax; extern crate rustc; extern crate rustc_plugin; +use syntax::symbol::Symbol; use syntax::feature_gate::AttributeType; use rustc_plugin::Registry; - #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { - reg.register_attribute("foo".to_owned(), AttributeType::Normal); - reg.register_attribute("bar".to_owned(), AttributeType::CrateLevel); - reg.register_attribute("baz".to_owned(), AttributeType::Whitelisted); + reg.register_attribute(Symbol::intern("foo"), AttributeType::Normal); + reg.register_attribute(Symbol::intern("bar"), AttributeType::CrateLevel); + reg.register_attribute(Symbol::intern("baz"), AttributeType::Whitelisted); } diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs index e8f1d2eedf559..7656b15721ada 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs @@ -11,6 +11,7 @@ use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LateLintPass use rustc_plugin::Registry; use rustc::hir; use syntax::attr; +use syntax::symbol::Symbol; declare_lint! { CRATE_NOT_OKAY, @@ -22,7 +23,7 @@ declare_lint_pass!(Pass => [CRATE_NOT_OKAY]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_crate(&mut self, cx: &LateContext, krate: &hir::Crate) { - if !attr::contains_name(&krate.attrs, "crate_okay") { + if !attr::contains_name(&krate.attrs, Symbol::intern("crate_okay")) { cx.span_lint(CRATE_NOT_OKAY, krate.span, "crate is not marked with #![crate_okay]"); } From 999c1fc2819e34539706b193711735d997633ef1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 7 May 2019 16:03:44 +1000 Subject: [PATCH 207/212] Remove the equality operation between `Symbol` and strings. And also the equality between `Path` and strings, because `Path` is made up of `Symbol`s. --- src/librustc/hir/lowering.rs | 69 ++++++++++--------- src/librustc/hir/map/mod.rs | 4 +- src/librustc/lint/levels.rs | 4 +- src/librustc/middle/entry.rs | 2 +- src/librustc/middle/lib_features.rs | 2 +- src/librustc/middle/stability.rs | 2 +- src/librustc/middle/weak_lang_items.rs | 6 +- src/librustc/session/config.rs | 3 +- src/librustc/traits/project.rs | 5 +- src/librustc_codegen_ssa/back/write.rs | 2 +- src/librustc_codegen_utils/link.rs | 2 +- src/librustc_driver/lib.rs | 3 +- src/librustc_interface/util.rs | 30 ++++---- src/librustc_metadata/creader.rs | 2 +- src/librustc_metadata/cstore_impl.rs | 4 +- src/librustc_metadata/link_args.rs | 2 +- src/librustc_metadata/locator.rs | 4 +- src/librustc_metadata/native_libs.rs | 4 +- src/librustc_plugin/registry.rs | 4 +- src/librustc_resolve/build_reduced_graph.rs | 2 +- src/librustc_resolve/lib.rs | 6 +- src/librustc_resolve/macros.rs | 13 ++-- src/librustc_resolve/resolve_imports.rs | 13 ++-- src/librustc_save_analysis/lib.rs | 2 +- src/librustc_typeck/check/mod.rs | 3 +- src/librustc_typeck/collect.rs | 4 +- src/librustdoc/clean/cfg.rs | 4 +- src/librustdoc/clean/mod.rs | 4 +- src/librustdoc/core.rs | 4 +- .../passes/collect_intra_doc_links.rs | 2 +- src/libsyntax/ast.rs | 6 -- src/libsyntax/attr/builtin.rs | 22 +++--- src/libsyntax/entry.rs | 2 +- src/libsyntax/ext/base.rs | 4 +- src/libsyntax/ext/derive.rs | 4 +- src/libsyntax/ext/expand.rs | 8 +-- src/libsyntax/ext/tt/macro_rules.rs | 23 ++++--- src/libsyntax/feature_gate.rs | 18 ++--- src/libsyntax/parse/mod.rs | 16 +++-- src/libsyntax/parse/parser.rs | 2 +- src/libsyntax/std_inject.rs | 3 + src/libsyntax/test.rs | 3 +- src/libsyntax_ext/asm.rs | 8 +-- src/libsyntax_ext/deriving/mod.rs | 4 +- src/libsyntax_pos/edition.rs | 7 +- src/libsyntax_pos/lib.rs | 2 +- src/libsyntax_pos/symbol.rs | 6 -- .../ui-fulldeps/auxiliary/lint-plugin-test.rs | 2 +- .../ui-fulldeps/auxiliary/lint-tool-test.rs | 4 +- 49 files changed, 182 insertions(+), 173 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 0d80a0874e63f..dd0d13d8f5a6a 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -73,7 +73,7 @@ use syntax_pos::Span; const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF; pub struct LoweringContext<'a> { - crate_root: Option<&'static str>, + crate_root: Option, /// Used to assign ids to HIR nodes that do not directly correspond to an AST node. sess: &'a Session, @@ -164,8 +164,8 @@ pub trait Resolver { fn resolve_str_path( &mut self, span: Span, - crate_root: Option<&str>, - components: &[&str], + crate_root: Option, + components: &[Symbol], is_value: bool, ) -> hir::Path; } @@ -228,7 +228,7 @@ pub fn lower_crate( dep_graph.assert_ignored(); LoweringContext { - crate_root: std_inject::injected_crate_name(), + crate_root: std_inject::injected_crate_name().map(Symbol::intern), sess, cstore, resolver, @@ -1149,7 +1149,7 @@ impl<'a> LoweringContext<'a> { ].into()), ); let gen_future = self.expr_std_path( - unstable_span, &["future", "from_generator"], None, ThinVec::new()); + unstable_span, &[sym::future, sym::from_generator], None, ThinVec::new()); hir::ExprKind::Call(P(gen_future), hir_vec![generator]) } @@ -2548,7 +2548,7 @@ impl<'a> LoweringContext<'a> { // ::std::future::Future let future_path = - self.std_path(span, &["future", "Future"], Some(future_params), false); + self.std_path(span, &[sym::future, sym::Future], Some(future_params), false); hir::GenericBound::Trait( hir::PolyTraitRef { @@ -4194,7 +4194,7 @@ impl<'a> LoweringContext<'a> { |x: P| x.into_inner(), ); block.expr = Some(this.wrap_in_try_constructor( - "from_ok", tail, unstable_span)); + sym::from_ok, tail, unstable_span)); hir::ExprKind::Block(P(block), None) }) } @@ -4336,7 +4336,7 @@ impl<'a> LoweringContext<'a> { self.expr_call_std_assoc_fn( id, e.span, - &["ops", "RangeInclusive"], + &[sym::ops, sym::RangeInclusive], "new", hir_vec![e1, e2], ) @@ -4345,11 +4345,11 @@ impl<'a> LoweringContext<'a> { use syntax::ast::RangeLimits::*; let path = match (e1, e2, lims) { - (&None, &None, HalfOpen) => "RangeFull", - (&Some(..), &None, HalfOpen) => "RangeFrom", - (&None, &Some(..), HalfOpen) => "RangeTo", - (&Some(..), &Some(..), HalfOpen) => "Range", - (&None, &Some(..), Closed) => "RangeToInclusive", + (&None, &None, HalfOpen) => sym::RangeFull, + (&Some(..), &None, HalfOpen) => sym::RangeFrom, + (&None, &Some(..), HalfOpen) => sym::RangeTo, + (&Some(..), &Some(..), HalfOpen) => sym::Range, + (&None, &Some(..), Closed) => sym::RangeToInclusive, (&Some(..), &Some(..), Closed) => unreachable!(), (_, &None, Closed) => self.diagnostic() .span_fatal(e.span, "inclusive range with no end") @@ -4367,7 +4367,7 @@ impl<'a> LoweringContext<'a> { .collect::>(); let is_unit = fields.is_empty(); - let struct_path = ["ops", path]; + let struct_path = [sym::ops, path]; let struct_path = self.std_path(e.span, &struct_path, None, is_unit); let struct_path = hir::QPath::Resolved(None, P(struct_path)); @@ -4656,7 +4656,7 @@ impl<'a> LoweringContext<'a> { let match_expr = { let iter = P(self.expr_ident(head_sp, iter, iter_pat_nid)); let ref_mut_iter = self.expr_mut_addr_of(head_sp, iter); - let next_path = &["iter", "Iterator", "next"]; + let next_path = &[sym::iter, sym::Iterator, sym::next]; let next_expr = P(self.expr_call_std_path( head_sp, next_path, @@ -4723,7 +4723,8 @@ impl<'a> LoweringContext<'a> { // `match ::std::iter::IntoIterator::into_iter() { ... }` let into_iter_expr = { - let into_iter_path = &["iter", "IntoIterator", "into_iter"]; + let into_iter_path = + &[sym::iter, sym::IntoIterator, sym::into_iter]; P(self.expr_call_std_path( head_sp, into_iter_path, @@ -4780,7 +4781,7 @@ impl<'a> LoweringContext<'a> { // expand let sub_expr = self.lower_expr(sub_expr); - let path = &["ops", "Try", "into_result"]; + let path = &[sym::ops, sym::Try, sym::into_result]; P(self.expr_call_std_path( unstable_span, path, @@ -4822,12 +4823,12 @@ impl<'a> LoweringContext<'a> { let err_ident = self.str_to_ident("err"); let (err_local, err_local_nid) = self.pat_ident(try_span, err_ident); let from_expr = { - let from_path = &["convert", "From", "from"]; + let from_path = &[sym::convert, sym::From, sym::from]; let err_expr = self.expr_ident(try_span, err_ident, err_local_nid); self.expr_call_std_path(try_span, from_path, hir_vec![err_expr]) }; let from_err_expr = - self.wrap_in_try_constructor("from_error", from_expr, unstable_span); + self.wrap_in_try_constructor(sym::from_error, from_expr, unstable_span); let thin_attrs = ThinVec::from(attrs); let catch_scope = self.catch_scopes.last().map(|x| *x); let ret_expr = if let Some(catch_node) = catch_scope { @@ -5057,7 +5058,7 @@ impl<'a> LoweringContext<'a> { fn expr_call_std_path( &mut self, span: Span, - path_components: &[&str], + path_components: &[Symbol], args: hir::HirVec, ) -> hir::Expr { let path = P(self.expr_std_path(span, path_components, None, ThinVec::new())); @@ -5077,7 +5078,7 @@ impl<'a> LoweringContext<'a> { &mut self, ty_path_id: hir::HirId, span: Span, - ty_path_components: &[&str], + ty_path_components: &[Symbol], assoc_fn_name: &str, args: hir::HirVec, ) -> hir::ExprKind { @@ -5119,7 +5120,7 @@ impl<'a> LoweringContext<'a> { fn expr_std_path( &mut self, span: Span, - components: &[&str], + components: &[Symbol], params: Option>, attrs: ThinVec, ) -> hir::Expr { @@ -5250,25 +5251,25 @@ impl<'a> LoweringContext<'a> { } fn pat_ok(&mut self, span: Span, pat: P) -> P { - self.pat_std_enum(span, &["result", "Result", "Ok"], hir_vec![pat]) + self.pat_std_enum(span, &[sym::result, sym::Result, sym::Ok], hir_vec![pat]) } fn pat_err(&mut self, span: Span, pat: P) -> P { - self.pat_std_enum(span, &["result", "Result", "Err"], hir_vec![pat]) + self.pat_std_enum(span, &[sym::result, sym::Result, sym::Err], hir_vec![pat]) } fn pat_some(&mut self, span: Span, pat: P) -> P { - self.pat_std_enum(span, &["option", "Option", "Some"], hir_vec![pat]) + self.pat_std_enum(span, &[sym::option, sym::Option, sym::Some], hir_vec![pat]) } fn pat_none(&mut self, span: Span) -> P { - self.pat_std_enum(span, &["option", "Option", "None"], hir_vec![]) + self.pat_std_enum(span, &[sym::option, sym::Option, sym::None], hir_vec![]) } fn pat_std_enum( &mut self, span: Span, - components: &[&str], + components: &[Symbol], subpats: hir::HirVec>, ) -> P { let path = self.std_path(span, components, None, true); @@ -5321,7 +5322,7 @@ impl<'a> LoweringContext<'a> { fn std_path( &mut self, span: Span, - components: &[&str], + components: &[Symbol], params: Option>, is_value: bool, ) -> hir::Path { @@ -5520,11 +5521,11 @@ impl<'a> LoweringContext<'a> { fn wrap_in_try_constructor( &mut self, - method: &'static str, + method: Symbol, e: hir::Expr, unstable_span: Span, ) -> P { - let path = &["ops", "Try", method]; + let path = &[sym::ops, sym::Try, method]; let from_err = P(self.expr_std_path(unstable_span, path, None, ThinVec::new())); P(self.expr_call(e.span, from_err, hir_vec![e])) @@ -5594,7 +5595,7 @@ impl<'a> LoweringContext<'a> { let new_unchecked_expr_kind = self.expr_call_std_assoc_fn( pin_ty_id, span, - &["pin", "Pin"], + &[sym::pin, sym::Pin], "new_unchecked", hir_vec![ref_mut_pinned], ); @@ -5602,7 +5603,7 @@ impl<'a> LoweringContext<'a> { let unsafe_expr = self.expr_unsafe(new_unchecked); P(self.expr_call_std_path( gen_future_span, - &["future", "poll_with_tls_context"], + &[sym::future, sym::poll_with_tls_context], hir_vec![unsafe_expr], )) }; @@ -5616,7 +5617,7 @@ impl<'a> LoweringContext<'a> { let x_expr = P(self.expr_ident(span, x_ident, x_pat_hid)); let ready_pat = self.pat_std_enum( span, - &["task", "Poll", "Ready"], + &[sym::task, sym::Poll, sym::Ready], hir_vec![x_pat], ); let break_x = self.with_loop_scope(loop_node_id, |this| { @@ -5633,7 +5634,7 @@ impl<'a> LoweringContext<'a> { let pending_arm = { let pending_pat = self.pat_std_enum( span, - &["task", "Poll", "Pending"], + &[sym::task, sym::Poll, sym::Pending], hir_vec![], ); let empty_block = P(self.expr_block_empty(span)); diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 1a48dff213b5f..b8ee98551a20e 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -1146,7 +1146,7 @@ impl<'a> NodesMatchingSuffix<'a> { None => return false, Some((node_id, name)) => (node_id, name), }; - if mod_name != &**part { + if mod_name.as_str() != *part { return false; } cursor = self.map.get_parent_item(mod_id); @@ -1183,7 +1183,7 @@ impl<'a> NodesMatchingSuffix<'a> { // We are looking at some node `n` with a given name and parent // id; do their names match what I am seeking? fn matches_names(&self, parent_of_n: HirId, name: Name) -> bool { - name == &**self.item_name && self.suffix_matches(parent_of_n) + name.as_str() == *self.item_name && self.suffix_matches(parent_of_n) } fn matches_suffix(&self, hir: HirId) -> bool { diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index a69758e33baba..6481f9af00b86 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -221,7 +221,7 @@ impl<'a> LintLevelsBuilder<'a> { match item.node { ast::MetaItemKind::Word => {} // actual lint names handled later ast::MetaItemKind::NameValue(ref name_value) => { - if item.path == "reason" { + if item.path == sym::reason { // found reason, reslice meta list to exclude it metas = &metas[0..metas.len()-1]; // FIXME (#55112): issue unused-attributes lint if we thereby @@ -261,7 +261,7 @@ impl<'a> LintLevelsBuilder<'a> { let mut err = bad_attr(li.span()); if let Some(item) = li.meta_item() { if let ast::MetaItemKind::NameValue(_) = item.node { - if item.path == "reason" { + if item.path == sym::reason { err.help("reason in lint attribute must come last"); } } diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs index e2e76e69dc4ed..67db2ec248156 100644 --- a/src/librustc/middle/entry.rs +++ b/src/librustc/middle/entry.rs @@ -86,7 +86,7 @@ fn entry_point_type(item: &Item, at_root: bool) -> EntryPointType { EntryPointType::Start } else if attr::contains_name(&item.attrs, sym::main) { EntryPointType::MainAttr - } else if item.ident.name == "main" { + } else if item.ident.name == sym::main { if at_root { // This is a top-level function so can be 'main'. EntryPointType::MainNamed diff --git a/src/librustc/middle/lib_features.rs b/src/librustc/middle/lib_features.rs index 5acd48c77d820..8696e2af8c2bc 100644 --- a/src/librustc/middle/lib_features.rs +++ b/src/librustc/middle/lib_features.rs @@ -76,7 +76,7 @@ impl<'a, 'tcx> LibFeatureCollector<'a, 'tcx> { // This additional check for stability is to make sure we // don't emit additional, irrelevant errors for malformed // attributes. - if *stab_attr != "stable" || since.is_some() { + if *stab_attr != sym::stable || since.is_some() { return Some((feature, since, attr.span)); } } diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index c608c72430cbe..d9a44714d7d08 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -686,7 +686,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // the `-Z force-unstable-if-unmarked` flag present (we're // compiling a compiler crate), then let this missing feature // annotation slide. - if feature == "rustc_private" && issue == 27812 { + if feature == sym::rustc_private && issue == 27812 { if self.sess.opts.debugging_opts.force_unstable_if_unmarked { return EvalResult::Allow; } diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs index 312924e5e90f5..75c21c738f7a0 100644 --- a/src/librustc/middle/weak_lang_items.rs +++ b/src/librustc/middle/weak_lang_items.rs @@ -6,7 +6,7 @@ use crate::middle::lang_items; use rustc_data_structures::fx::FxHashSet; use rustc_target::spec::PanicStrategy; use syntax::ast; -use syntax::symbol::Symbol; +use syntax::symbol::{Symbol, sym}; use syntax_pos::Span; use crate::hir::def_id::DefId; use crate::hir::intravisit::{Visitor, NestedVisitorMap}; @@ -46,8 +46,8 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pub fn link_name(attrs: &[ast::Attribute]) -> Option { lang_items::extract(attrs).and_then(|(name, _)| { - $(if name == stringify!($name) { - Some(Symbol::intern(stringify!($sym))) + $(if name == sym::$name { + Some(sym::$sym) } else)* { None } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 12427daa38381..f61ffac15d5f9 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -2753,6 +2753,7 @@ mod tests { // another --cfg test #[test] fn test_switch_implies_cfg_test_unless_cfg_test() { + use syntax::symbol::sym; syntax::with_globals(|| { let matches = &match optgroups().parse(&["--test".to_string(), "--cfg=test".to_string()]) { @@ -2763,7 +2764,7 @@ mod tests { let (sessopts, cfg) = build_session_options_and_crate_config(matches); let sess = build_session(sessopts, None, registry); let cfg = build_configuration(&sess, to_crate_config(cfg)); - let mut test_items = cfg.iter().filter(|&&(name, _)| name == "test"); + let mut test_items = cfg.iter().filter(|&&(name, _)| name == sym::test); assert!(test_items.next().is_some()); assert!(test_items.next().is_none()); }); diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index b5232e828c4cd..f05a19372918e 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -19,6 +19,7 @@ use crate::mir::interpret::{GlobalId, ConstValue}; use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap}; use rustc_macros::HashStable; use syntax::ast::Ident; +use syntax::symbol::sym; use crate::ty::subst::{Subst, InternalSubsts}; use crate::ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt}; use crate::ty::fold::{TypeFoldable, TypeFolder}; @@ -1318,9 +1319,9 @@ fn confirm_generator_candidate<'cx, 'gcx, 'tcx>( gen_sig) .map_bound(|(trait_ref, yield_ty, return_ty)| { let name = tcx.associated_item(obligation.predicate.item_def_id).ident.name; - let ty = if name == "Return" { + let ty = if name == sym::Return { return_ty - } else if name == "Yield" { + } else if name == sym::Yield { yield_ty } else { bug!() diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 204ca59efc8d3..6320d8a671ddb 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -386,7 +386,7 @@ pub fn start_async_codegen( let subsystem = attr::first_attr_value_str_by_name(&tcx.hir().krate().attrs, sym::windows_subsystem); let windows_subsystem = subsystem.map(|subsystem| { - if subsystem != "windows" && subsystem != "console" { + if subsystem != sym::windows && subsystem != sym::console { tcx.sess.fatal(&format!("invalid windows subsystem `{}`, only \ `windows` and `console` are allowed", subsystem)); diff --git a/src/librustc_codegen_utils/link.rs b/src/librustc_codegen_utils/link.rs index 30f37fefa7cf7..a2ac64fa7e0c6 100644 --- a/src/librustc_codegen_utils/link.rs +++ b/src/librustc_codegen_utils/link.rs @@ -56,7 +56,7 @@ pub fn find_crate_name(sess: Option<&Session>, if let Some(sess) = sess { if let Some(ref s) = sess.opts.crate_name { if let Some((attr, name)) = attr_crate_name { - if name != &**s { + if name.as_str() != *s { let msg = format!("--crate-name and #[crate_name] are \ required to match, but `{}` != `{}`", s, name); diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 5b42b049b5b18..02f8eee67b151 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -63,6 +63,7 @@ use syntax::ast; use syntax::source_map::FileLoader; use syntax::feature_gate::{GatedCfg, UnstableFeatures}; use syntax::parse::{self, PResult}; +use syntax::symbol::sym; use syntax_pos::{DUMMY_SP, MultiSpan, FileName}; pub mod pretty; @@ -669,7 +670,7 @@ impl RustcDefaultCalls { // through to build scripts. let value = value.as_ref().map(|s| s.as_str()); let value = value.as_ref().map(|s| s.as_ref()); - if name != "target_feature" || value != Some("crt-static") { + if name != sym::target_feature || value != Some("crt-static") { if !allow_unstable_cfg && gated_cfg.is_some() { return None } diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index 2b1a993d1cc2c..d2d0d19180783 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -497,22 +497,22 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec Some(config::CrateType::Rlib), - Some(ref n) if *n == "dylib" => Some(config::CrateType::Dylib), - Some(ref n) if *n == "cdylib" => Some(config::CrateType::Cdylib), - Some(ref n) if *n == "lib" => Some(config::default_lib_output()), - Some(ref n) if *n == "staticlib" => Some(config::CrateType::Staticlib), - Some(ref n) if *n == "proc-macro" => Some(config::CrateType::ProcMacro), - Some(ref n) if *n == "bin" => Some(config::CrateType::Executable), - Some(ref n) => { + Some(sym::rlib) => Some(config::CrateType::Rlib), + Some(sym::dylib) => Some(config::CrateType::Dylib), + Some(sym::cdylib) => Some(config::CrateType::Cdylib), + Some(sym::lib) => Some(config::default_lib_output()), + Some(sym::staticlib) => Some(config::CrateType::Staticlib), + Some(sym::proc_dash_macro) => Some(config::CrateType::ProcMacro), + Some(sym::bin) => Some(config::CrateType::Executable), + Some(n) => { let crate_types = vec![ - Symbol::intern("rlib"), - Symbol::intern("dylib"), - Symbol::intern("cdylib"), - Symbol::intern("lib"), - Symbol::intern("staticlib"), - Symbol::intern("proc-macro"), - Symbol::intern("bin") + sym::rlib, + sym::dylib, + sym::cdylib, + sym::lib, + sym::staticlib, + sym::proc_dash_macro, + sym::bin ]; if let ast::MetaItemKind::NameValue(spanned) = a.meta().unwrap().node { diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 20caad70f2b57..b7b17a84aa768 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -837,7 +837,7 @@ impl<'a> CrateLoader<'a> { let mut uses_std = false; self.cstore.iter_crate_data(|_, data| { - if data.name == "std" { + if data.name == sym::std { uses_std = true; } }); diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index dfeaeca323f8e..087256a971056 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -31,7 +31,7 @@ use syntax::source_map; use syntax::edition::Edition; use syntax::parse::source_file_to_stream; use syntax::parse::parser::emit_unclosed_delims; -use syntax::symbol::Symbol; +use syntax::symbol::{Symbol, sym}; use syntax_pos::{Span, NO_EXPANSION, FileName}; use rustc_data_structures::bit_set::BitSet; @@ -432,7 +432,7 @@ impl cstore::CStore { let data = self.get_crate_data(id.krate); if let Some(ref proc_macros) = data.proc_macros { return LoadedMacro::ProcMacro(proc_macros[id.index.to_proc_macro_index()].1.clone()); - } else if data.name == "proc_macro" && data.item_name(id.index) == "quote" { + } else if data.name == sym::proc_macro && data.item_name(id.index) == "quote" { use syntax::ext::base::SyntaxExtension; use syntax_ext::proc_macro_impl::BangProcMacro; diff --git a/src/librustc_metadata/link_args.rs b/src/librustc_metadata/link_args.rs index cd5951f0e0e3c..f4682465a659a 100644 --- a/src/librustc_metadata/link_args.rs +++ b/src/librustc_metadata/link_args.rs @@ -11,7 +11,7 @@ pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Vec { tcx.hir().krate().visit_all_item_likes(&mut collector); for attr in tcx.hir().krate().attrs.iter() { - if attr.path == "link_args" { + if attr.path == sym::link_args { if let Some(linkarg) = attr.value_str() { collector.add_link_args(&linkarg.as_str()); } diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index 116042c53fb9e..7d7dd1061a959 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -225,7 +225,7 @@ use rustc::session::search_paths::PathKind; use rustc::util::nodemap::FxHashMap; use errors::DiagnosticBuilder; -use syntax::symbol::Symbol; +use syntax::symbol::{Symbol, sym}; use syntax::struct_span_err; use syntax_pos::Span; use rustc_target::spec::{Target, TargetTriple}; @@ -408,7 +408,7 @@ impl<'a> Context<'a> { self.ident, add); - if (self.ident == "std" || self.ident == "core") + if (self.ident == sym::std || self.ident == sym::core) && self.triple != TargetTriple::from_triple(config::host_triple()) { err.note(&format!("the `{}` target may not be installed", self.triple)); } diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs index 3e7e740a15c04..fee08f421549d 100644 --- a/src/librustc_metadata/native_libs.rs +++ b/src/librustc_metadata/native_libs.rs @@ -181,7 +181,7 @@ impl<'a, 'tcx> Collector<'a, 'tcx> { let any_duplicate = self.libs .iter() .filter_map(|lib| lib.name.as_ref()) - .any(|n| n == name); + .any(|n| n.as_str() == *name); if new_name.is_empty() { self.tcx.sess.err( &format!("an empty renaming target was specified for library `{}`",name)); @@ -212,7 +212,7 @@ impl<'a, 'tcx> Collector<'a, 'tcx> { // can move them to the end of the list below. let mut existing = self.libs.drain_filter(|lib| { if let Some(lib_name) = lib.name { - if lib_name == name as &str { + if lib_name.as_str() == *name { if let Some(k) = kind { lib.kind = k; } diff --git a/src/librustc_plugin/registry.rs b/src/librustc_plugin/registry.rs index 913657b2934e4..c2d1d5fa65af2 100644 --- a/src/librustc_plugin/registry.rs +++ b/src/librustc_plugin/registry.rs @@ -7,7 +7,7 @@ use rustc::util::nodemap::FxHashMap; use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT, IdentTT}; use syntax::ext::base::MacroExpanderFn; use syntax::ext::hygiene; -use syntax::symbol::Symbol; +use syntax::symbol::{Symbol, sym}; use syntax::ast; use syntax::feature_gate::AttributeType; use syntax_pos::Span; @@ -86,7 +86,7 @@ impl<'a> Registry<'a> { /// /// This is the most general hook into `libsyntax`'s expansion behavior. pub fn register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxExtension) { - if name == "macro_rules" { + if name == sym::macro_rules { panic!("user-defined macros may not be named `macro_rules`"); } self.syntax_exts.push((name, match extension { diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index cf09e31bb6282..f70ca6f859b98 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -369,7 +369,7 @@ impl<'a> Resolver<'a> { }; self.populate_module_if_necessary(module); - if injected_crate_name().map_or(false, |name| ident.name == name) { + if injected_crate_name().map_or(false, |name| ident.name.as_str() == name) { self.injected_crate = Some(module); } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 0dd6f378730f9..678f4c23d3e9e 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1812,8 +1812,8 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> { fn resolve_str_path( &mut self, span: Span, - crate_root: Option<&str>, - components: &[&str], + crate_root: Option, + components: &[Symbol], is_value: bool ) -> hir::Path { let root = if crate_root.is_some() { @@ -1825,7 +1825,7 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> { .chain( crate_root.into_iter() .chain(components.iter().cloned()) - .map(Ident::from_str) + .map(Ident::with_empty_ctxt) ).map(|i| self.new_ast_path_segment(i)).collect::>(); diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 62f2768888ad7..9f3e1c308f637 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -982,7 +982,7 @@ impl<'a> Resolver<'a> { let msg = format!("cannot find {} `{}{}` in this scope", kind.descr(), ident, bang); let mut err = self.session.struct_span_err(ident.span, &msg); - self.suggest_macro_name(&ident.as_str(), kind, &mut err, ident.span); + self.suggest_macro_name(ident.name, kind, &mut err, ident.span); err.emit(); } } @@ -1010,11 +1010,12 @@ impl<'a> Resolver<'a> { } } - fn suggest_macro_name(&mut self, name: &str, kind: MacroKind, + fn suggest_macro_name(&mut self, name: Symbol, kind: MacroKind, err: &mut DiagnosticBuilder<'a>, span: Span) { // First check if this is a locally-defined bang macro. let suggestion = if let MacroKind::Bang = kind { - find_best_match_for_name(self.macro_names.iter().map(|ident| &ident.name), name, None) + find_best_match_for_name( + self.macro_names.iter().map(|ident| &ident.name), &name.as_str(), None) } else { None // Then check global macros. @@ -1023,7 +1024,7 @@ impl<'a> Resolver<'a> { .filter_map(|(name, binding)| { if binding.macro_kind() == Some(kind) { Some(name) } else { None } }); - find_best_match_for_name(names, name, None) + find_best_match_for_name(names, &name.as_str(), None) // Then check modules. }).or_else(|| { let is_macro = |res| { @@ -1033,7 +1034,7 @@ impl<'a> Resolver<'a> { false } }; - let ident = Ident::new(Symbol::intern(name), span); + let ident = Ident::new(name, span); self.lookup_typo_candidate(&[Segment::from_ident(ident)], MacroNS, is_macro, span) .map(|suggestion| suggestion.candidate) }); @@ -1092,7 +1093,7 @@ impl<'a> Resolver<'a> { current_legacy_scope: &mut LegacyScope<'a>) { self.local_macro_def_scopes.insert(item.id, self.current_module); let ident = item.ident; - if ident.name == "macro_rules" { + if ident.name == sym::macro_rules { self.session.span_err(item.span, "user-defined macros may not be named `macro_rules`"); } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 9e6b8d035458d..4058f0bce0f95 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -29,7 +29,7 @@ use rustc::{bug, span_bug}; use syntax::ast::{self, Ident, Name, NodeId, CRATE_NODE_ID}; use syntax::ext::base::Determinacy::{self, Determined, Undetermined}; use syntax::ext::hygiene::Mark; -use syntax::symbol::keywords; +use syntax::symbol::{keywords, sym}; use syntax::util::lev_distance::find_best_match_for_name; use syntax::{struct_span_err, unwrap_or}; use syntax_pos::{MultiSpan, Span}; @@ -496,7 +496,8 @@ impl<'a> Resolver<'a> { // Reserve some names that are not quite covered by the general check // performed on `Resolver::builtin_attrs`. if ns == MacroNS && - (ident.name == "cfg" || ident.name == "cfg_attr" || ident.name == "derive") { + (ident.name == sym::cfg || ident.name == sym::cfg_attr || + ident.name == sym::derive) { self.session.span_err(ident.span, &format!("name `{}` is reserved in macro namespace", ident)); } @@ -706,7 +707,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { has_errors = true; if let SingleImport { source, ref source_bindings, .. } = import.subclass { - if source.name == "self" { + if source.name == keywords::SelfLower.name() { // Silence `unresolved import` error if E0429 is already emitted if let Err(Determined) = source_bindings.value_ns.get() { continue; @@ -1041,7 +1042,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { let initial_res = source_bindings[ns].get().map(|initial_binding| { all_ns_err = false; if let Some(target_binding) = target_bindings[ns].get() { - if target.name == "_" && + // Note that as_str() de-gensyms the Symbol + if target.name.as_str() == "_" && initial_binding.is_extern_crate() && !initial_binding.is_import() { this.record_use(ident, ns, target_binding, directive.module_path.is_empty()); @@ -1392,7 +1394,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { // (e.g. implicitly injected `std`) cannot be properly encoded in metadata, // so they can cause name conflict errors downstream. let is_good_import = binding.is_import() && !binding.is_ambiguity() && - !(ident.name.is_gensymed() && ident.name != "_"); + // Note that as_str() de-gensyms the Symbol + !(ident.name.is_gensymed() && ident.name.as_str() != "_"); if is_good_import || binding.is_macro_def() { let res = binding.res(); if res != Res::Err { diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index cb2454aa4b56e..e03da2ed608be 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -1197,7 +1197,7 @@ fn null_id() -> rls_data::Id { fn lower_attributes(attrs: Vec, scx: &SaveContext<'_, '_>) -> Vec { attrs.into_iter() // Only retain real attributes. Doc comments are lowered separately. - .filter(|attr| attr.path != "doc") + .filter(|attr| attr.path != sym::doc) .map(|mut attr| { // Remove the surrounding '#[..]' or '#![..]' of the pretty printed // attribute. First normalize all inner attribute (#![..]) to outer diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a184a2daeb6ad..362b6f0504d99 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4197,7 +4197,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // ... except when we try to 'break rust;'. // ICE this expression in particular (see #43162). if let ExprKind::Path(QPath::Resolved(_, ref path)) = e.node { - if path.segments.len() == 1 && path.segments[0].ident.name == "rust" { + if path.segments.len() == 1 && + path.segments[0].ident.name == sym::rust { fatally_break_rust(self.tcx.sess); } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 29b4708940955..ffba9403743a3 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -2594,7 +2594,7 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen } codegen_fn_attrs.inline = attrs.iter().fold(InlineAttr::None, |ia, attr| { - if attr.path != "inline" { + if attr.path != sym::inline { return ia; } match attr.meta().map(|i| i.node) { @@ -2634,7 +2634,7 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen }); codegen_fn_attrs.optimize = attrs.iter().fold(OptimizeAttr::None, |ia, attr| { - if attr.path != "optimize" { + if attr.path != sym::optimize { return ia; } let err = |sp, s| span_err!(tcx.sess.diagnostic(), sp, E0722, "{}", s); diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index b96ac19c1ea61..c795b2dcd7a43 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -7,7 +7,7 @@ use std::mem; use std::fmt::{self, Write}; use std::ops; -use syntax::symbol::Symbol; +use syntax::symbol::{Symbol, sym}; use syntax::ast::{MetaItem, MetaItemKind, NestedMetaItem, LitKind}; use syntax::parse::ParseSess; use syntax::feature_gate::Features; @@ -186,7 +186,7 @@ impl Cfg { fn should_use_with_in_description(&self) -> bool { match *self { - Cfg::Cfg(ref name, _) if name == &"target_feature" => true, + Cfg::Cfg(name, _) if name == sym::target_feature => true, _ => false, } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 6790b13dbf8d5..f9a43ccfbace1 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4383,7 +4383,7 @@ where // Start of code copied from rust-clippy -pub fn path_to_def_local(tcx: TyCtxt<'_, '_, '_>, path: &[&str]) -> Option { +pub fn path_to_def_local(tcx: TyCtxt<'_, '_, '_>, path: &[Symbol]) -> Option { let krate = tcx.hir().krate(); let mut items = krate.module.item_ids.clone(); let mut path_it = path.iter().peekable(); @@ -4408,7 +4408,7 @@ pub fn path_to_def_local(tcx: TyCtxt<'_, '_, '_>, path: &[&str]) -> Option, path: &[&str]) -> Option { +pub fn path_to_def(tcx: TyCtxt<'_, '_, '_>, path: &[Symbol]) -> Option { let crates = tcx.crates(); let krate = crates diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 1b099fbd91d1e..bc87086e1061a 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -368,9 +368,9 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt }; let send_trait = if crate_name == Some("core".to_string()) { - clean::path_to_def_local(tcx, &["marker", "Send"]) + clean::path_to_def_local(tcx, &[sym::marker, sym::Send]) } else { - clean::path_to_def(tcx, &["core", "marker", "Send"]) + clean::path_to_def(tcx, &[sym::core, sym::marker, sym::Send]) }; let mut renderinfo = RenderInfo::default(); diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index abf19a0a5efa4..9e108e605c8bb 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -99,7 +99,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { // Try looking for methods and associated items. let mut split = path_str.rsplitn(2, "::"); let item_name = if let Some(first) = split.next() { - first + Symbol::intern(first) } else { return Err(()) }; diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index aa176c8925883..d12240655e628 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -81,12 +81,6 @@ impl PartialEq for Path { } } -impl<'a> PartialEq<&'a str> for Path { - fn eq(&self, string: &&'a str) -> bool { - self.segments.len() == 1 && self.segments[0].ident.name == *string - } -} - impl fmt::Debug for Path { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "path({})", pprust::path_to_string(self)) diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs index a8310c48b9627..43de3f74e4a2e 100644 --- a/src/libsyntax/attr/builtin.rs +++ b/src/libsyntax/attr/builtin.rs @@ -185,12 +185,12 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, 'outer: for attr in attrs_iter { if ![ - "rustc_deprecated", - "rustc_const_unstable", - "unstable", - "stable", - "rustc_promotable", - "rustc_allow_const_fn_ptr", + sym::rustc_deprecated, + sym::rustc_const_unstable, + sym::unstable, + sym::stable, + sym::rustc_promotable, + sym::rustc_allow_const_fn_ptr, ].iter().any(|&s| attr.path == s) { continue // not a stability level } @@ -199,10 +199,10 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, let meta = attr.meta(); - if attr.path == "rustc_promotable" { + if attr.path == sym::rustc_promotable { promotable = true; } - if attr.path == "rustc_allow_const_fn_ptr" { + if attr.path == sym::rustc_allow_const_fn_ptr { allow_const_fn_ptr = true; } // attributes with data @@ -721,7 +721,7 @@ pub fn find_repr_attrs(sess: &ParseSess, attr: &Attribute) -> Vec { let mut acc = Vec::new(); let diagnostic = &sess.span_diagnostic; - if attr.path == "repr" { + if attr.path == sym::repr { if let Some(items) = attr.meta_item_list() { mark_used(attr); for item in items { @@ -770,14 +770,14 @@ pub fn find_repr_attrs(sess: &ParseSess, attr: &Attribute) -> Vec { }; let mut literal_error = None; - if name == "align" { + if name == sym::align { recognised = true; match parse_alignment(&value.node) { Ok(literal) => acc.push(ReprAlign(literal)), Err(message) => literal_error = Some(message) }; } - else if name == "packed" { + else if name == sym::packed { recognised = true; match parse_alignment(&value.node) { Ok(literal) => acc.push(ReprPacked(literal)), diff --git a/src/libsyntax/entry.rs b/src/libsyntax/entry.rs index 267f863ce35e4..0b6cf30bd27d2 100644 --- a/src/libsyntax/entry.rs +++ b/src/libsyntax/entry.rs @@ -19,7 +19,7 @@ pub fn entry_point_type(item: &Item, depth: usize) -> EntryPointType { EntryPointType::Start } else if attr::contains_name(&item.attrs, sym::main) { EntryPointType::MainAttr - } else if item.ident.name == "main" { + } else if item.ident.name == sym::main { if depth == 1 { // This is a top-level function so can be 'main' EntryPointType::MainNamed diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index cc19acb61adc2..0a88d2f8824d3 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -10,7 +10,7 @@ use crate::mut_visit::{self, MutVisitor}; use crate::parse::{self, parser, DirectoryOwnership}; use crate::parse::token; use crate::ptr::P; -use crate::symbol::{keywords, Ident, Symbol}; +use crate::symbol::{keywords, Ident, Symbol, sym}; use crate::ThinVec; use crate::tokenstream::{self, TokenStream}; @@ -871,7 +871,7 @@ impl<'a> ExtCtxt<'a> { let mut last_macro = None; loop { if ctxt.outer().expn_info().map_or(None, |info| { - if info.format.name() == "include" { + if info.format.name() == sym::include { // Stop going up the backtrace once include! is encountered return None; } diff --git a/src/libsyntax/ext/derive.rs b/src/libsyntax/ext/derive.rs index 6df369133d01d..a24e09f127eae 100644 --- a/src/libsyntax/ext/derive.rs +++ b/src/libsyntax/ext/derive.rs @@ -4,7 +4,7 @@ use crate::source_map::{hygiene, ExpnInfo, ExpnFormat}; use crate::ext::base::ExtCtxt; use crate::ext::build::AstBuilder; use crate::parse::parser::PathStyle; -use crate::symbol::Symbol; +use crate::symbol::{Symbol, sym}; use syntax_pos::Span; @@ -13,7 +13,7 @@ use rustc_data_structures::fx::FxHashSet; pub fn collect_derives(cx: &mut ExtCtxt<'_>, attrs: &mut Vec) -> Vec { let mut result = Vec::new(); attrs.retain(|attr| { - if attr.path != "derive" { + if attr.path != sym::derive { return true; } if !attr.is_meta_item_list() { diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 7ebfcfd176adb..a286fd83e3c20 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -376,7 +376,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } let mut item = self.fully_configure(item); - item.visit_attrs(|attrs| attrs.retain(|a| a.path != "derive")); + item.visit_attrs(|attrs| attrs.retain(|a| a.path != sym::derive)); let mut item_with_markers = item.clone(); add_derived_markers(&mut self.cx, item.span(), &traits, &mut item_with_markers); let derives = derives.entry(invoc.expansion_data.mark).or_default(); @@ -1109,7 +1109,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { -> Option { let attr = attrs.iter() .position(|a| { - if a.path == "derive" { + if a.path == sym::derive { *after_derive = true; } !attr::is_known(a) && !is_builtin_attr(a) @@ -1117,7 +1117,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { .map(|i| attrs.remove(i)); if let Some(attr) = &attr { if !self.cx.ecfg.enable_custom_inner_attributes() && - attr.style == ast::AttrStyle::Inner && attr.path != "test" { + attr.style == ast::AttrStyle::Inner && attr.path != sym::test { emit_feature_err(&self.cx.parse_sess, sym::custom_inner_attributes, attr.span, GateIssue::Language, "non-builtin inner attributes are unstable"); @@ -1167,7 +1167,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { self.check_attribute_inner(attr, features); // macros are expanded before any lint passes so this warning has to be hardcoded - if attr.path == "derive" { + if attr.path == sym::derive { self.cx.struct_span_warn(attr.span, "`#[derive]` does nothing on macro invocations") .note("this may become a hard error in a future release") .emit(); diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 5559621009369..06651750de741 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -13,7 +13,7 @@ use crate::parse::{Directory, ParseSess}; use crate::parse::parser::Parser; use crate::parse::token::{self, NtTT}; use crate::parse::token::Token::*; -use crate::symbol::{Symbol, sym}; +use crate::symbol::{Symbol, keywords, sym}; use crate::tokenstream::{DelimSpan, TokenStream, TokenTree}; use errors::FatalError; @@ -467,7 +467,7 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[quoted::TokenTree]) -> bool { TokenTree::Sequence(span, ref seq) => { if seq.separator.is_none() && seq.tts.iter().all(|seq_tt| { match *seq_tt { - TokenTree::MetaVarDecl(_, _, id) => id.name == "vis", + TokenTree::MetaVarDecl(_, _, id) => id.name == sym::vis, TokenTree::Sequence(_, ref sub_seq) => sub_seq.op == quoted::KleeneOp::ZeroOrMore || sub_seq.op == quoted::KleeneOp::ZeroOrOne, @@ -1046,7 +1046,8 @@ fn is_in_follow(tok: "ed::TokenTree, frag: &str) -> IsInFollow { match *tok { TokenTree::Token(_, ref tok) => match *tok { FatArrow | Comma | Eq | BinOp(token::Or) => IsInFollow::Yes, - Ident(i, false) if i.name == "if" || i.name == "in" => IsInFollow::Yes, + Ident(i, false) if i.name == keywords::If.name() || + i.name == keywords::In.name() => IsInFollow::Yes, _ => IsInFollow::No(tokens), }, _ => IsInFollow::No(tokens), @@ -1063,10 +1064,12 @@ fn is_in_follow(tok: "ed::TokenTree, frag: &str) -> IsInFollow { OpenDelim(token::DelimToken::Bracket) | Comma | FatArrow | Colon | Eq | Gt | BinOp(token::Shr) | Semi | BinOp(token::Or) => IsInFollow::Yes, - Ident(i, false) if i.name == "as" || i.name == "where" => IsInFollow::Yes, + Ident(i, false) if i.name == keywords::As.name() || + i.name == keywords::Where.name() => IsInFollow::Yes, _ => IsInFollow::No(tokens), }, - TokenTree::MetaVarDecl(_, _, frag) if frag.name == "block" => IsInFollow::Yes, + TokenTree::MetaVarDecl(_, _, frag) if frag.name == sym::block => + IsInFollow::Yes, _ => IsInFollow::No(tokens), } }, @@ -1089,16 +1092,18 @@ fn is_in_follow(tok: "ed::TokenTree, frag: &str) -> IsInFollow { match *tok { TokenTree::Token(_, ref tok) => match *tok { Comma => IsInFollow::Yes, - Ident(i, is_raw) if is_raw || i.name != "priv" => IsInFollow::Yes, + Ident(i, is_raw) if is_raw || i.name != keywords::Priv.name() => + IsInFollow::Yes, ref tok => if tok.can_begin_type() { IsInFollow::Yes } else { IsInFollow::No(tokens) } }, - TokenTree::MetaVarDecl(_, _, frag) if frag.name == "ident" - || frag.name == "ty" - || frag.name == "path" => IsInFollow::Yes, + TokenTree::MetaVarDecl(_, _, frag) if frag.name == sym::ident + || frag.name == sym::ty + || frag.name == sym::path => + IsInFollow::Yes, _ => IsInFollow::No(tokens), } }, diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 53ecb0762ab44..e7740f1835bc5 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -22,13 +22,13 @@ use crate::source_map::Spanned; use crate::edition::{ALL_EDITIONS, Edition}; use crate::visit::{self, FnKind, Visitor}; use crate::parse::{token, ParseSess}; -use crate::symbol::Symbol; +use crate::symbol::{Symbol, keywords, sym}; use crate::tokenstream::TokenTree; use errors::{DiagnosticBuilder, Handler}; use rustc_data_structures::fx::FxHashMap; use rustc_target::spec::abi::Abi; -use syntax_pos::{Span, DUMMY_SP, sym}; +use syntax_pos::{Span, DUMMY_SP}; use log::debug; use lazy_static::lazy_static; @@ -562,9 +562,9 @@ declare_features! ( // Some features are known to be incomplete and using them is likely to have // unanticipated results, such as compiler crashes. We warn the user about these // to alert them. -const INCOMPLETE_FEATURES: &[&str] = &[ - "generic_associated_types", - "const_generics" +const INCOMPLETE_FEATURES: &[Symbol] = &[ + sym::generic_associated_types, + sym::const_generics ]; declare_features! ( @@ -1947,7 +1947,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_item(&mut self, i: &'a ast::Item) { match i.node { ast::ItemKind::Const(_,_) => { - if i.ident.name == "_" { + if i.ident.name == keywords::Underscore.name() { gate_feature_post!(&self, underscore_const_names, i.span, "naming constants with `_` is unstable"); } @@ -2304,7 +2304,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], if edition <= crate_edition { // The `crate_edition` implies its respective umbrella feature-gate // (i.e., `#![feature(rust_20XX_preview)]` isn't needed on edition 20XX). - edition_enabled_features.insert(Symbol::intern(edition.feature_name()), edition); + edition_enabled_features.insert(edition.feature_name(), edition); } } @@ -2335,7 +2335,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], } let name = mi.name_or_empty(); - if INCOMPLETE_FEATURES.iter().any(|f| name == *f) { + if INCOMPLETE_FEATURES.iter().any(|f| name == f.as_str()) { span_handler.struct_span_warn( mi.span(), &format!( @@ -2345,7 +2345,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], ).emit(); } - if let Some(edition) = ALL_EDITIONS.iter().find(|e| name == e.feature_name()) { + if let Some(edition) = ALL_EDITIONS.iter().find(|e| name == e.feature_name().as_str()) { if *edition <= crate_edition { continue; } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 64f3704e8083f..655baafcd2d5d 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -391,6 +391,8 @@ mod tests { #[test] fn string_to_tts_macro () { with_globals(|| { + use crate::symbol::sym; + let tts: Vec<_> = string_to_stream("macro_rules! zip (($a)=>($a))".to_string()).trees().collect(); let tts: &[TokenTree] = &tts[..]; @@ -403,8 +405,8 @@ mod tests { Some(&TokenTree::Token(_, token::Ident(name_zip, false))), Some(&TokenTree::Delimited(_, macro_delim, ref macro_tts)), ) - if name_macro_rules.name == "macro_rules" - && name_zip.name == "zip" => { + if name_macro_rules.name == sym::macro_rules + && name_zip.name.as_str() == "zip" => { let tts = ¯o_tts.trees().collect::>(); match (tts.len(), tts.get(0), tts.get(1), tts.get(2)) { ( @@ -421,7 +423,7 @@ mod tests { Some(&TokenTree::Token(_, token::Dollar)), Some(&TokenTree::Token(_, token::Ident(ident, false))), ) - if first_delim == token::Paren && ident.name == "a" => {}, + if first_delim == token::Paren && ident.name.as_str() == "a" => {}, _ => panic!("value 3: {:?} {:?}", first_delim, first_tts), } let tts = &second_tts.trees().collect::>(); @@ -431,7 +433,7 @@ mod tests { Some(&TokenTree::Token(_, token::Dollar)), Some(&TokenTree::Token(_, token::Ident(ident, false))), ) - if second_delim == token::Paren && ident.name == "a" => {}, + if second_delim == token::Paren && ident.name.as_str() == "a" => {}, _ => panic!("value 4: {:?} {:?}", second_delim, second_tts), } }, @@ -584,13 +586,13 @@ mod tests { let item = parse_item_from_source_str(name_1, source, &sess) .unwrap().unwrap(); let doc = first_attr_value_str_by_name(&item.attrs, sym::doc).unwrap(); - assert_eq!(doc, "/// doc comment"); + assert_eq!(doc.as_str(), "/// doc comment"); let name_2 = FileName::Custom("crlf_source_2".to_string()); let source = "/// doc comment\r\n/// line 2\r\nfn foo() {}".to_string(); let item = parse_item_from_source_str(name_2, source, &sess) .unwrap().unwrap(); - let docs = item.attrs.iter().filter(|a| a.path == "doc") + let docs = item.attrs.iter().filter(|a| a.path == sym::doc) .map(|a| a.value_str().unwrap().to_string()).collect::>(); let b: &[_] = &["/// doc comment".to_string(), "/// line 2".to_string()]; assert_eq!(&docs[..], b); @@ -599,7 +601,7 @@ mod tests { let source = "/** doc comment\r\n * with CRLF */\r\nfn foo() {}".to_string(); let item = parse_item_from_source_str(name_3, source, &sess).unwrap().unwrap(); let doc = first_attr_value_str_by_name(&item.attrs, sym::doc).unwrap(); - assert_eq!(doc, "/** doc comment\n * with CRLF */"); + assert_eq!(doc.as_str(), "/** doc comment\n * with CRLF */"); }); } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d3dd6bb1e01a9..c0f3c358e98f5 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5099,7 +5099,7 @@ impl<'a> Parser<'a> { (ident, ast::MacroDef { tokens: tokens.into(), legacy: false }) } - token::Ident(ident, _) if ident.name == "macro_rules" && + token::Ident(ident, _) if ident.name == sym::macro_rules && self.look_ahead(1, |t| *t == token::Not) => { let prev_span = self.prev_span; self.complain_if_pub_macro(&vis.node, prev_span); diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index 42ca8b7c23cb0..f08fdcc6fb53c 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -35,6 +35,9 @@ pub fn injected_crate_name() -> Option<&'static str> { } thread_local! { + // A `Symbol` might make more sense here, but it doesn't work, probably for + // reasons relating to the use of thread-local storage for the Symbol + // interner. static INJECTED_CRATE_NAME: Cell> = Cell::new(None); } diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 8e5e594ce9aa5..21bc236d00e6b 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -272,7 +272,8 @@ fn generate_test_harness(sess: &ParseSess, test_cases: Vec::new(), reexport_test_harness_main, // N.B., doesn't consider the value of `--crate-name` passed on the command line. - is_libtest: attr::find_crate_name(&krate.attrs).map(|s| s == "test").unwrap_or(false), + is_libtest: attr::find_crate_name(&krate.attrs) + .map(|s| s == sym::test).unwrap_or(false), toplevel_reexport: None, ctxt: SyntaxContext::empty().apply_mark(mark), features, diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs index 6213736ed5f46..b8e89c3ecf876 100644 --- a/src/libsyntax_ext/asm.rs +++ b/src/libsyntax_ext/asm.rs @@ -39,7 +39,7 @@ impl State { } } -const OPTIONS: &[&str] = &["volatile", "alignstack", "intel"]; +const OPTIONS: &[Symbol] = &[sym::volatile, sym::alignstack, sym::intel]; pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, @@ -233,13 +233,13 @@ fn parse_inline_asm<'a>( Options => { let (option, _) = p.parse_str()?; - if option == "volatile" { + if option == sym::volatile { // Indicates that the inline assembly has side effects // and must not be optimized out along with its outputs. volatile = true; - } else if option == "alignstack" { + } else if option == sym::alignstack { alignstack = true; - } else if option == "intel" { + } else if option == sym::intel { dialect = AsmDialect::Intel; } else { cx.span_warn(p.prev_span, "unrecognized option"); diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index fff54814a38c4..c27de692d887c 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -6,7 +6,7 @@ use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension, Resolver}; use syntax::ext::build::AstBuilder; use syntax::ext::hygiene::{Mark, SyntaxContext}; use syntax::ptr::P; -use syntax::symbol::Symbol; +use syntax::symbol::{Symbol, sym}; use syntax_pos::Span; macro path_local($x:ident) { @@ -139,7 +139,7 @@ fn call_intrinsic(cx: &ExtCtxt<'_>, let intrinsic_allowed_via_allow_internal_unstable = cx .current_expansion.mark.expn_info().unwrap() .allow_internal_unstable.map_or(false, |features| features.iter().any(|&s| - s == "core_intrinsics" + s == sym::core_intrinsics )); if intrinsic_allowed_via_allow_internal_unstable { span = span.with_ctxt(cx.backtrace()); diff --git a/src/libsyntax_pos/edition.rs b/src/libsyntax_pos/edition.rs index a0b0052f26dab..00cd00f283784 100644 --- a/src/libsyntax_pos/edition.rs +++ b/src/libsyntax_pos/edition.rs @@ -1,3 +1,4 @@ +use crate::symbol::{Symbol, sym}; use std::fmt; use std::str::FromStr; @@ -44,10 +45,10 @@ impl Edition { } } - pub fn feature_name(&self) -> &'static str { + pub fn feature_name(&self) -> Symbol { match *self { - Edition::Edition2015 => "rust_2015_preview", - Edition::Edition2018 => "rust_2018_preview", + Edition::Edition2015 => sym::rust_2015_preview, + Edition::Edition2018 => sym::rust_2018_preview, } } diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index c5d6da74eb618..39859f25f97fb 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -393,7 +393,7 @@ impl Span { Some(info) => info .allow_internal_unstable .map_or(false, |features| features.iter().any(|&f| - f == feature || f == "allow_internal_unstable_backcompat_hack" + f == feature || f == sym::allow_internal_unstable_backcompat_hack )), None => false, } diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index ac3f999c53794..ec0ce4253fa2d 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -822,12 +822,6 @@ impl Decodable for Symbol { } } -impl> PartialEq for Symbol { - fn eq(&self, other: &T) -> bool { - self.as_str() == other.deref() - } -} - // The `&'static str`s in this type actually point into the arena. // // Note that normal symbols are indexed upward from 0, and gensyms are indexed diff --git a/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs index 1d204e7bfcffa..0deb1bf091508 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs @@ -20,7 +20,7 @@ declare_lint_pass!(Pass => [TEST_LINT]); impl EarlyLintPass for Pass { fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) { - if it.ident.name == "lintme" { + if it.ident.name.as_str() == "lintme" { cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'"); } } diff --git a/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs b/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs index 182d2899da185..64664377cd943 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs @@ -23,10 +23,10 @@ declare_lint_pass!(Pass => [TEST_LINT, TEST_GROUP]); impl EarlyLintPass for Pass { fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) { - if it.ident.name == "lintme" { + if it.ident.name.as_str() == "lintme" { cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'"); } - if it.ident.name == "lintmetoo" { + if it.ident.name.as_str() == "lintmetoo" { cx.span_lint(TEST_GROUP, it.span, "item is named 'lintmetoo'"); } } From ea9fac5687c24abad493caf4ec5042af47458af9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 8 May 2019 14:33:06 +1000 Subject: [PATCH 208/212] Return a `Symbol` from `name_or_empty` functions. --- src/librustc/hir/check_attr.rs | 18 ++--- src/librustc/lint/levels.rs | 2 +- src/librustc/lint/mod.rs | 15 ++++- src/librustc/middle/lib_features.rs | 6 +- src/librustc/middle/stability.rs | 2 +- src/librustc_lint/unused.rs | 2 +- src/librustc_metadata/creader.rs | 3 +- src/librustc_passes/layout_test.rs | 10 +-- src/librustc_plugin/load.rs | 10 +-- src/librustdoc/core.rs | 10 +-- src/librustdoc/html/render.rs | 34 +++++----- src/libsyntax/attr/builtin.rs | 81 +++++++++++------------ src/libsyntax/attr/mod.rs | 14 ++-- src/libsyntax/feature_gate.rs | 6 +- src/libsyntax_ext/deriving/generic/mod.rs | 4 +- 15 files changed, 112 insertions(+), 105 deletions(-) diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index 23c8a671ec5b3..b199eee6dad87 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -178,9 +178,9 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { let mut is_transparent = false; for hint in &hints { - let (article, allowed_targets) = match hint.name_or_empty().get() { - name @ "C" | name @ "align" => { - is_c |= name == "C"; + let (article, allowed_targets) = match hint.name_or_empty() { + name @ sym::C | name @ sym::align => { + is_c |= name == sym::C; if target != Target::Struct && target != Target::Union && target != Target::Enum { @@ -189,7 +189,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { continue } } - "packed" => { + sym::packed => { if target != Target::Struct && target != Target::Union { ("a", "struct or union") @@ -197,7 +197,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { continue } } - "simd" => { + sym::simd => { is_simd = true; if target != Target::Struct { ("a", "struct") @@ -205,7 +205,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { continue } } - "transparent" => { + sym::transparent => { is_transparent = true; if target != Target::Struct { ("a", "struct") @@ -213,9 +213,9 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { continue } } - "i8" | "u8" | "i16" | "u16" | - "i32" | "u32" | "i64" | "u64" | - "isize" | "usize" => { + sym::i8 | sym::u8 | sym::i16 | sym::u16 | + sym::i32 | sym::u32 | sym::i64 | sym::u64 | + sym::isize | sym::usize => { int_reprs += 1; if target != Target::Enum { ("an", "enum") diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index 6481f9af00b86..9c926dff325bf 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -194,7 +194,7 @@ impl<'a> LintLevelsBuilder<'a> { struct_span_err!(sess, span, E0452, "malformed lint attribute") }; for attr in attrs { - let level = match Level::from_str(&attr.name_or_empty()) { + let level = match Level::from_symbol(attr.name_or_empty()) { None => continue, Some(lvl) => lvl, }; diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 6613440ee7c9e..68b65f9b4a1cc 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -38,7 +38,7 @@ use syntax::ast; use syntax::source_map::{MultiSpan, ExpnFormat}; use syntax::early_buffered_lints::BufferedEarlyLintId; use syntax::edition::Edition; -use syntax::symbol::Symbol; +use syntax::symbol::{Symbol, sym}; use syntax_pos::Span; pub use crate::lint::context::{LateContext, EarlyContext, LintContext, LintStore, @@ -570,6 +570,17 @@ impl Level { _ => None, } } + + /// Converts a symbol to a level. + pub fn from_symbol(x: Symbol) -> Option { + match x { + sym::allow => Some(Allow), + sym::warn => Some(Warn), + sym::deny => Some(Deny), + sym::forbid => Some(Forbid), + _ => None, + } + } } /// How a lint level was set. @@ -752,7 +763,7 @@ pub fn struct_lint_level<'a>(sess: &'a Session, pub fn maybe_lint_level_root(tcx: TyCtxt<'_, '_, '_>, id: hir::HirId) -> bool { let attrs = tcx.hir().attrs_by_hir_id(id); - attrs.iter().any(|attr| Level::from_str(&attr.name_or_empty()).is_some()) + attrs.iter().any(|attr| Level::from_symbol(attr.name_or_empty()).is_some()) } fn lint_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cnum: CrateNum) diff --git a/src/librustc/middle/lib_features.rs b/src/librustc/middle/lib_features.rs index 8696e2af8c2bc..76934ddd69b1b 100644 --- a/src/librustc/middle/lib_features.rs +++ b/src/librustc/middle/lib_features.rs @@ -65,9 +65,9 @@ impl<'a, 'tcx> LibFeatureCollector<'a, 'tcx> { for meta in metas { if let Some(mi) = meta.meta_item() { // Find the `feature = ".."` meta-item. - match (mi.name_or_empty().get(), mi.value_str()) { - ("feature", val) => feature = val, - ("since", val) => since = val, + match (mi.name_or_empty(), mi.value_str()) { + (sym::feature, val) => feature = val, + (sym::since, val) => since = val, _ => {} } } diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index d9a44714d7d08..abcf164cda6d4 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -195,7 +195,7 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> { // Emit errors for non-staged-api crates. for attr in attrs { let name = attr.name_or_empty(); - if ["unstable", "stable", "rustc_deprecated"].contains(&name.get()) { + if [sym::unstable, sym::stable, sym::rustc_deprecated].contains(&name) { attr::mark_used(attr); self.tcx.sess.span_err(attr.span, "stability attributes may not be used \ outside of the standard library"); diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 93af7a1cd8f28..c3dfd44ad8572 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -262,7 +262,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes { // Has a plugin registered this attribute as one that must be used at // the crate level? let plugin_crate = plugin_attributes.iter() - .find(|&&(ref x, t)| name == x.as_str() && AttributeType::CrateLevel == t) + .find(|&&(x, t)| name == x && AttributeType::CrateLevel == t) .is_some(); if known_crate || plugin_crate { let msg = match attr.style { diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index b7b17a84aa768..7f2a1c0b4b1d1 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -650,9 +650,8 @@ impl<'a> CrateLoader<'a> { /// SVH and DefIndex of the registrar function. pub fn find_plugin_registrar(&mut self, span: Span, - name: &str) + name: Symbol) -> Option<(PathBuf, CrateDisambiguator)> { - let name = Symbol::intern(name); let ekrate = self.read_extension_crate(span, name, name); if ekrate.target_only { diff --git a/src/librustc_passes/layout_test.rs b/src/librustc_passes/layout_test.rs index c865845b5e367..dea5774aa6eb7 100644 --- a/src/librustc_passes/layout_test.rs +++ b/src/librustc_passes/layout_test.rs @@ -55,26 +55,26 @@ impl<'a, 'tcx> VarianceTest<'a, 'tcx> { // The `..` are the names of fields to dump. let meta_items = attr.meta_item_list().unwrap_or_default(); for meta_item in meta_items { - match meta_item.name_or_empty().get() { - "abi" => { + match meta_item.name_or_empty() { + sym::abi => { self.tcx .sess .span_err(item.span, &format!("abi: {:?}", ty_layout.abi)); } - "align" => { + sym::align => { self.tcx .sess .span_err(item.span, &format!("align: {:?}", ty_layout.align)); } - "size" => { + sym::size => { self.tcx .sess .span_err(item.span, &format!("size: {:?}", ty_layout.size)); } - "homogeneous_aggregate" => { + sym::homogeneous_aggregate => { self.tcx.sess.span_err( item.span, &format!( diff --git a/src/librustc_plugin/load.rs b/src/librustc_plugin/load.rs index 43eddbb653fee..680bdcc4bbe97 100644 --- a/src/librustc_plugin/load.rs +++ b/src/librustc_plugin/load.rs @@ -11,7 +11,7 @@ use std::mem; use std::path::PathBuf; use syntax::ast; use syntax::span_err; -use syntax::symbol::sym; +use syntax::symbol::{Symbol, keywords, sym}; use syntax_pos::{Span, DUMMY_SP}; /// Pointer to a registrar function. @@ -58,9 +58,9 @@ pub fn load_plugins(sess: &Session, for plugin in plugins { // plugins must have a name and can't be key = value let name = plugin.name_or_empty(); - if !name.is_empty() && !plugin.is_value_str() { + if name != keywords::Invalid.name() && !plugin.is_value_str() { let args = plugin.meta_item_list().map(ToOwned::to_owned); - loader.load_plugin(plugin.span(), &name, args.unwrap_or_default()); + loader.load_plugin(plugin.span(), name, args.unwrap_or_default()); } else { call_malformed_plugin_attribute(sess, attr.span); } @@ -70,7 +70,7 @@ pub fn load_plugins(sess: &Session, if let Some(plugins) = addl_plugins { for plugin in plugins { - loader.load_plugin(DUMMY_SP, &plugin, vec![]); + loader.load_plugin(DUMMY_SP, Symbol::intern(&plugin), vec![]); } } @@ -86,7 +86,7 @@ impl<'a> PluginLoader<'a> { } } - fn load_plugin(&mut self, span: Span, name: &str, args: Vec) { + fn load_plugin(&mut self, span: Span, name: Symbol, args: Vec) { let registrar = self.reader.find_plugin_registrar(span, name); if let Some((lib, disambiguator)) = registrar { diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index bc87086e1061a..428f4f328b907 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -421,19 +421,19 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt let name = attr.name_or_empty(); if attr.is_word() { - if name == "no_default_passes" { + if name == sym::no_default_passes { report_deprecated_attr("no_default_passes", diag); if default_passes == passes::DefaultPassOption::Default { default_passes = passes::DefaultPassOption::None; } } } else if let Some(value) = attr.value_str() { - let sink = match name.get() { - "passes" => { + let sink = match name { + sym::passes => { report_deprecated_attr("passes = \"...\"", diag); &mut manual_passes }, - "plugins" => { + sym::plugins => { report_deprecated_attr("plugins = \"...\"", diag); eprintln!("WARNING: #![doc(plugins = \"...\")] no longer functions; \ see CVE-2018-1000622"); @@ -446,7 +446,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt } } - if attr.is_word() && name == "document_private_items" { + if attr.is_word() && name == sym::document_private_items { if default_passes == passes::DefaultPassOption::Default { default_passes = passes::DefaultPassOption::Private; } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index cbaa911eccca5..0207fcda9e880 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -50,7 +50,7 @@ use syntax::ast; use syntax::ext::base::MacroKind; use syntax::source_map::FileName; use syntax::feature_gate::UnstableFeatures; -use syntax::symbol::sym; +use syntax::symbol::{Symbol, sym}; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId}; use rustc::middle::privacy::AccessLevels; use rustc::middle::stability; @@ -573,23 +573,23 @@ pub fn run(mut krate: clean::Crate, // going to emit HTML if let Some(attrs) = krate.module.as_ref().map(|m| &m.attrs) { for attr in attrs.lists(sym::doc) { - match (attr.name_or_empty().get(), attr.value_str()) { - ("html_favicon_url", Some(s)) => { + match (attr.name_or_empty(), attr.value_str()) { + (sym::html_favicon_url, Some(s)) => { scx.layout.favicon = s.to_string(); } - ("html_logo_url", Some(s)) => { + (sym::html_logo_url, Some(s)) => { scx.layout.logo = s.to_string(); } - ("html_playground_url", Some(s)) => { + (sym::html_playground_url, Some(s)) => { markdown::PLAYGROUND.with(|slot| { let name = krate.name.clone(); *slot.borrow_mut() = Some((Some(name), s.to_string())); }); } - ("issue_tracker_base_url", Some(s)) => { + (sym::issue_tracker_base_url, Some(s)) => { scx.issue_tracker_base_url = Some(s.to_string()); } - ("html_no_source", None) if attr.is_word() => { + (sym::html_no_source, None) if attr.is_word() => { scx.include_sources = false; } _ => {} @@ -3762,22 +3762,22 @@ fn render_attribute(attr: &ast::MetaItem) -> Option { } } -const ATTRIBUTE_WHITELIST: &'static [&'static str] = &[ - "export_name", - "lang", - "link_section", - "must_use", - "no_mangle", - "repr", - "unsafe_destructor_blind_to_params", - "non_exhaustive" +const ATTRIBUTE_WHITELIST: &'static [Symbol] = &[ + sym::export_name, + sym::lang, + sym::link_section, + sym::must_use, + sym::no_mangle, + sym::repr, + sym::unsafe_destructor_blind_to_params, + sym::non_exhaustive ]; fn render_attributes(w: &mut dyn fmt::Write, it: &clean::Item) -> fmt::Result { let mut attrs = String::new(); for attr in &it.attrs.other_attrs { - if !ATTRIBUTE_WHITELIST.contains(&attr.name_or_empty().get()) { + if !ATTRIBUTE_WHITELIST.contains(&attr.name_or_empty()) { continue; } if let Some(s) = render_attribute(&attr.meta().unwrap()) { diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs index 43de3f74e4a2e..65ca96afab129 100644 --- a/src/libsyntax/attr/builtin.rs +++ b/src/libsyntax/attr/builtin.rs @@ -229,10 +229,9 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, )+ for meta in metas { if let Some(mi) = meta.meta_item() { - match mi.name_or_empty().get() { + match mi.name_or_empty() { $( - stringify!($name) - => if !get(mi, &mut $name) { continue 'outer }, + sym::$name => if !get(mi, &mut $name) { continue 'outer }, )+ _ => { let expected = &[ $( stringify!($name) ),+ ]; @@ -259,8 +258,8 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, } } - match meta.name_or_empty().get() { - "rustc_deprecated" => { + match meta.name_or_empty() { + sym::rustc_deprecated => { if rustc_depr.is_some() { span_err!(diagnostic, item_sp, E0540, "multiple rustc_deprecated attributes"); @@ -287,7 +286,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, } } } - "rustc_const_unstable" => { + sym::rustc_const_unstable => { if rustc_const_unstable.is_some() { span_err!(diagnostic, item_sp, E0553, "multiple rustc_const_unstable attributes"); @@ -302,7 +301,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, continue } } - "unstable" => { + sym::unstable => { if stab.is_some() { handle_errors(sess, attr.span, AttrError::MultipleStabilityLevels); break @@ -313,10 +312,10 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, let mut issue = None; for meta in metas { if let Some(mi) = meta.meta_item() { - match mi.name_or_empty().get() { - "feature" => if !get(mi, &mut feature) { continue 'outer }, - "reason" => if !get(mi, &mut reason) { continue 'outer }, - "issue" => if !get(mi, &mut issue) { continue 'outer }, + match mi.name_or_empty() { + sym::feature => if !get(mi, &mut feature) { continue 'outer }, + sym::reason => if !get(mi, &mut reason) { continue 'outer }, + sym::issue => if !get(mi, &mut issue) { continue 'outer }, _ => { handle_errors( sess, @@ -374,7 +373,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, } } } - "stable" => { + sym::stable => { if stab.is_some() { handle_errors(sess, attr.span, AttrError::MultipleStabilityLevels); break @@ -385,11 +384,9 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, for meta in metas { match meta { NestedMetaItem::MetaItem(mi) => { - match mi.name_or_empty().get() { - "feature" => - if !get(mi, &mut feature) { continue 'outer }, - "since" => - if !get(mi, &mut since) { continue 'outer }, + match mi.name_or_empty() { + sym::feature => if !get(mi, &mut feature) { continue 'outer }, + sym::since => if !get(mi, &mut since) { continue 'outer }, _ => { handle_errors( sess, @@ -542,14 +539,14 @@ pub fn eval_condition(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F) // The unwraps below may look dangerous, but we've already asserted // that they won't fail with the loop above. - match cfg.name_or_empty().get() { - "any" => mis.iter().any(|mi| { + match cfg.name_or_empty() { + sym::any => mis.iter().any(|mi| { eval_condition(mi.meta_item().unwrap(), sess, eval) }), - "all" => mis.iter().all(|mi| { + sym::all => mis.iter().all(|mi| { eval_condition(mi.meta_item().unwrap(), sess, eval) }), - "not" => { + sym::not => { if mis.len() != 1 { span_err!(sess.span_diagnostic, cfg.span, E0536, "expected 1 cfg-pattern"); return false; @@ -645,9 +642,9 @@ fn find_deprecation_generic<'a, I>(sess: &ParseSess, for meta in list { match meta { NestedMetaItem::MetaItem(mi) => { - match mi.name_or_empty().get() { - "since" => if !get(mi, &mut since) { continue 'outer }, - "note" => if !get(mi, &mut note) { continue 'outer }, + match mi.name_or_empty() { + sym::since => if !get(mi, &mut since) { continue 'outer }, + sym::note => if !get(mi, &mut note) { continue 'outer }, _ => { handle_errors( sess, @@ -739,11 +736,11 @@ pub fn find_repr_attrs(sess: &ParseSess, attr: &Attribute) -> Vec { let mut recognised = false; if item.is_word() { - let hint = match item.name_or_empty().get() { - "C" => Some(ReprC), - "packed" => Some(ReprPacked(1)), - "simd" => Some(ReprSimd), - "transparent" => Some(ReprTransparent), + let hint = match item.name_or_empty() { + sym::C => Some(ReprC), + sym::packed => Some(ReprPacked(1)), + sym::simd => Some(ReprSimd), + sym::transparent => Some(ReprTransparent), name => int_type_of_word(name).map(ReprInt), }; @@ -830,22 +827,22 @@ pub fn find_repr_attrs(sess: &ParseSess, attr: &Attribute) -> Vec { acc } -fn int_type_of_word(s: &str) -> Option { +fn int_type_of_word(s: Symbol) -> Option { use IntType::*; match s { - "i8" => Some(SignedInt(ast::IntTy::I8)), - "u8" => Some(UnsignedInt(ast::UintTy::U8)), - "i16" => Some(SignedInt(ast::IntTy::I16)), - "u16" => Some(UnsignedInt(ast::UintTy::U16)), - "i32" => Some(SignedInt(ast::IntTy::I32)), - "u32" => Some(UnsignedInt(ast::UintTy::U32)), - "i64" => Some(SignedInt(ast::IntTy::I64)), - "u64" => Some(UnsignedInt(ast::UintTy::U64)), - "i128" => Some(SignedInt(ast::IntTy::I128)), - "u128" => Some(UnsignedInt(ast::UintTy::U128)), - "isize" => Some(SignedInt(ast::IntTy::Isize)), - "usize" => Some(UnsignedInt(ast::UintTy::Usize)), + sym::i8 => Some(SignedInt(ast::IntTy::I8)), + sym::u8 => Some(UnsignedInt(ast::UintTy::U8)), + sym::i16 => Some(SignedInt(ast::IntTy::I16)), + sym::u16 => Some(UnsignedInt(ast::UintTy::U16)), + sym::i32 => Some(SignedInt(ast::IntTy::I32)), + sym::u32 => Some(UnsignedInt(ast::UintTy::U32)), + sym::i64 => Some(SignedInt(ast::IntTy::I64)), + sym::u64 => Some(UnsignedInt(ast::UintTy::U64)), + sym::i128 => Some(SignedInt(ast::IntTy::I128)), + sym::u128 => Some(UnsignedInt(ast::UintTy::U128)), + sym::isize => Some(SignedInt(ast::IntTy::Isize)), + sym::usize => Some(UnsignedInt(ast::UintTy::Usize)), _ => None } } diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index c0defa1c6e019..d94a3165b0f1d 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -22,7 +22,7 @@ use crate::parse::parser::Parser; use crate::parse::{self, ParseSess, PResult}; use crate::parse::token::{self, Token}; use crate::ptr::P; -use crate::symbol::{keywords, LocalInternedString, Symbol}; +use crate::symbol::{keywords, Symbol}; use crate::ThinVec; use crate::tokenstream::{TokenStream, TokenTree, DelimSpan}; use crate::GLOBALS; @@ -89,8 +89,8 @@ impl NestedMetaItem { pub fn ident(&self) -> Option { self.meta_item().and_then(|meta_item| meta_item.ident()) } - pub fn name_or_empty(&self) -> LocalInternedString { - self.ident().unwrap_or(keywords::Invalid.ident()).name.as_str() + pub fn name_or_empty(&self) -> Symbol { + self.ident().unwrap_or(keywords::Invalid.ident()).name } /// Gets the string value if self is a MetaItem and the MetaItem is a @@ -167,8 +167,8 @@ impl Attribute { None } } - pub fn name_or_empty(&self) -> LocalInternedString { - self.ident().unwrap_or(keywords::Invalid.ident()).name.as_str() + pub fn name_or_empty(&self) -> Symbol { + self.ident().unwrap_or(keywords::Invalid.ident()).name } pub fn value_str(&self) -> Option { @@ -205,8 +205,8 @@ impl MetaItem { None } } - pub fn name_or_empty(&self) -> LocalInternedString { - self.ident().unwrap_or(keywords::Invalid.ident()).name.as_str() + pub fn name_or_empty(&self) -> Symbol { + self.ident().unwrap_or(keywords::Invalid.ident()).name } // #[attribute(name = "value")] diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index e7740f1835bc5..a49926158de1d 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1605,7 +1605,7 @@ impl<'a> Context<'a> { } } if !attr::is_known(attr) { - if attr.name_or_empty().starts_with("rustc_") { + if attr.name_or_empty().as_str().starts_with("rustc_") { let msg = "unless otherwise specified, attributes with the prefix `rustc_` \ are reserved for internal compiler diagnostics"; gate_feature!(self, rustc_attrs, attr.span, msg); @@ -2335,7 +2335,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], } let name = mi.name_or_empty(); - if INCOMPLETE_FEATURES.iter().any(|f| name == f.as_str()) { + if INCOMPLETE_FEATURES.iter().any(|f| name == *f) { span_handler.struct_span_warn( mi.span(), &format!( @@ -2345,7 +2345,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], ).emit(); } - if let Some(edition) = ALL_EDITIONS.iter().find(|e| name == e.feature_name().as_str()) { + if let Some(edition) = ALL_EDITIONS.iter().find(|e| name == e.feature_name()) { if *edition <= crate_edition { continue; } diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 228862c830fd8..a13dc07085f80 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -464,8 +464,8 @@ impl<'a> TraitDef<'a> { attrs.extend(item.attrs .iter() .filter(|a| { - ["allow", "warn", "deny", "forbid", "stable", "unstable"] - .contains(&a.name_or_empty().get()) + [sym::allow, sym::warn, sym::deny, sym::forbid, sym::stable, sym::unstable] + .contains(&a.name_or_empty()) }) .cloned()); push(Annotatable::Item(P(ast::Item { attrs: attrs, ..(*newitem).clone() }))) From ea956e3ae9e0089861934062544aa44588052e2a Mon Sep 17 00:00:00 2001 From: Pulkit Goyal <7895pulkit@gmail.com> Date: Mon, 13 May 2019 00:37:05 +0300 Subject: [PATCH 209/212] add impl_trait_in_bindings to INCOMPLETE_FEATURES impl_trait_in_bindings is not yet complete and can lead to compiler crashes. Fixes #60764. --- src/libsyntax/feature_gate.rs | 1 + src/test/run-pass/impl-trait-in-bindings.rs | 1 + src/test/run-pass/impl-trait-in-bindings.stderr | 6 ++++++ src/test/ui/impl-trait/bindings-opaque.rs | 1 + src/test/ui/impl-trait/bindings-opaque.stderr | 12 +++++++++--- src/test/ui/impl-trait/bindings.rs | 1 + src/test/ui/impl-trait/bindings.stderr | 14 ++++++++++---- 7 files changed, 29 insertions(+), 7 deletions(-) create mode 100644 src/test/run-pass/impl-trait-in-bindings.stderr diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index a49926158de1d..8a066f3f4a093 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -563,6 +563,7 @@ declare_features! ( // unanticipated results, such as compiler crashes. We warn the user about these // to alert them. const INCOMPLETE_FEATURES: &[Symbol] = &[ + sym::impl_trait_in_bindings, sym::generic_associated_types, sym::const_generics ]; diff --git a/src/test/run-pass/impl-trait-in-bindings.rs b/src/test/run-pass/impl-trait-in-bindings.rs index 9a1f53b48933a..1e3a641b7cf94 100644 --- a/src/test/run-pass/impl-trait-in-bindings.rs +++ b/src/test/run-pass/impl-trait-in-bindings.rs @@ -1,4 +1,5 @@ #![feature(impl_trait_in_bindings)] +//~^ WARN the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash use std::fmt::Debug; diff --git a/src/test/run-pass/impl-trait-in-bindings.stderr b/src/test/run-pass/impl-trait-in-bindings.stderr new file mode 100644 index 0000000000000..4896deb9d5c91 --- /dev/null +++ b/src/test/run-pass/impl-trait-in-bindings.stderr @@ -0,0 +1,6 @@ +warning: the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash + --> $DIR/impl-trait-in-bindings.rs:1:12 + | +LL | #![feature(impl_trait_in_bindings)] + | ^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/src/test/ui/impl-trait/bindings-opaque.rs b/src/test/ui/impl-trait/bindings-opaque.rs index 5f623321943a3..d4eef29ed3207 100644 --- a/src/test/ui/impl-trait/bindings-opaque.rs +++ b/src/test/ui/impl-trait/bindings-opaque.rs @@ -1,4 +1,5 @@ #![feature(impl_trait_in_bindings)] +//~^ WARN the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash const FOO: impl Copy = 42; diff --git a/src/test/ui/impl-trait/bindings-opaque.stderr b/src/test/ui/impl-trait/bindings-opaque.stderr index 8b2514c050142..d0a6a4ee578f7 100644 --- a/src/test/ui/impl-trait/bindings-opaque.stderr +++ b/src/test/ui/impl-trait/bindings-opaque.stderr @@ -1,17 +1,23 @@ +warning: the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash + --> $DIR/bindings-opaque.rs:1:12 + | +LL | #![feature(impl_trait_in_bindings)] + | ^^^^^^^^^^^^^^^^^^^^^^ + error[E0599]: no method named `count_ones` found for type `impl std::marker::Copy` in the current scope - --> $DIR/bindings-opaque.rs:10:17 + --> $DIR/bindings-opaque.rs:11:17 | LL | let _ = FOO.count_ones(); | ^^^^^^^^^^ error[E0599]: no method named `count_ones` found for type `impl std::marker::Copy` in the current scope - --> $DIR/bindings-opaque.rs:12:17 + --> $DIR/bindings-opaque.rs:13:17 | LL | let _ = BAR.count_ones(); | ^^^^^^^^^^ error[E0599]: no method named `count_ones` found for type `impl std::marker::Copy` in the current scope - --> $DIR/bindings-opaque.rs:14:17 + --> $DIR/bindings-opaque.rs:15:17 | LL | let _ = foo.count_ones(); | ^^^^^^^^^^ diff --git a/src/test/ui/impl-trait/bindings.rs b/src/test/ui/impl-trait/bindings.rs index 91d092634a901..104a44d65662e 100644 --- a/src/test/ui/impl-trait/bindings.rs +++ b/src/test/ui/impl-trait/bindings.rs @@ -1,4 +1,5 @@ #![feature(impl_trait_in_bindings)] +//~^ WARN the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash fn a(x: T) { const foo: impl Clone = x; diff --git a/src/test/ui/impl-trait/bindings.stderr b/src/test/ui/impl-trait/bindings.stderr index a5bf583afeaf6..c66836ab8e5af 100644 --- a/src/test/ui/impl-trait/bindings.stderr +++ b/src/test/ui/impl-trait/bindings.stderr @@ -1,23 +1,29 @@ +warning: the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash + --> $DIR/bindings.rs:1:12 + | +LL | #![feature(impl_trait_in_bindings)] + | ^^^^^^^^^^^^^^^^^^^^^^ + error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/bindings.rs:4:29 + --> $DIR/bindings.rs:5:29 | LL | const foo: impl Clone = x; | ^ non-constant value error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/bindings.rs:10:33 + --> $DIR/bindings.rs:11:33 | LL | const foo: impl Clone = x; | ^ non-constant value error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/bindings.rs:17:33 + --> $DIR/bindings.rs:18:33 | LL | const foo: impl Clone = x; | ^ non-constant value error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/bindings.rs:24:33 + --> $DIR/bindings.rs:25:33 | LL | const foo: impl Clone = x; | ^ non-constant value From 02a148dba261439626c5020a7cbb15e690521e87 Mon Sep 17 00:00:00 2001 From: "@amit.chandra" <@amit.chandra> Date: Fri, 26 Apr 2019 19:53:18 +0530 Subject: [PATCH 210/212] wip nth_back on chunks Signed-off-by: wizAmit --- src/libcore/slice/mod.rs | 16 ++++++++++++++++ src/libcore/tests/slice.rs | 13 +++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 8731f48675356..049d38c158ce5 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -4152,6 +4152,22 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { Some(snd) } } + + #[inline] + fn nth_back(&mut self, n: usize) { + let (end, overflow) = self.v.len().overflowing_sub(n); + if end < self.v.len() || overflow { + self.v = &[]; + None + } else { + let start = match end.checked_sub(self.chunk_size) { + Some(sum) => cmp::min(self.v.len(), sum), + None => self.v.len(), + }; + let nth = &self.v[start..end]; + self.v = &self.v[end..]; + } + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index acf6b03791f01..0233b96d3a72d 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -134,6 +134,19 @@ fn test_chunks_nth() { assert_eq!(c2.next(), None); } +#[test] +fn test_chunks_nth_back() { + let v: &[i32] = &[0, 1, 2, 3, 4, 5]; + let mut c = v.chunks(2); + assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); + assert_eq!(c.next().unwrap(), &[4, 5]); + + let v2: &[i32] = &[0, 1, 2, 3, 4]; + let mut c2 = v2.chunks(3); + assert_eq!(c2.nth_back(1).unwrap(), &[0, 1]); + assert_eq!(c2.next(), None); +} + #[test] fn test_chunks_last() { let v: &[i32] = &[0, 1, 2, 3, 4, 5]; From aff83c80dd162b43a301e2bea73762cc4560f0f3 Mon Sep 17 00:00:00 2001 From: "@amit.chandra" <@amit.chandra> Date: Wed, 1 May 2019 23:34:07 +0530 Subject: [PATCH 211/212] hopefully working nth_back on chunks Signed-off-by: wizAmit --- src/libcore/slice/mod.rs | 17 +++++++++-------- src/libcore/tests/slice.rs | 9 ++++++++- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 049d38c158ce5..00dbe7104d1a4 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -4154,18 +4154,19 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { } #[inline] - fn nth_back(&mut self, n: usize) { - let (end, overflow) = self.v.len().overflowing_sub(n); - if end < self.v.len() || overflow { - self.v = &[]; + fn nth_back(&mut self, n: usize) -> Option { + let (end, overflow) = self.v.len().overflowing_sub(n * self.chunk_size); + if overflow { + self.v = &mut []; None } else { let start = match end.checked_sub(self.chunk_size) { - Some(sum) => cmp::min(self.v.len(), sum), - None => self.v.len(), + Some(res) => cmp::min(self.v.len(), res), + None => 0, }; - let nth = &self.v[start..end]; - self.v = &self.v[end..]; + let nth_back = &self.v[start..end]; + self.v = &self.v[..start]; + Some(nth_back) } } } diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index 0233b96d3a72d..edea405fad791 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -139,12 +139,19 @@ fn test_chunks_nth_back() { let v: &[i32] = &[0, 1, 2, 3, 4, 5]; let mut c = v.chunks(2); assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); - assert_eq!(c.next().unwrap(), &[4, 5]); + assert_eq!(c.next().unwrap(), &[0, 1]); + assert_eq!(c.next(), None); let v2: &[i32] = &[0, 1, 2, 3, 4]; let mut c2 = v2.chunks(3); assert_eq!(c2.nth_back(1).unwrap(), &[0, 1]); assert_eq!(c2.next(), None); + assert_eq!(c2.next_back(), None); + + let v3: &[i32] = &[0, 1, 2, 3, 4]; + let mut c3 = v3.chunks(10); + assert_eq!(c3.nth_back(0).unwrap(), &[0, 1, 2, 3, 4]); + assert_eq!(c3.next(), None); } #[test] From 16223e4bea1ecb087c60d2ac1aeb16c7b7033d52 Mon Sep 17 00:00:00 2001 From: wizAmit Date: Tue, 14 May 2019 13:28:43 +0530 Subject: [PATCH 212/212] new implementation for nth_back for chunks --- src/libcore/slice/mod.rs | 27 ++++++++++++++++++++++----- src/libcore/tests/slice.rs | 6 +++++- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 00dbe7104d1a4..72a54c5ce82d0 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -4155,15 +4155,32 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { #[inline] fn nth_back(&mut self, n: usize) -> Option { - let (end, overflow) = self.v.len().overflowing_sub(n * self.chunk_size); + let remainder = match self.v.len().checked_rem(self.chunk_size) { + Some(res) => res, + None => 0, + }; + + let sub_chunk_size = if remainder != 0 { remainder } else { self.chunk_size }; + + let safe_sub = match n.checked_mul(sub_chunk_size) { + Some(res) => res, + None => 0, + }; + + let (end, overflow) = self.v.len().overflowing_sub(safe_sub); if overflow { - self.v = &mut []; + self.v= &[]; None } else { - let start = match end.checked_sub(self.chunk_size) { - Some(res) => cmp::min(self.v.len(), res), - None => 0, + let start = if n == 0 { + self.v.len() - sub_chunk_size + } else { + match end.checked_sub(self.chunk_size) { + Some(res) => res, + None => 0, + } }; + let nth_back = &self.v[start..end]; self.v = &self.v[..start]; Some(nth_back) diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index edea405fad791..cf2602f3210f1 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -144,7 +144,7 @@ fn test_chunks_nth_back() { let v2: &[i32] = &[0, 1, 2, 3, 4]; let mut c2 = v2.chunks(3); - assert_eq!(c2.nth_back(1).unwrap(), &[0, 1]); + assert_eq!(c2.nth_back(1).unwrap(), &[0, 1, 2]); assert_eq!(c2.next(), None); assert_eq!(c2.next_back(), None); @@ -152,6 +152,10 @@ fn test_chunks_nth_back() { let mut c3 = v3.chunks(10); assert_eq!(c3.nth_back(0).unwrap(), &[0, 1, 2, 3, 4]); assert_eq!(c3.next(), None); + + let v4: &[i32] = &[0, 1, 2]; + let mut c4 = v4.chunks(10); + assert_eq!(c4.nth_back(1_000_000_000usize), None); } #[test]