From: bors Date: Sat, 12 Feb 2022 21:42:10 +0000 (+0000) Subject: Auto merge of #91403 - cjgillot:inherit-async, r=oli-obk X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=3cfa4def7c87d571bd46d92fed608edf8fad236e;hp=10cf626d0ea7be3eb971691772b5eb30013d4f02;p=rust.git Auto merge of #91403 - cjgillot:inherit-async, r=oli-obk Inherit lifetimes for async fn instead of duplicating them. The current desugaring of `async fn foo<'a>(&usize) -> &u8` is equivalent to ```rust fn foo<'a, '0>(&'0 usize) -> foo<'static, 'static>::Opaque<'a, '0, '_>; type foo<'_a, '_0>::Opaque<'a, '0, '1> = impl Future; ``` following the RPIT model. Duplicating all the inherited lifetime parameters and setting the inherited version to `'static` makes lowering more complex and causes issues like #61949. This PR removes the duplication of inherited lifetimes to directly use ```rust fn foo<'a, '0>(&'0 usize) -> foo<'a, '0>::Opaque<'_>; type foo<'a, '0>::Opaque<'1> = impl Future; ``` following the TAIT model. Fixes https://github.com/rust-lang/rust/issues/61949 --- diff --git a/RELEASES.md b/RELEASES.md index aae2a669650..a9422fa103e 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -156,6 +156,7 @@ Language - [Macro attributes may follow `#[derive]` and will see the original (pre-`cfg`) input.][87220] - [Accept curly-brace macros in expressions, like `m!{ .. }.method()` and `m!{ .. }?`.][88690] - [Allow panicking in constant evaluation.][89508] +- [Ignore derived `Clone` and `Debug` implementations during dead code analysis.][85200] Compiler -------- @@ -216,6 +217,9 @@ Cargo Compatibility notes ------------------- +- [Ignore derived `Clone` and `Debug` implementations during dead code analysis.][85200] + This will break some builds that set `#![deny(dead_code)]`. + Internal changes ---------------- These changes provide no direct user facing benefits, but represent significant @@ -224,6 +228,7 @@ and related tools. - [Added an experimental backend for codegen with `libgccjit`.][87260] +[85200]: https://github.com/rust-lang/rust/pull/85200/ [86191]: https://github.com/rust-lang/rust/pull/86191/ [87220]: https://github.com/rust-lang/rust/pull/87220/ [87260]: https://github.com/rust-lang/rust/pull/87260/ diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 89d411d4b36..5a85356d96d 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -373,7 +373,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { err.emit(); } Entry::Vacant(v) => { - v.insert(idx); + if r == reg { + v.insert(idx); + } } } }; diff --git a/compiler/rustc_ast_pretty/src/pp/convenience.rs b/compiler/rustc_ast_pretty/src/pp/convenience.rs index 785e6886d8a..93310dd45c5 100644 --- a/compiler/rustc_ast_pretty/src/pp/convenience.rs +++ b/compiler/rustc_ast_pretty/src/pp/convenience.rs @@ -75,6 +75,10 @@ pub fn hardbreak_tok_offset(off: isize) -> Token { } pub fn trailing_comma(&mut self) { + self.scan_break(BreakToken { pre_break: Some(','), ..BreakToken::default() }); + } + + pub fn trailing_comma_or_space(&mut self) { self.scan_break(BreakToken { blank_space: 1, pre_break: Some(','), diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index 44116fa76a0..6435f1b6141 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -142,7 +142,7 @@ fn print_expr_struct( if !field.is_last || has_rest { self.word_space(","); } else { - self.trailing_comma(); + self.trailing_comma_or_space(); } } if has_rest { diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index dac84ae9d5f..d7e9ef0e50d 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -1,5 +1,6 @@ use crate::pp::Breaks::Inconsistent; -use crate::pprust::state::{AnnNode, PrintState, State}; +use crate::pprust::state::delimited::IterDelimited; +use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT}; use rustc_ast as ast; use rustc_ast::GenericBound; @@ -138,11 +139,10 @@ fn print_associated_type( self.end(); // end outer head-block } ast::ItemKind::Use(ref tree) => { - self.head(visibility_qualified(&item.vis, "use")); + self.print_visibility(&item.vis); + self.word_nbsp("use"); self.print_use_tree(tree); self.word(";"); - self.end(); // end inner head-block - self.end(); // end outer head-block } ast::ItemKind::Static(ref ty, mutbl, ref body) => { let def = ast::Defaultness::Final; @@ -615,8 +615,8 @@ fn print_use_tree(&mut self, tree: &ast::UseTree) { ast::UseTreeKind::Simple(rename, ..) => { self.print_path(&tree.prefix, false, 0); if let Some(rename) = rename { - self.space(); - self.word_space("as"); + self.nbsp(); + self.word_nbsp("as"); self.print_ident(rename); } } @@ -628,16 +628,36 @@ fn print_use_tree(&mut self, tree: &ast::UseTree) { self.word("*"); } ast::UseTreeKind::Nested(ref items) => { - if tree.prefix.segments.is_empty() { - self.word("{"); - } else { + if !tree.prefix.segments.is_empty() { self.print_path(&tree.prefix, false, 0); - self.word("::{"); + self.word("::"); + } + if items.is_empty() { + self.word("{}"); + } else if items.len() == 1 { + self.print_use_tree(&items[0].0); + } else { + self.cbox(INDENT_UNIT); + self.word("{"); + self.zerobreak(); + self.ibox(0); + for use_tree in items.iter().delimited() { + self.print_use_tree(&use_tree.0); + if !use_tree.is_last { + self.word(","); + if let ast::UseTreeKind::Nested(_) = use_tree.0.kind { + self.hardbreak(); + } else { + self.space(); + } + } + } + self.end(); + self.trailing_comma(); + self.offset(-INDENT_UNIT); + self.word("}"); + self.end(); } - self.commasep(Inconsistent, &items, |this, &(ref tree, _)| { - this.print_use_tree(tree) - }); - self.word("}"); } } } diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index 5702203d7c4..7140cda8e4e 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -327,7 +327,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { verb: &str, optional_adverb_for_moved: &str, moved_path: Option, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { let moved_path = moved_path.map(|mp| format!(": `{}`", mp)).unwrap_or_default(); struct_span_err!( diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index 96326ef2d5a..ac9950241bf 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -55,7 +55,7 @@ impl<'tcx> UniverseInfo<'tcx> { found, TypeError::RegionsPlaceholderMismatch, ); - err.buffer(&mut mbcx.errors_buffer); + mbcx.buffer_error(err); } UniverseInfoInner::TypeOp(ref type_op_info) => { type_op_info.report_error(mbcx, placeholder, error_element, cause); @@ -64,11 +64,9 @@ impl<'tcx> UniverseInfo<'tcx> { // FIXME: This error message isn't great, but it doesn't show // up in the existing UI tests. Consider investigating this // some more. - mbcx.infcx - .tcx - .sess - .struct_span_err(cause.span, "higher-ranked subtype error") - .buffer(&mut mbcx.errors_buffer); + mbcx.buffer_error( + mbcx.infcx.tcx.sess.struct_span_err(cause.span, "higher-ranked subtype error"), + ); } } } @@ -149,7 +147,7 @@ fn report_error( { adjusted } else { - self.fallback_error(tcx, cause.span).buffer(&mut mbcx.errors_buffer); + mbcx.buffer_error(self.fallback_error(tcx, cause.span)); return; }; @@ -178,9 +176,9 @@ fn report_error( let nice_error = self.nice_error(tcx, cause, placeholder_region, error_region); if let Some(nice_error) = nice_error { - nice_error.buffer(&mut mbcx.errors_buffer); + mbcx.buffer_error(nice_error); } else { - self.fallback_error(tcx, span).buffer(&mut mbcx.errors_buffer); + mbcx.buffer_error(self.fallback_error(tcx, span)); } } } diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index ba111d394ec..7b8b5974fe7 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -104,9 +104,9 @@ pub(crate) fn report_use_of_moved_or_uninitialized( format!("{} occurs due to use{}", desired_action.as_noun(), use_spans.describe()), ); - err.buffer(&mut self.errors_buffer); + self.buffer_error(err); } else { - if let Some((reported_place, _)) = self.move_error_reported.get(&move_out_indices) { + if let Some((reported_place, _)) = self.has_move_error(&move_out_indices) { if self.prefixes(*reported_place, PrefixSet::All).any(|p| p == used_place) { debug!( "report_use_of_moved_or_uninitialized place: error suppressed \ @@ -449,12 +449,7 @@ pub(crate) fn report_use_of_moved_or_uninitialized( } } - if let Some((_, mut old_err)) = - self.move_error_reported.insert(move_out_indices, (used_place, err)) - { - // Cancel the old error so it doesn't ICE. - old_err.cancel(); - } + self.buffer_move_error(move_out_indices, (used_place, err)); } } @@ -503,7 +498,7 @@ pub(crate) fn report_move_out_while_borrowed( Some(borrow_span), None, ); - err.buffer(&mut self.errors_buffer); + self.buffer_error(err); } pub(crate) fn report_use_while_mutably_borrowed( @@ -1021,7 +1016,7 @@ pub(crate) fn report_borrowed_value_does_not_live_long_enough( if self.body.local_decls[borrowed_local].is_ref_to_thread_local() { let err = self.report_thread_local_value_does_not_live_long_enough(drop_span, borrow_span); - err.buffer(&mut self.errors_buffer); + self.buffer_error(err); return; } @@ -1113,7 +1108,7 @@ pub(crate) fn report_borrowed_value_does_not_live_long_enough( ), }; - err.buffer(&mut self.errors_buffer); + self.buffer_error(err); } fn report_local_value_does_not_live_long_enough( @@ -1295,7 +1290,7 @@ fn report_borrow_conflicts_with_destructor( None, ); - err.buffer(&mut self.errors_buffer); + self.buffer_error(err); } fn report_thread_local_value_does_not_live_long_enough( @@ -1810,7 +1805,7 @@ pub(crate) fn report_illegal_mutation_of_borrowed( loan.kind.describe_mutability(), ); - err.buffer(&mut self.errors_buffer); + self.buffer_error(err); return; } @@ -1836,7 +1831,7 @@ pub(crate) fn report_illegal_mutation_of_borrowed( self.explain_deref_coercion(loan, &mut err); - err.buffer(&mut self.errors_buffer); + self.buffer_error(err); } fn explain_deref_coercion(&mut self, loan: &BorrowData<'tcx>, err: &mut DiagnosticBuilder<'_>) { @@ -1938,7 +1933,7 @@ pub(crate) fn report_illegal_reassignment( } } err.span_label(span, msg); - err.buffer(&mut self.errors_buffer); + self.buffer_error(err); } fn classify_drop_access_kind(&self, place: PlaceRef<'tcx>) -> StorageDeadOrDrop<'tcx> { diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 692c20d7dfe..2934d921868 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -264,7 +264,7 @@ fn report(&mut self, error: GroupedMoveError<'tcx>) { }; self.add_move_hints(error, &mut err, err_span); - err.buffer(&mut self.errors_buffer); + self.buffer_error(err); } fn report_cannot_move_from_static( diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index e6c057cc8ee..5963904aa0b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -626,7 +626,7 @@ pub(crate) fn report_mutability_error( } } - err.buffer(&mut self.errors_buffer); + self.buffer_error(err); } /// User cannot make signature of a trait mutable without changing the diff --git a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs index 723b57ed970..21f00af5c0c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs +++ b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs @@ -256,6 +256,6 @@ fn compile_all_suggestions( diag.sort_span = mir_span.shrink_to_hi(); // Buffer the diagnostic - diag.buffer(&mut mbcx.errors_buffer); + mbcx.buffer_error(diag); } } diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index df23eaf24bc..31c977cc78d 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -168,14 +168,12 @@ pub(crate) fn report_region_errors(&mut self, nll_errors: RegionErrors<'tcx>) { let type_test_span = type_test.locations.span(&self.body); if let Some(lower_bound_region) = lower_bound_region { - self.infcx - .construct_generic_bound_failure( - type_test_span, - None, - type_test.generic_kind, - lower_bound_region, - ) - .buffer(&mut self.errors_buffer); + self.buffer_error(self.infcx.construct_generic_bound_failure( + type_test_span, + None, + type_test.generic_kind, + lower_bound_region, + )); } else { // FIXME. We should handle this case better. It // indicates that we have e.g., some region variable @@ -186,27 +184,22 @@ pub(crate) fn report_region_errors(&mut self, nll_errors: RegionErrors<'tcx>) { // to report it; we could probably handle it by // iterating over the universal regions and reporting // an error that multiple bounds are required. - self.infcx - .tcx - .sess - .struct_span_err( - type_test_span, - &format!("`{}` does not live long enough", type_test.generic_kind), - ) - .buffer(&mut self.errors_buffer); + self.buffer_error(self.infcx.tcx.sess.struct_span_err( + type_test_span, + &format!("`{}` does not live long enough", type_test.generic_kind), + )); } } RegionErrorKind::UnexpectedHiddenRegion { span, hidden_ty, member_region } => { let named_ty = self.regioncx.name_regions(self.infcx.tcx, hidden_ty); let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region); - unexpected_hidden_region_diagnostic( + self.buffer_error(unexpected_hidden_region_diagnostic( self.infcx.tcx, span, named_ty, named_region, - ) - .buffer(&mut self.errors_buffer); + )); } RegionErrorKind::BoundUniversalRegionError { @@ -285,7 +278,7 @@ pub(crate) fn report_region_error( if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) { let nice = NiceRegionError::new_from_span(self.infcx, cause.span, o, f); if let Some(diag) = nice.try_report_from_nll() { - diag.buffer(&mut self.errors_buffer); + self.buffer_error(diag); return; } } @@ -375,7 +368,7 @@ pub(crate) fn report_region_error( } } - diag.buffer(&mut self.errors_buffer); + self.buffer_error(diag); } /// Report a specialized error when `FnMut` closures return a reference to a captured variable. diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 5597a8b0915..459b03b0fad 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -175,10 +175,13 @@ fn do_mir_borrowck<'a, 'tcx>( } } + let mut errors = error::BorrowckErrors::new(); + // Gather the upvars of a closure, if any. let tables = tcx.typeck_opt_const_arg(def); if let Some(ErrorReported) = tables.tainted_by_errors { infcx.set_tainted_by_errors(); + errors.set_tainted_by_errors(); } let upvars: Vec<_> = tables .closure_min_captures_flattened(def.did.to_def_id()) @@ -205,7 +208,6 @@ fn do_mir_borrowck<'a, 'tcx>( let location_table_owned = LocationTable::new(body); let location_table = &location_table_owned; - let mut errors_buffer = Vec::new(); let (move_data, move_errors): (MoveData<'tcx>, Vec<(Place<'tcx>, MoveError<'tcx>)>) = match MoveData::gather_moves(&body, tcx, param_env) { Ok(move_data) => (move_data, Vec::new()), @@ -263,7 +265,7 @@ fn do_mir_borrowck<'a, 'tcx>( ®ioncx, &opt_closure_req, &opaque_type_values, - &mut errors_buffer, + &mut errors, ); // The various `flow_*` structures can be large. We drop `flow_inits` here @@ -310,9 +312,7 @@ fn do_mir_borrowck<'a, 'tcx>( access_place_error_reported: Default::default(), reservation_error_reported: Default::default(), reservation_warnings: Default::default(), - move_error_reported: BTreeMap::new(), uninitialized_error_reported: Default::default(), - errors_buffer, regioncx: regioncx.clone(), used_mut: Default::default(), used_mut_upvars: SmallVec::new(), @@ -323,9 +323,10 @@ fn do_mir_borrowck<'a, 'tcx>( region_names: RefCell::default(), next_region_name: RefCell::new(1), polonius_output: None, + errors, }; promoted_mbcx.report_move_errors(move_errors); - errors_buffer = promoted_mbcx.errors_buffer; + errors = promoted_mbcx.errors; }; } @@ -343,9 +344,7 @@ fn do_mir_borrowck<'a, 'tcx>( access_place_error_reported: Default::default(), reservation_error_reported: Default::default(), reservation_warnings: Default::default(), - move_error_reported: BTreeMap::new(), uninitialized_error_reported: Default::default(), - errors_buffer, regioncx: Rc::clone(®ioncx), used_mut: Default::default(), used_mut_upvars: SmallVec::new(), @@ -356,6 +355,7 @@ fn do_mir_borrowck<'a, 'tcx>( region_names: RefCell::default(), next_region_name: RefCell::new(1), polonius_output, + errors, }; // Compute and report region errors, if any. @@ -398,7 +398,7 @@ fn do_mir_borrowck<'a, 'tcx>( diag.message = initial_diag.styled_message().clone(); diag.span = initial_diag.span.clone(); - diag.buffer(&mut mbcx.errors_buffer); + mbcx.buffer_error(diag); }, ); initial_diag.cancel(); @@ -423,7 +423,7 @@ fn do_mir_borrowck<'a, 'tcx>( mbcx.gather_used_muts(temporary_used_locals, unused_mut_locals); debug!("mbcx.used_mut: {:?}", mbcx.used_mut); - let used_mut = mbcx.used_mut; + let used_mut = std::mem::take(&mut mbcx.used_mut); for local in mbcx.body.mut_vars_and_args_iter().filter(|local| !used_mut.contains(local)) { let local_decl = &mbcx.body.local_decls[local]; let lint_root = match &mbcx.body.source_scopes[local_decl.source_info.scope].local_data { @@ -460,23 +460,13 @@ fn do_mir_borrowck<'a, 'tcx>( }) } - // Buffer any move errors that we collected and de-duplicated. - for (_, (_, diag)) in mbcx.move_error_reported { - diag.buffer(&mut mbcx.errors_buffer); - } - - if !mbcx.errors_buffer.is_empty() { - mbcx.errors_buffer.sort_by_key(|diag| diag.sort_span); - - for diag in mbcx.errors_buffer.drain(..) { - mbcx.infcx.tcx.sess.diagnostic().emit_diagnostic(&diag); - } - } + let tainted_by_errors = mbcx.emit_errors(); let result = BorrowCheckResult { concrete_opaque_types: opaque_type_values, closure_requirements: opt_closure_req, used_mut_upvars: mbcx.used_mut_upvars, + tainted_by_errors, }; let body_with_facts = if return_body_with_facts { @@ -553,26 +543,9 @@ struct MirBorrowckCtxt<'cx, 'tcx> { /// for the activation of the borrow. reservation_warnings: FxHashMap, Span, Location, BorrowKind, BorrowData<'tcx>)>, - /// This field keeps track of move errors that are to be reported for given move indices. - /// - /// There are situations where many errors can be reported for a single move out (see #53807) - /// and we want only the best of those errors. - /// - /// The `report_use_of_moved_or_uninitialized` function checks this map and replaces the - /// diagnostic (if there is one) if the `Place` of the error being reported is a prefix of the - /// `Place` of the previous most diagnostic. This happens instead of buffering the error. Once - /// all move errors have been reported, any diagnostics in this map are added to the buffer - /// to be emitted. - /// - /// `BTreeMap` is used to preserve the order of insertions when iterating. This is necessary - /// when errors in the map are being re-added to the error buffer so that errors with the - /// same primary span come out in a consistent order. - move_error_reported: BTreeMap, (PlaceRef<'tcx>, DiagnosticBuilder<'cx>)>, /// This field keeps track of errors reported in the checking of uninitialized variables, /// so that we don't report seemingly duplicate errors. uninitialized_error_reported: FxHashSet>, - /// Errors to be reported buffer - errors_buffer: Vec, /// This field keeps track of all the local variables that are declared mut and are mutated. /// Used for the warning issued by an unused mutable local variable. used_mut: FxHashSet, @@ -604,6 +577,8 @@ struct MirBorrowckCtxt<'cx, 'tcx> { /// Results of Polonius analysis. polonius_output: Option>, + + errors: error::BorrowckErrors<'tcx>, } // Check that: @@ -1027,7 +1002,6 @@ fn access_place( if conflict_error || mutability_error { debug!("access_place: logging error place_span=`{:?}` kind=`{:?}`", place_span, kind); - self.access_place_error_reported.insert((place_span.0, place_span.1)); } } @@ -1107,12 +1081,14 @@ fn check_access_for_conflict( error_reported = true; match kind { ReadKind::Copy => { - this.report_use_while_mutably_borrowed(location, place_span, borrow) - .buffer(&mut this.errors_buffer); + let err = this + .report_use_while_mutably_borrowed(location, place_span, borrow); + this.buffer_error(err); } ReadKind::Borrow(bk) => { - this.report_conflicting_borrow(location, place_span, bk, borrow) - .buffer(&mut this.errors_buffer); + let err = + this.report_conflicting_borrow(location, place_span, bk, borrow); + this.buffer_error(err); } } Control::Break @@ -1162,8 +1138,9 @@ fn check_access_for_conflict( error_reported = true; match kind { WriteKind::MutableBorrow(bk) => { - this.report_conflicting_borrow(location, place_span, bk, borrow) - .buffer(&mut this.errors_buffer); + let err = + this.report_conflicting_borrow(location, place_span, bk, borrow); + this.buffer_error(err); } WriteKind::StorageDeadOrDrop => this .report_borrowed_value_does_not_live_long_enough( @@ -1570,7 +1547,7 @@ fn check_for_local_borrow(&mut self, borrow: &BorrowData<'tcx>, yield_span: Span yield_span, ); - err.buffer(&mut self.errors_buffer); + self.buffer_error(err); } } @@ -2046,10 +2023,9 @@ fn check_access_permissions( | WriteKind::MutableBorrow(BorrowKind::Shared) | WriteKind::MutableBorrow(BorrowKind::Shallow), ) => { - if let (Err(_), true) = ( - self.is_mutable(place.as_ref(), is_local_mutation_allowed), - self.errors_buffer.is_empty(), - ) { + if self.is_mutable(place.as_ref(), is_local_mutation_allowed).is_err() + && !self.has_buffered_errors() + { // rust-lang/rust#46908: In pure NLL mode this code path should be // unreachable, but we use `delay_span_bug` because we can hit this when // dereferencing a non-Copy raw pointer *and* have `-Ztreat-err-as-bug` @@ -2301,6 +2277,103 @@ fn is_upvar_field_projection(&self, place_ref: PlaceRef<'tcx>) -> Option } } +mod error { + use super::*; + + pub struct BorrowckErrors<'tcx> { + /// This field keeps track of move errors that are to be reported for given move indices. + /// + /// There are situations where many errors can be reported for a single move out (see #53807) + /// and we want only the best of those errors. + /// + /// The `report_use_of_moved_or_uninitialized` function checks this map and replaces the + /// diagnostic (if there is one) if the `Place` of the error being reported is a prefix of the + /// `Place` of the previous most diagnostic. This happens instead of buffering the error. Once + /// all move errors have been reported, any diagnostics in this map are added to the buffer + /// to be emitted. + /// + /// `BTreeMap` is used to preserve the order of insertions when iterating. This is necessary + /// when errors in the map are being re-added to the error buffer so that errors with the + /// same primary span come out in a consistent order. + buffered_move_errors: + BTreeMap, (PlaceRef<'tcx>, DiagnosticBuilder<'tcx>)>, + /// Errors to be reported buffer + buffered: Vec, + /// Set to Some if we emit an error during borrowck + tainted_by_errors: Option, + } + + impl BorrowckErrors<'_> { + pub fn new() -> Self { + BorrowckErrors { + buffered_move_errors: BTreeMap::new(), + buffered: Default::default(), + tainted_by_errors: None, + } + } + + pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_>) { + self.tainted_by_errors = Some(ErrorReported {}); + t.buffer(&mut self.buffered); + } + + pub fn set_tainted_by_errors(&mut self) { + self.tainted_by_errors = Some(ErrorReported {}); + } + } + + impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { + pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_>) { + self.errors.buffer_error(t); + } + + pub fn buffer_move_error( + &mut self, + move_out_indices: Vec, + place_and_err: (PlaceRef<'tcx>, DiagnosticBuilder<'tcx>), + ) -> bool { + if let Some((_, mut diag)) = + self.errors.buffered_move_errors.insert(move_out_indices, place_and_err) + { + // Cancel the old diagnostic so we don't ICE + diag.cancel(); + false + } else { + true + } + } + + pub fn emit_errors(&mut self) -> Option { + // Buffer any move errors that we collected and de-duplicated. + for (_, (_, diag)) in std::mem::take(&mut self.errors.buffered_move_errors) { + // We have already set tainted for this error, so just buffer it. + diag.buffer(&mut self.errors.buffered); + } + + if !self.errors.buffered.is_empty() { + self.errors.buffered.sort_by_key(|diag| diag.sort_span); + + for diag in self.errors.buffered.drain(..) { + self.infcx.tcx.sess.diagnostic().emit_diagnostic(&diag); + } + } + + self.errors.tainted_by_errors + } + + pub fn has_buffered_errors(&self) -> bool { + self.errors.buffered.is_empty() + } + + pub fn has_move_error( + &self, + move_out_indices: &[MoveOutIndex], + ) -> Option<&(PlaceRef<'tcx>, DiagnosticBuilder<'cx>)> { + self.errors.buffered_move_errors.get(move_out_indices) + } + } +} + /// The degree of overlap between 2 places for borrow-checking. enum Overlap { /// The places might partially overlap - in this case, we give diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 6ffab165779..7fc1fe1130b 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -1,7 +1,6 @@ //! The entry point of the NLL borrow checker. use rustc_data_structures::vec_map::VecMap; -use rustc_errors::Diagnostic; use rustc_index::vec::IndexVec; use rustc_infer::infer::InferCtxt; use rustc_middle::mir::{create_dump_file, dump_enabled, dump_mir, PassWhere}; @@ -373,7 +372,7 @@ pub(super) fn dump_annotation<'a, 'tcx>( regioncx: &RegionInferenceContext<'tcx>, closure_region_requirements: &Option>, opaque_type_values: &VecMap, Ty<'tcx>>, - errors_buffer: &mut Vec, + errors: &mut crate::error::BorrowckErrors<'tcx>, ) { let tcx = infcx.tcx; let base_def_id = tcx.typeck_root_def_id(body.source.def_id()); @@ -418,7 +417,7 @@ pub(super) fn dump_annotation<'a, 'tcx>( err.note(&format!("Inferred opaque type values:\n{:#?}", opaque_type_values)); } - err.buffer(errors_buffer); + errors.buffer_error(err); } fn for_each_region_constraint( diff --git a/compiler/rustc_builtin_macros/src/standard_library_imports.rs b/compiler/rustc_builtin_macros/src/standard_library_imports.rs index e106f6014a3..3571517d2b2 100644 --- a/compiler/rustc_builtin_macros/src/standard_library_imports.rs +++ b/compiler/rustc_builtin_macros/src/standard_library_imports.rs @@ -11,7 +11,6 @@ pub fn inject( mut krate: ast::Crate, resolver: &mut dyn ResolverExpand, sess: &Session, - alt_std_name: Option, ) -> ast::Crate { let edition = sess.parse_sess.edition; @@ -53,7 +52,7 @@ pub fn inject( span, ident, vec![cx.attribute(cx.meta_word(span, sym::macro_use))], - ast::ItemKind::ExternCrate(alt_std_name), + ast::ItemKind::ExternCrate(None), ), ); } diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 7f82ce307d5..2472789601e 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -322,12 +322,33 @@ pub fn from_fn_attrs<'ll, 'tcx>( // The target doesn't care; the subtarget reads our attribute. apply_tune_cpu_attr(cx, llfn); - let mut function_features = codegen_fn_attrs - .target_features + let function_features = + codegen_fn_attrs.target_features.iter().map(|f| f.as_str()).collect::>(); + + if let Some(f) = llvm_util::check_tied_features( + cx.tcx.sess, + &function_features.iter().map(|f| (*f, true)).collect(), + ) { + let span = cx + .tcx + .get_attrs(instance.def_id()) + .iter() + .find(|a| a.has_name(rustc_span::sym::target_feature)) + .map_or_else(|| cx.tcx.def_span(instance.def_id()), |a| a.span); + let msg = format!( + "the target features {} must all be either enabled or disabled together", + f.join(", ") + ); + let mut err = cx.tcx.sess.struct_span_err(span, &msg); + err.help("add the missing features in a `target_feature` attribute"); + err.emit(); + return; + } + + let mut function_features = function_features .iter() - .flat_map(|f| { - let feature = f.as_str(); - llvm_util::to_llvm_feature(cx.tcx.sess, feature) + .flat_map(|feat| { + llvm_util::to_llvm_feature(cx.tcx.sess, feat) .into_iter() .map(|f| format!("+{}", f)) .collect::>() diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index f91fad2d9c9..727d079d83d 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -2,8 +2,8 @@ use crate::{llvm, llvm_util}; use libc::c_int; use libloading::Library; -use rustc_codegen_ssa::target_features::supported_target_features; -use rustc_data_structures::fx::FxHashSet; +use rustc_codegen_ssa::target_features::{supported_target_features, tied_target_features}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_fs_util::path_to_c_string; use rustc_middle::bug; use rustc_session::config::PrintRequest; @@ -191,10 +191,30 @@ pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> Vec<&'a str> { ("aarch64", "frintts") => vec!["fptoint"], ("aarch64", "fcma") => vec!["complxnum"], ("aarch64", "pmuv3") => vec!["perfmon"], + ("aarch64", "paca") => vec!["pauth"], + ("aarch64", "pacg") => vec!["pauth"], (_, s) => vec![s], } } +// Given a map from target_features to whether they are enabled or disabled, +// ensure only valid combinations are allowed. +pub fn check_tied_features( + sess: &Session, + features: &FxHashMap<&str, bool>, +) -> Option<&'static [&'static str]> { + for tied in tied_target_features(sess) { + // Tied features must be set to the same value, or not set at all + let mut tied_iter = tied.iter(); + let enabled = features.get(tied_iter.next().unwrap()); + + if tied_iter.any(|f| enabled != features.get(f)) { + return Some(tied); + } + } + None +} + pub fn target_features(sess: &Session) -> Vec { let target_machine = create_informational_target_machine(sess); supported_target_features(sess) @@ -395,15 +415,19 @@ pub fn llvm_global_features(sess: &Session) -> Vec { Some(_) | None => {} }; + fn strip(s: &str) -> &str { + s.strip_prefix(&['+', '-']).unwrap_or(s) + } + let filter = |s: &str| { if s.is_empty() { return vec![]; } - let feature = if s.starts_with('+') || s.starts_with('-') { - &s[1..] - } else { + let feature = strip(s); + if feature == s { return vec![s.to_string()]; - }; + } + // Rustc-specific feature requests like `+crt-static` or `-crt-static` // are not passed down to LLVM. if RUSTC_SPECIFIC_FEATURES.contains(&feature) { @@ -420,8 +444,17 @@ pub fn llvm_global_features(sess: &Session) -> Vec { features.extend(sess.target.features.split(',').flat_map(&filter)); // -Ctarget-features - features.extend(sess.opts.cg.target_feature.split(',').flat_map(&filter)); - + let feats: Vec<&str> = sess.opts.cg.target_feature.split(',').collect(); + // LLVM enables based on the last occurence of a feature + if let Some(f) = + check_tied_features(sess, &feats.iter().map(|f| (strip(f), !f.starts_with("-"))).collect()) + { + sess.err(&format!( + "Target features {} must all be enabled or disabled together", + f.join(", ") + )); + } + features.extend(feats.iter().flat_map(|&f| filter(f))); features } diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index 63cc6faf9ec..f31b0ee592e 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -74,8 +74,10 @@ ("ssbs", Some(sym::aarch64_target_feature)), // FEAT_SB ("sb", Some(sym::aarch64_target_feature)), - // FEAT_PAUTH - ("pauth", Some(sym::aarch64_target_feature)), + // FEAT_PAUTH (address authentication) + ("paca", Some(sym::aarch64_target_feature)), + // FEAT_PAUTH (generic authentication) + ("pacg", Some(sym::aarch64_target_feature)), // FEAT_DPB ("dpb", Some(sym::aarch64_target_feature)), // FEAT_DPB2 @@ -137,6 +139,8 @@ ("v8.7a", Some(sym::aarch64_target_feature)), ]; +const AARCH64_TIED_FEATURES: &[&[&str]] = &[&["paca", "pacg"]]; + const X86_ALLOWED_FEATURES: &[(&str, Option)] = &[ ("adx", Some(sym::adx_target_feature)), ("aes", None), @@ -256,6 +260,13 @@ pub fn supported_target_features(sess: &Session) -> &'static [(&'static str, Opt } } +pub fn tied_target_features(sess: &Session) -> &'static [&'static [&'static str]] { + match &*sess.target.arch { + "aarch64" => AARCH64_TIED_FEATURES, + _ => &[], + } +} + pub(crate) fn provide(providers: &mut Providers) { providers.supported_target_features = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 9dc34260de7..bfb9c40be57 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -6,7 +6,6 @@ ScalarMaybeUninit, StackPopCleanup, }; -use rustc_errors::ErrorReported; use rustc_hir::def::DefKind; use rustc_middle::mir; use rustc_middle::mir::interpret::ErrorHandled; @@ -281,25 +280,6 @@ pub fn eval_to_allocation_raw_provider<'tcx>( let cid = key.value; let def = cid.instance.def.with_opt_param(); - - if let Some(def) = def.as_local() { - if tcx.has_typeck_results(def.did) { - if let Some(error_reported) = tcx.typeck_opt_const_arg(def).tainted_by_errors { - return Err(ErrorHandled::Reported(error_reported)); - } - } - if !tcx.is_mir_available(def.did) { - tcx.sess.delay_span_bug( - tcx.def_span(def.did), - &format!("no MIR body is available for {:?}", def.did), - ); - return Err(ErrorHandled::Reported(ErrorReported {})); - } - if let Some(error_reported) = tcx.mir_const_qualif_opt_const_arg(def).error_occured { - return Err(ErrorHandled::Reported(error_reported)); - } - } - let is_static = tcx.is_static(def.did); let mut ecx = InterpCx::new( diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 89717b75f12..e157b584052 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -1,3 +1,5 @@ +use rustc_errors::ErrorReported; +use rustc_hir::def::DefKind; use rustc_middle::mir; use rustc_middle::ty::{self, Ty}; use std::borrow::Borrow; @@ -243,6 +245,12 @@ fn load_mir( ty::InstanceDef::Item(def) => { if ecx.tcx.is_ctfe_mir_available(def.did) { Ok(ecx.tcx.mir_for_ctfe_opt_const_arg(def)) + } else if ecx.tcx.def_kind(def.did) == DefKind::AssocConst { + ecx.tcx.sess.delay_span_bug( + rustc_span::DUMMY_SP, + "This is likely a const item that is missing from its impl", + ); + throw_inval!(AlreadyReported(ErrorReported {})); } else { let path = ecx.tcx.def_path_str(def.did); Err(ConstEvalErrKind::NeedsRfc(format!("calling extern function `{}`", path)) diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 0a8112da2ab..1b86bcfa8c9 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -509,20 +509,18 @@ pub fn load_mir( instance: ty::InstanceDef<'tcx>, promoted: Option, ) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> { - // do not continue if typeck errors occurred (can only occur in local crate) let def = instance.with_opt_param(); - if let Some(def) = def.as_local() { - if self.tcx.has_typeck_results(def.did) { - if let Some(error_reported) = self.tcx.typeck_opt_const_arg(def).tainted_by_errors { - throw_inval!(AlreadyReported(error_reported)) - } - } - } trace!("load mir(instance={:?}, promoted={:?})", instance, promoted); - if let Some(promoted) = promoted { - return Ok(&self.tcx.promoted_mir_opt_const_arg(def)[promoted]); + let body = if let Some(promoted) = promoted { + &self.tcx.promoted_mir_opt_const_arg(def)[promoted] + } else { + M::load_mir(self, instance)? + }; + // do not continue if typeck errors occurred (can only occur in local crate) + if let Some(err) = body.tainted_by_errors { + throw_inval!(AlreadyReported(err)); } - M::load_mir(self, instance) + Ok(body) } /// Call this on things you got out of the MIR (so it is as generic as the current diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 6799514a449..12a8b8c6d77 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -120,7 +120,7 @@ pub fn has_mut_interior( fn in_return_place( &mut self, ccx: &'mir ConstCx<'mir, 'tcx>, - error_occured: Option, + tainted_by_errors: Option, ) -> ConstQualifs { // Find the `Return` terminator if one exists. // @@ -134,7 +134,9 @@ fn in_return_place( .map(|(bb, _)| bb); let return_block = match return_block { - None => return qualifs::in_any_value_of_ty(ccx, ccx.body.return_ty(), error_occured), + None => { + return qualifs::in_any_value_of_ty(ccx, ccx.body.return_ty(), tainted_by_errors); + } Some(bb) => bb, }; @@ -166,7 +168,7 @@ fn in_return_place( needs_non_const_drop: self.needs_non_const_drop(ccx, RETURN_PLACE, return_loc), has_mut_interior: self.has_mut_interior(ccx, RETURN_PLACE, return_loc), custom_eq, - error_occured, + tainted_by_errors, } } } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index 91610b15eb9..c3fa98b000f 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -17,14 +17,14 @@ pub fn in_any_value_of_ty<'tcx>( cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>, - error_occured: Option, + tainted_by_errors: Option, ) -> ConstQualifs { ConstQualifs { has_mut_interior: HasMutInterior::in_any_value_of_ty(cx, ty), needs_drop: NeedsDrop::in_any_value_of_ty(cx, ty), needs_non_const_drop: NeedsNonConstDrop::in_any_value_of_ty(cx, ty), custom_eq: CustomEq::in_any_value_of_ty(cx, ty), - error_occured, + tainted_by_errors, } } diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index ac282a5ecc8..92d1f5bceef 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -974,6 +974,7 @@ pub fn promote_candidates<'tcx>( vec![], body.span, body.generator_kind(), + body.tainted_by_errors, ); let promoter = Promoter { diff --git a/compiler/rustc_data_structures/src/sip128.rs b/compiler/rustc_data_structures/src/sip128.rs index 53062b9c20d..6e5c0617bf3 100644 --- a/compiler/rustc_data_structures/src/sip128.rs +++ b/compiler/rustc_data_structures/src/sip128.rs @@ -202,28 +202,26 @@ pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher128 { hasher } - // A specialized write function for values with size <= 8. #[inline] - fn short_write(&mut self, x: T) { - let size = mem::size_of::(); + pub fn short_write(&mut self, bytes: [u8; LEN]) { let nbuf = self.nbuf; - debug_assert!(size <= 8); + debug_assert!(LEN <= 8); debug_assert!(nbuf < BUFFER_SIZE); - debug_assert!(nbuf + size < BUFFER_WITH_SPILL_SIZE); + debug_assert!(nbuf + LEN < BUFFER_WITH_SPILL_SIZE); - if nbuf + size < BUFFER_SIZE { + if nbuf + LEN < BUFFER_SIZE { unsafe { // The memcpy call is optimized away because the size is known. let dst = (self.buf.as_mut_ptr() as *mut u8).add(nbuf); - ptr::copy_nonoverlapping(&x as *const _ as *const u8, dst, size); + ptr::copy_nonoverlapping(bytes.as_ptr(), dst, LEN); } - self.nbuf = nbuf + size; + self.nbuf = nbuf + LEN; return; } - unsafe { self.short_write_process_buffer(x) } + unsafe { self.short_write_process_buffer(bytes) } } // A specialized write function for values with size <= 8 that should only @@ -233,18 +231,17 @@ fn short_write(&mut self, x: T) { // `self.nbuf` must cause `self.buf` to become fully initialized (and not // overflow) if it wasn't already. #[inline(never)] - unsafe fn short_write_process_buffer(&mut self, x: T) { - let size = mem::size_of::(); + unsafe fn short_write_process_buffer(&mut self, bytes: [u8; LEN]) { let nbuf = self.nbuf; - debug_assert!(size <= 8); + debug_assert!(LEN <= 8); debug_assert!(nbuf < BUFFER_SIZE); - debug_assert!(nbuf + size >= BUFFER_SIZE); - debug_assert!(nbuf + size < BUFFER_WITH_SPILL_SIZE); + debug_assert!(nbuf + LEN >= BUFFER_SIZE); + debug_assert!(nbuf + LEN < BUFFER_WITH_SPILL_SIZE); // Copy first part of input into end of buffer, possibly into spill // element. The memcpy call is optimized away because the size is known. let dst = (self.buf.as_mut_ptr() as *mut u8).add(nbuf); - ptr::copy_nonoverlapping(&x as *const _ as *const u8, dst, size); + ptr::copy_nonoverlapping(bytes.as_ptr(), dst, LEN); // Process buffer. for i in 0..BUFFER_CAPACITY { @@ -254,17 +251,17 @@ unsafe fn short_write_process_buffer(&mut self, x: T) { self.state.v0 ^= elem; } - // Copy remaining input into start of buffer by copying size - 1 - // elements from spill (at most size - 1 bytes could have overflowed + // Copy remaining input into start of buffer by copying LEN - 1 + // elements from spill (at most LEN - 1 bytes could have overflowed // into the spill). The memcpy call is optimized away because the size - // is known. And the whole copy is optimized away for size == 1. + // is known. And the whole copy is optimized away for LEN == 1. let src = self.buf.get_unchecked(BUFFER_SPILL_INDEX) as *const _ as *const u8; - ptr::copy_nonoverlapping(src, self.buf.as_mut_ptr() as *mut u8, size - 1); + ptr::copy_nonoverlapping(src, self.buf.as_mut_ptr() as *mut u8, LEN - 1); // This function should only be called when the write fills the buffer. - // Therefore, when size == 1, the new `self.nbuf` must be zero. The size - // is statically known, so the branch is optimized away. - self.nbuf = if size == 1 { 0 } else { nbuf + size - BUFFER_SIZE }; + // Therefore, when LEN == 1, the new `self.nbuf` must be zero. + // LEN is statically known, so the branch is optimized away. + self.nbuf = if LEN == 1 { 0 } else { nbuf + LEN - BUFFER_SIZE }; self.processed += BUFFER_SIZE; } @@ -412,52 +409,52 @@ pub fn finish128(mut self) -> (u64, u64) { impl Hasher for SipHasher128 { #[inline] fn write_u8(&mut self, i: u8) { - self.short_write(i); + self.short_write(i.to_ne_bytes()); } #[inline] fn write_u16(&mut self, i: u16) { - self.short_write(i); + self.short_write(i.to_ne_bytes()); } #[inline] fn write_u32(&mut self, i: u32) { - self.short_write(i); + self.short_write(i.to_ne_bytes()); } #[inline] fn write_u64(&mut self, i: u64) { - self.short_write(i); + self.short_write(i.to_ne_bytes()); } #[inline] fn write_usize(&mut self, i: usize) { - self.short_write(i); + self.short_write(i.to_ne_bytes()); } #[inline] fn write_i8(&mut self, i: i8) { - self.short_write(i as u8); + self.short_write((i as u8).to_ne_bytes()); } #[inline] fn write_i16(&mut self, i: i16) { - self.short_write(i as u16); + self.short_write((i as u16).to_ne_bytes()); } #[inline] fn write_i32(&mut self, i: i32) { - self.short_write(i as u32); + self.short_write((i as u32).to_ne_bytes()); } #[inline] fn write_i64(&mut self, i: i64) { - self.short_write(i as u64); + self.short_write((i as u64).to_ne_bytes()); } #[inline] fn write_isize(&mut self, i: isize) { - self.short_write(i as usize); + self.short_write((i as usize).to_ne_bytes()); } #[inline] diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs index a121bbcedc8..31d6a42cf28 100644 --- a/compiler/rustc_data_structures/src/stable_hasher.rs +++ b/compiler/rustc_data_structures/src/stable_hasher.rs @@ -80,22 +80,22 @@ fn write_u8(&mut self, i: u8) { #[inline] fn write_u16(&mut self, i: u16) { - self.state.write_u16(i.to_le()); + self.state.short_write(i.to_le_bytes()); } #[inline] fn write_u32(&mut self, i: u32) { - self.state.write_u32(i.to_le()); + self.state.short_write(i.to_le_bytes()); } #[inline] fn write_u64(&mut self, i: u64) { - self.state.write_u64(i.to_le()); + self.state.short_write(i.to_le_bytes()); } #[inline] fn write_u128(&mut self, i: u128) { - self.state.write_u128(i.to_le()); + self.state.write(&i.to_le_bytes()); } #[inline] @@ -103,7 +103,7 @@ fn write_usize(&mut self, i: usize) { // Always treat usize as u64 so we get the same results on 32 and 64 bit // platforms. This is important for symbol hashes when cross compiling, // for example. - self.state.write_u64((i as u64).to_le()); + self.state.short_write((i as u64).to_le_bytes()); } #[inline] @@ -113,22 +113,22 @@ fn write_i8(&mut self, i: i8) { #[inline] fn write_i16(&mut self, i: i16) { - self.state.write_i16(i.to_le()); + self.state.short_write((i as u16).to_le_bytes()); } #[inline] fn write_i32(&mut self, i: i32) { - self.state.write_i32(i.to_le()); + self.state.short_write((i as u32).to_le_bytes()); } #[inline] fn write_i64(&mut self, i: i64) { - self.state.write_i64(i.to_le()); + self.state.short_write((i as u64).to_le_bytes()); } #[inline] fn write_i128(&mut self, i: i128) { - self.state.write_i128(i.to_le()); + self.state.write(&(i as u128).to_le_bytes()); } #[inline] @@ -144,7 +144,7 @@ fn write_isize(&mut self, i: isize) { #[inline(never)] fn hash_value(state: &mut SipHasher128, value: u64) { state.write_u8(0xFF); - state.write_u64(value.to_le()); + state.short_write(value.to_le_bytes()); } // `isize` values often seem to have a small (positive) numeric value in practice. @@ -161,10 +161,6 @@ fn hash_value(state: &mut SipHasher128, value: u64) { // 8 bytes. Since this prefix cannot occur when we hash a single byte, when we hash two // `isize`s that fit within a different amount of bytes, they should always produce a different // byte stream for the hasher. - // - // To ensure that this optimization hashes the exact same bytes on both little-endian and - // big-endian architectures, we compare the value with 0xFF before we convert the number - // into a unified representation (little-endian). if value < 0xFF { self.state.write_u8(value as u8); } else { diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index c401f65edda..a72681dbf4e 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -97,6 +97,7 @@ E0185: include_str!("./error_codes/E0185.md"), E0186: include_str!("./error_codes/E0186.md"), E0191: include_str!("./error_codes/E0191.md"), +E0192: include_str!("./error_codes/E0192.md"), E0193: include_str!("./error_codes/E0193.md"), E0195: include_str!("./error_codes/E0195.md"), E0197: include_str!("./error_codes/E0197.md"), @@ -522,7 +523,6 @@ // E0188, // can not cast an immutable reference to a mutable pointer // E0189, // deprecated: can only cast a boxed pointer to a boxed object // E0190, // deprecated: can only cast a &-pointer to an &-object -// E0192, // negative impl only applicable to auto traits // E0194, // merged into E0403 // E0196, // cannot determine a type for this closure E0208, diff --git a/compiler/rustc_error_codes/src/error_codes/E0192.md b/compiler/rustc_error_codes/src/error_codes/E0192.md index 5fd951b2e86..deca042a91a 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0192.md +++ b/compiler/rustc_error_codes/src/error_codes/E0192.md @@ -1,15 +1,17 @@ +#### Note: this error code is no longer emitted by the compiler. + A negative impl was added on a trait implementation. Erroneous code example: -```compile_fail,E0192 +```compile_fail trait Trait { type Bar; } struct Foo; -impl !Trait for Foo { } //~ ERROR E0192 +impl !Trait for Foo { } //~ ERROR fn main() {} ``` diff --git a/compiler/rustc_hir/src/itemlikevisit.rs b/compiler/rustc_hir/src/itemlikevisit.rs index 0db562f91a6..db70002c2d6 100644 --- a/compiler/rustc_hir/src/itemlikevisit.rs +++ b/compiler/rustc_hir/src/itemlikevisit.rs @@ -8,7 +8,7 @@ /// /// 1. **Shallow visit**: Get a simple callback for every item (or item-like thing) in the HIR. /// - Example: find all items with a `#[foo]` attribute on them. -/// - How: Implement `ItemLikeVisitor` and call `tcx.hir().krate().visit_all_item_likes()`. +/// - How: Implement `ItemLikeVisitor` and call `tcx.hir().visit_all_item_likes()`. /// - Pro: Efficient; just walks the lists of item-like things, not the nodes themselves. /// - Con: Don't get information about nesting /// - Con: Don't have methods for specific bits of HIR, like "on @@ -19,9 +19,9 @@ /// - Example: Examine each expression to look for its type and do some check or other. /// - How: Implement `intravisit::Visitor` and override the `nested_visit_map()` method /// to return `NestedVisitorMap::OnlyBodies` and use -/// `tcx.hir().krate().visit_all_item_likes(&mut visitor.as_deep_visitor())`. Within -/// your `intravisit::Visitor` impl, implement methods like `visit_expr()` (don't forget -/// to invoke `intravisit::walk_expr()` to keep walking the subparts). +/// `tcx.hir().visit_all_item_likes(&mut visitor.as_deep_visitor())`. Within your +/// `intravisit::Visitor` impl, implement methods like `visit_expr()` (don't forget to invoke +/// `intravisit::walk_expr()` to keep walking the subparts). /// - Pro: Visitor methods for any kind of HIR node, not just item-like things. /// - Pro: Integrates well into dependency tracking. /// - Con: Don't get information about nesting between items diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index f5a4e11de16..66e1e78b285 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -286,8 +286,7 @@ pub fn configure_and_expand( rustc_builtin_macros::register_builtin_macros(resolver); krate = sess.time("crate_injection", || { - let alt_std_name = sess.opts.alt_std_name.as_ref().map(|s| Symbol::intern(s)); - rustc_builtin_macros::standard_library_imports::inject(krate, resolver, sess, alt_std_name) + rustc_builtin_macros::standard_library_imports::inject(krate, resolver, sess) }); util::check_attr_crate_type(sess, &krate.attrs, &mut resolver.lint_buffer()); diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 6d9183eda9d..f74cadfebac 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -118,7 +118,7 @@ fn get_stack_size() -> Option { /// Like a `thread::Builder::spawn` followed by a `join()`, but avoids the need /// for `'static` bounds. #[cfg(not(parallel_compiler))] -pub fn scoped_thread R + Send, R: Send>(cfg: thread::Builder, f: F) -> R { +fn scoped_thread R + Send, R: Send>(cfg: thread::Builder, f: F) -> R { // SAFETY: join() is called immediately, so any closure captures are still // alive. match unsafe { cfg.spawn_unchecked(f) }.unwrap().join() { @@ -379,7 +379,7 @@ fn current_dll_path() -> Option { } } -pub fn get_codegen_sysroot(maybe_sysroot: &Option, backend_name: &str) -> MakeBackendFn { +fn get_codegen_sysroot(maybe_sysroot: &Option, backend_name: &str) -> MakeBackendFn { // For now we only allow this function to be called once as it'll dlopen a // few things, which seems to work best if we only do that once. In // general this assertion never trips due to the once guard in `get_codegen_backend`, diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 33fb1e570b1..0688d7d2569 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -13,6 +13,7 @@ use crate::ty::{self, List, Ty, TyCtxt}; use crate::ty::{AdtDef, InstanceDef, Region, ScalarInt, UserTypeAnnotationIndex}; +use rustc_errors::ErrorReported; use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_hir::{self, GeneratorKind}; @@ -284,6 +285,8 @@ pub struct Body<'tcx> { predecessor_cache: PredecessorCache, is_cyclic: GraphIsCyclicCache, + + pub tainted_by_errors: Option, } impl<'tcx> Body<'tcx> { @@ -297,6 +300,7 @@ pub fn new( var_debug_info: Vec>, span: Span, generator_kind: Option, + tainted_by_errors: Option, ) -> Self { // We need `arg_count` locals, and one for the return place. assert!( @@ -329,6 +333,7 @@ pub fn new( is_polymorphic: false, predecessor_cache: PredecessorCache::new(), is_cyclic: GraphIsCyclicCache::new(), + tainted_by_errors, }; body.is_polymorphic = body.has_param_types_or_consts(); body @@ -356,6 +361,7 @@ pub fn new_cfg_only(basic_blocks: IndexVec>) -> is_polymorphic: false, predecessor_cache: PredecessorCache::new(), is_cyclic: GraphIsCyclicCache::new(), + tainted_by_errors: None, }; body.is_polymorphic = body.has_param_types_or_consts(); body diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 4b8eb3fbd96..6e2b060e7dd 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -214,6 +214,7 @@ pub struct BorrowCheckResult<'tcx> { pub concrete_opaque_types: VecMap, Ty<'tcx>>, pub closure_requirements: Option>, pub used_mut_upvars: SmallVec<[Field; 8]>, + pub tainted_by_errors: Option, } /// The result of the `mir_const_qualif` query. @@ -227,7 +228,7 @@ pub struct ConstQualifs { pub needs_drop: bool, pub needs_non_const_drop: bool, pub custom_eq: bool, - pub error_occured: Option, + pub tainted_by_errors: Option, } /// After we borrow check a closure, we are left with various diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index a119655a90b..4a3efb5c1b8 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -8,7 +8,9 @@ use crate::middle::resolve_lifetime::{self, LifetimeScopeForPath}; use crate::middle::stability; use crate::mir::interpret::{self, Allocation, ConstValue, Scalar}; -use crate::mir::{Body, Field, Local, Place, PlaceElem, ProjectionKind, Promoted}; +use crate::mir::{ + Body, BorrowCheckResult, Field, Local, Place, PlaceElem, ProjectionKind, Promoted, +}; use crate::thir::Thir; use crate::traits; use crate::ty::query::{self, TyCtxtAt}; @@ -1061,6 +1063,17 @@ pub fn typeck_opt_const_arg( } } + pub fn mir_borrowck_opt_const_arg( + self, + def: ty::WithOptConstParam, + ) -> &'tcx BorrowCheckResult<'tcx> { + if let Some(param_did) = def.const_param_did { + self.mir_borrowck_const_arg((def.did, param_did)) + } else { + self.mir_borrowck(def.did) + } + } + pub fn alloc_steal_thir(self, thir: Thir<'tcx>) -> &'tcx Steal> { self.arena.alloc(Steal::new(thir)) } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 1c5bc7860db..39efc006d9d 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -253,6 +253,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { crate::ty::UniverseIndex, crate::ty::Variance, ::rustc_span::Span, + ::rustc_errors::ErrorReported, } /////////////////////////////////////////////////////////////////////////// diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 88d994e32fe..10807d43276 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -104,8 +104,8 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> Body<'_ let span_with_body = span_with_body.unwrap_or_else(|| tcx.hir().span(id)); tcx.infer_ctxt().enter(|infcx| { - let body = if let Some(ErrorReported) = typeck_results.tainted_by_errors { - build::construct_error(&infcx, def, id, body_id, body_owner_kind) + let body = if let Some(error_reported) = typeck_results.tainted_by_errors { + build::construct_error(&infcx, def, id, body_id, body_owner_kind, error_reported) } else if body_owner_kind.is_fn_or_closure() { // fetch the fully liberated fn signature (that is, all bound // types/lifetimes replaced) @@ -715,6 +715,7 @@ fn construct_error<'a, 'tcx>( hir_id: hir::HirId, body_id: hir::BodyId, body_owner_kind: hir::BodyOwnerKind, + err: ErrorReported, ) -> Body<'tcx> { let tcx = infcx.tcx; let span = tcx.hir().span(hir_id); @@ -769,6 +770,7 @@ fn construct_error<'a, 'tcx>( vec![], span, generator_kind, + Some(err), ); body.generator.as_mut().map(|gen| gen.yield_ty = Some(ty)); body @@ -857,6 +859,7 @@ fn finish(self) -> Body<'tcx> { self.var_debug_info, self.fn_span, self.generator_kind, + self.typeck_results.tainted_by_errors, ) } diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index 98de64cd97c..0d314a109ba 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -145,6 +145,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { Default::default(), body.span, body.generator_kind(), + body.tainted_by_errors, ); // FIXME(oli-obk, eddyb) Optimize locals (or even local paths) to hold diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 991d10a8547..e7d5bab8fd9 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -252,8 +252,11 @@ fn mir_promoted<'tcx>( // Ensure that we compute the `mir_const_qualif` for constants at // this point, before we steal the mir-const result. // Also this means promotion can rely on all const checks having been done. - let _ = tcx.mir_const_qualif_opt_const_arg(def); + let const_qualifs = tcx.mir_const_qualif_opt_const_arg(def); let mut body = tcx.mir_const(def).steal(); + if let Some(error_reported) = const_qualifs.tainted_by_errors { + body.tainted_by_errors = Some(error_reported); + } let mut required_consts = Vec::new(); let mut required_consts_visitor = RequiredConstsVisitor::new(&mut required_consts); @@ -358,13 +361,7 @@ fn mir_drops_elaborated_and_const_checked<'tcx>( return tcx.mir_drops_elaborated_and_const_checked(def); } - // (Mir-)Borrowck uses `mir_promoted`, so we have to force it to - // execute before we can steal. - if let Some(param_did) = def.const_param_did { - tcx.ensure().mir_borrowck_const_arg((def.did, param_did)); - } else { - tcx.ensure().mir_borrowck(def.did); - } + let mir_borrowck = tcx.mir_borrowck_opt_const_arg(def); let is_fn_like = tcx.hir().get_by_def_id(def.did).fn_kind().is_some(); if is_fn_like { @@ -379,6 +376,9 @@ fn mir_drops_elaborated_and_const_checked<'tcx>( let (body, _) = tcx.mir_promoted(def); let mut body = body.steal(); + if let Some(error_reported) = mir_borrowck.tainted_by_errors { + body.tainted_by_errors = Some(error_reported); + } // IMPORTANT pm::run_passes(tcx, &mut body, &[&remove_false_edges::RemoveFalseEdges]); @@ -544,15 +544,13 @@ fn promoted_mir<'tcx>( return tcx.arena.alloc(IndexVec::new()); } - if let Some(param_did) = def.const_param_did { - tcx.ensure().mir_borrowck_const_arg((def.did, param_did)); - } else { - tcx.ensure().mir_borrowck(def.did); - } - let (_, promoted) = tcx.mir_promoted(def); - let mut promoted = promoted.steal(); + let tainted_by_errors = tcx.mir_borrowck_opt_const_arg(def).tainted_by_errors; + let mut promoted = tcx.mir_promoted(def).1.steal(); for body in &mut promoted { + if let Some(error_reported) = tainted_by_errors { + body.tainted_by_errors = Some(error_reported); + } run_post_borrowck_cleanup_passes(tcx, body); } diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 919171db39e..a4927c467cf 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -235,6 +235,8 @@ fn new_body<'tcx>( vec![], span, None, + // FIXME(compiler-errors): is this correct? + None, ) } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 4898a4844b9..e9aa4adcaf7 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1457,9 +1457,9 @@ fn parse_labeled_expr( } else if self.check(&token::OpenDelim(token::Brace)) || self.token.is_whole_block() { self.parse_block_expr(label, lo, BlockCheckMode::Default, attrs) } else if !ate_colon && (self.check(&TokenKind::Comma) || self.check(&TokenKind::Gt)) { - // We're probably inside of a `Path<'a>` that needs a turbofish, so suppress the - // "must be followed by a colon" error, and the "expected one of" error. - self.diagnostic().delay_span_bug(lo, "this label wasn't parsed correctly"); + // We're probably inside of a `Path<'a>` that needs a turbofish + let msg = "expected `while`, `for`, `loop` or `{` after a label"; + self.struct_span_err(self.token.span, msg).span_label(self.token.span, msg).emit(); consume_colon = false; Ok(self.mk_expr_err(lo)) } else { diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index c7edcb077b9..1f657218a64 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -453,28 +453,28 @@ impl<'a> Resolver<'a> { // edit: // only do this if the const and usage of the non-constant value are on the same line // the further the two are apart, the higher the chance of the suggestion being wrong - // also make sure that the pos for the suggestion is not 0 (ICE #90878) - let sp = - self.session.source_map().span_extend_to_prev_str(ident.span, current, true); - - let pos_for_suggestion = sp.lo().0.saturating_sub(current.len() as u32); + let sp = self + .session + .source_map() + .span_extend_to_prev_str(ident.span, current, true, false); - if sp.lo().0 == 0 - || pos_for_suggestion == 0 - || self.session.source_map().is_multiline(sp) - { - err.span_label(ident.span, &format!("this would need to be a `{}`", sugg)); - } else { - let sp = sp.with_lo(BytePos(pos_for_suggestion)); - err.span_suggestion( - sp, - &format!("consider using `{}` instead of `{}`", sugg, current), - format!("{} {}", sugg, ident), - Applicability::MaybeIncorrect, - ); - err.span_label(span, "non-constant value"); + match sp { + Some(sp) if !self.session.source_map().is_multiline(sp) => { + let sp = sp.with_lo(BytePos(sp.lo().0 - (current.len() as u32))); + err.span_suggestion( + sp, + &format!("consider using `{}` instead of `{}`", sugg, current), + format!("{} {}", sugg, ident), + Applicability::MaybeIncorrect, + ); + err.span_label(span, "non-constant value"); + } + _ => { + err.span_label(ident.span, &format!("this would need to be a `{}`", sugg)); + } } + err } ResolutionError::BindingShadowsSomethingUnacceptable { diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 8630ffec241..79962d5db89 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -770,7 +770,6 @@ fn default() -> Options { externs: Externs(BTreeMap::new()), extern_dep_specs: ExternDepSpecs(BTreeMap::new()), crate_name: None, - alt_std_name: None, libs: Vec::new(), unstable_features: UnstableFeatures::Disallow, debug_assertions: true, @@ -2382,7 +2381,6 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { unstable_features: UnstableFeatures::from_environment(crate_name.as_deref()), extern_dep_specs, crate_name, - alt_std_name: None, libs, debug_assertions, actually_rustdoc: false, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 550da9e0580..ae1b638c344 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -184,10 +184,6 @@ pub struct Options { externs: Externs [UNTRACKED], extern_dep_specs: ExternDepSpecs [UNTRACKED], crate_name: Option [TRACKED], - /// An optional name to use as the crate for std during std injection, - /// written `extern crate name as std`. Defaults to `std`. Used by - /// out-of-tree drivers. - alt_std_name: Option [TRACKED], /// Indicates how the compiler should treat unstable features. unstable_features: UnstableFeatures [TRACKED], diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index 7414d201f51..95177102dcf 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -629,26 +629,41 @@ pub fn span_extend_to_prev_char(&self, sp: Span, c: char, accept_newlines: bool) } /// Extends the given `Span` to just after the previous occurrence of `pat` when surrounded by - /// whitespace. Returns the same span if no character could be found or if an error occurred - /// while retrieving the code snippet. - pub fn span_extend_to_prev_str(&self, sp: Span, pat: &str, accept_newlines: bool) -> Span { + /// whitespace. Returns None if the pattern could not be found or if an error occurred while + /// retrieving the code snippet. + pub fn span_extend_to_prev_str( + &self, + sp: Span, + pat: &str, + accept_newlines: bool, + include_whitespace: bool, + ) -> Option { // assure that the pattern is delimited, to avoid the following // fn my_fn() // ^^^^ returned span without the check // ---------- correct span + let prev_source = self.span_to_prev_source(sp).ok()?; for ws in &[" ", "\t", "\n"] { let pat = pat.to_owned() + ws; - if let Ok(prev_source) = self.span_to_prev_source(sp) { - let prev_source = prev_source.rsplit(&pat).next().unwrap_or("").trim_start(); - if prev_source.is_empty() && sp.lo().0 != 0 { - return sp.with_lo(BytePos(sp.lo().0 - 1)); - } else if accept_newlines || !prev_source.contains('\n') { - return sp.with_lo(BytePos(sp.lo().0 - prev_source.len() as u32)); + if let Some(pat_pos) = prev_source.rfind(&pat) { + let just_after_pat_pos = pat_pos + pat.len() - 1; + let just_after_pat_plus_ws = if include_whitespace { + just_after_pat_pos + + prev_source[just_after_pat_pos..] + .find(|c: char| !c.is_whitespace()) + .unwrap_or(0) + } else { + just_after_pat_pos + }; + let len = prev_source.len() - just_after_pat_plus_ws; + let prev_source = &prev_source[just_after_pat_plus_ws..]; + if accept_newlines || !prev_source.trim_start().contains('\n') { + return Some(sp.with_lo(BytePos(sp.lo().0 - len as u32))); } } } - sp + None } /// Returns the source snippet as `String` after the given `Span`. @@ -927,7 +942,7 @@ pub fn count_lines(&self) -> usize { } pub fn generate_fn_name_span(&self, span: Span) -> Option { - let prev_span = self.span_extend_to_prev_str(span, "fn", true); + let prev_span = self.span_extend_to_prev_str(span, "fn", true, true).unwrap_or(span); if let Ok(snippet) = self.span_to_snippet(prev_span) { debug!( "generate_fn_name_span: span={:?}, prev_span={:?}, snippet={:?}", @@ -968,8 +983,7 @@ pub fn generate_fn_name_span(&self, span: Span) -> Option { pub fn generate_local_type_param_snippet(&self, span: Span) -> Option<(Span, String)> { // Try to extend the span to the previous "fn" keyword to retrieve the function // signature. - let sugg_span = self.span_extend_to_prev_str(span, "fn", false); - if sugg_span != span { + if let Some(sugg_span) = self.span_extend_to_prev_str(span, "fn", false, true) { if let Ok(snippet) = self.span_to_snippet(sugg_span) { // Consume the function name. let mut offset = snippet diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index a17553b920f..8aa22852a6f 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -1819,7 +1819,7 @@ fn suggest_traits_to_import( [] => {} [trait_info] => { let msg = format!( - "the trait `{}` defines an item `{}`, but is explicitely unimplemented", + "the trait `{}` defines an item `{}`, but is explicitly unimplemented", self.tcx.def_path_str(trait_info.def_id), item_name ); @@ -1827,7 +1827,7 @@ fn suggest_traits_to_import( } trait_infos => { let mut msg = format!( - "the following traits define an item `{}`, but are explicitely unimplemented:", + "the following traits define an item `{}`, but are explicitly unimplemented:", item_name ); for trait_info in trait_infos { diff --git a/library/std/src/env.rs b/library/std/src/env.rs index c06928647d3..5ed9fa9d6f0 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -23,6 +23,11 @@ /// Returns the current working directory as a [`PathBuf`]. /// +/// # Platform-specific behavior +/// +/// This function currently corresponds to the `getcwd` function on Unix +/// and the `GetCurrentDirectoryW` function on Windows. +/// /// # Errors /// /// Returns an [`Err`] if the current working directory value is invalid. @@ -49,6 +54,11 @@ pub fn current_dir() -> io::Result { /// Changes the current working directory to the specified path. /// +/// # Platform-specific behavior +/// +/// This function currently corresponds to the `chdir` function on Unix +/// and the `SetCurrentDirectoryW` function on Windows. +/// /// Returns an [`Err`] if the operation fails. /// /// # Examples diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 4b55324a242..1aa6d657889 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -296,12 +296,11 @@ pub enum ErrorKind { /// The filesystem does not support making so many hardlinks to the same file. #[unstable(feature = "io_error_more", issue = "86442")] TooManyLinks, - /// Filename too long. + /// A filename was invalid. /// - /// The limit might be from the underlying filesystem or API, or an administratively imposed - /// resource limit. + /// This error can also cause if it exceeded the filename length limit. #[unstable(feature = "io_error_more", issue = "86442")] - FilenameTooLong, + InvalidFilename, /// Program argument list too long. /// /// When trying to run an external program, a system or process limit on the size of the @@ -382,12 +381,12 @@ pub(crate) fn as_str(&self) -> &'static str { DirectoryNotEmpty => "directory not empty", ExecutableFileBusy => "executable file busy", FileTooLarge => "file too large", - FilenameTooLong => "filename too long", FilesystemLoop => "filesystem loop or indirection limit (e.g. symlink loop)", FilesystemQuotaExceeded => "filesystem quota exceeded", HostUnreachable => "host unreachable", Interrupted => "operation interrupted", InvalidData => "invalid data", + InvalidFilename => "invalid filename", InvalidInput => "invalid input parameter", IsADirectory => "is a directory", NetworkDown => "network down", diff --git a/library/std/src/io/error/repr_bitpacked.rs b/library/std/src/io/error/repr_bitpacked.rs index f317368e8e5..4301e941b3d 100644 --- a/library/std/src/io/error/repr_bitpacked.rs +++ b/library/std/src/io/error/repr_bitpacked.rs @@ -315,7 +315,7 @@ macro_rules! from_prim { Deadlock, CrossesDevices, TooManyLinks, - FilenameTooLong, + InvalidFilename, ArgumentListTooLong, Interrupted, Other, diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 2aae29f2154..82f0291decb 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -546,13 +546,14 @@ pub mod arch { #[doc(no_inline)] // Note (#82861): required for correct documentation pub use core::arch::*; + #[stable(feature = "simd_aarch64", since = "1.60.0")] + pub use std_detect::is_aarch64_feature_detected; #[stable(feature = "simd_x86", since = "1.27.0")] pub use std_detect::is_x86_feature_detected; #[unstable(feature = "stdsimd", issue = "48556")] pub use std_detect::{ - is_aarch64_feature_detected, is_arm_feature_detected, is_mips64_feature_detected, - is_mips_feature_detected, is_powerpc64_feature_detected, is_powerpc_feature_detected, - is_riscv_feature_detected, + is_arm_feature_detected, is_mips64_feature_detected, is_mips_feature_detected, + is_powerpc64_feature_detected, is_powerpc_feature_detected, is_riscv_feature_detected, }; } diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index b53c3e79b0f..71c660e7186 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -200,6 +200,22 @@ pub trait AsFd { fn as_fd(&self) -> BorrowedFd<'_>; } +#[unstable(feature = "io_safety", issue = "87074")] +impl AsFd for &T { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + T::as_fd(self) + } +} + +#[unstable(feature = "io_safety", issue = "87074")] +impl AsFd for &mut T { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + T::as_fd(self) + } +} + #[unstable(feature = "io_safety", issue = "87074")] impl AsFd for BorrowedFd<'_> { #[inline] diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs index db7edcd0574..75d65e6d5fc 100644 --- a/library/std/src/os/unix/fs.rs +++ b/library/std/src/os/unix/fs.rs @@ -966,7 +966,7 @@ pub fn chown>(dir: P, uid: Option, gid: Option) -> io:: /// /// fn main() -> std::io::Result<()> { /// let f = std::fs::File::open("/file")?; -/// fs::fchown(f, Some(0), Some(0))?; +/// fs::fchown(&f, Some(0), Some(0))?; /// Ok(()) /// } /// ``` diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs index e37ce633a12..8df6c54a414 100644 --- a/library/std/src/os/windows/io/handle.rs +++ b/library/std/src/os/windows/io/handle.rs @@ -316,6 +316,22 @@ pub trait AsHandle { fn as_handle(&self) -> BorrowedHandle<'_>; } +#[unstable(feature = "io_safety", issue = "87074")] +impl AsHandle for &T { + #[inline] + fn as_handle(&self) -> BorrowedHandle<'_> { + T::as_handle(self) + } +} + +#[unstable(feature = "io_safety", issue = "87074")] +impl AsHandle for &mut T { + #[inline] + fn as_handle(&self) -> BorrowedHandle<'_> { + T::as_handle(self) + } +} + impl AsHandle for BorrowedHandle<'_> { #[inline] fn as_handle(&self) -> BorrowedHandle<'_> { diff --git a/library/std/src/os/windows/io/socket.rs b/library/std/src/os/windows/io/socket.rs index d3a5b6dcc76..2f13eb77a1b 100644 --- a/library/std/src/os/windows/io/socket.rs +++ b/library/std/src/os/windows/io/socket.rs @@ -210,6 +210,22 @@ pub trait AsSocket { fn as_socket(&self) -> BorrowedSocket<'_>; } +#[unstable(feature = "io_safety", issue = "87074")] +impl AsSocket for &T { + #[inline] + fn as_socket(&self) -> BorrowedSocket<'_> { + T::as_socket(self) + } +} + +#[unstable(feature = "io_safety", issue = "87074")] +impl AsSocket for &mut T { + #[inline] + fn as_socket(&self) -> BorrowedSocket<'_> { + T::as_socket(self) + } +} + impl AsSocket for BorrowedSocket<'_> { #[inline] fn as_socket(&self) -> BorrowedSocket<'_> { diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 85cad65da6a..551b66891c9 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -2922,12 +2922,12 @@ fn eq(&self, other: &Path) -> bool { impl Hash for Path { fn hash(&self, h: &mut H) { let bytes = self.as_u8_slice(); - let prefix_len = match parse_prefix(&self.inner) { + let (prefix_len, verbatim) = match parse_prefix(&self.inner) { Some(prefix) => { prefix.hash(h); - prefix.len() + (prefix.len(), prefix.is_verbatim()) } - None => 0, + None => (0, false), }; let bytes = &bytes[prefix_len..]; @@ -2935,7 +2935,8 @@ fn hash(&self, h: &mut H) { let mut bytes_hashed = 0; for i in 0..bytes.len() { - if is_sep_byte(bytes[i]) { + let is_sep = if verbatim { is_verbatim_sep(bytes[i]) } else { is_sep_byte(bytes[i]) }; + if is_sep { if i > component_start { let to_hash = &bytes[component_start..i]; h.write(to_hash); @@ -2943,11 +2944,18 @@ fn hash(&self, h: &mut H) { } // skip over separator and optionally a following CurDir item - // since components() would normalize these away - component_start = i + match bytes[i..] { - [_, b'.', b'/', ..] | [_, b'.'] => 2, - _ => 1, - }; + // since components() would normalize these away. + component_start = i + 1; + + let tail = &bytes[component_start..]; + + if !verbatim { + component_start += match tail { + [b'.'] => 1, + [b'.', sep @ _, ..] if is_sep_byte(*sep) => 1, + _ => 0, + }; + } } } diff --git a/library/std/src/path/tests.rs b/library/std/src/path/tests.rs index 2bf499e1ab8..0ab5956e1bc 100644 --- a/library/std/src/path/tests.rs +++ b/library/std/src/path/tests.rs @@ -1498,6 +1498,20 @@ macro_rules! tc ( relative_from: Some("") ); + tc!("foo/.", "foo", + eq: true, + starts_with: true, + ends_with: true, + relative_from: Some("") + ); + + tc!("foo/./bar", "foo/bar", + eq: true, + starts_with: true, + ends_with: true, + relative_from: Some("") + ); + tc!("foo/bar", "foo", eq: false, starts_with: true, @@ -1541,6 +1555,27 @@ macro_rules! tc ( ends_with: true, relative_from: Some("") ); + + tc!(r"C:\foo\.\bar.txt", r"C:\foo\bar.txt", + eq: true, + starts_with: true, + ends_with: true, + relative_from: Some("") + ); + + tc!(r"C:\foo\.", r"C:\foo", + eq: true, + starts_with: true, + ends_with: true, + relative_from: Some("") + ); + + tc!(r"\\?\C:\foo\.\bar.txt", r"\\?\C:\foo\bar.txt", + eq: false, + starts_with: false, + ends_with: false, + relative_from: None + ); } } diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs index 6382354eb6e..605cc499b3c 100644 --- a/library/std/src/sys/unix/mod.rs +++ b/library/std/src/sys/unix/mod.rs @@ -159,7 +159,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { libc::ENOSPC => StorageFull, libc::ENOSYS => Unsupported, libc::EMLINK => TooManyLinks, - libc::ENAMETOOLONG => FilenameTooLong, + libc::ENAMETOOLONG => InvalidFilename, libc::ENETDOWN => NetworkDown, libc::ENETUNREACH => NetworkUnreachable, libc::ENOTCONN => NotConnected, diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs index c70f254cf39..dc288176346 100644 --- a/library/std/src/sys/windows/mod.rs +++ b/library/std/src/sys/windows/mod.rs @@ -71,6 +71,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { c::ERROR_FILE_NOT_FOUND => return NotFound, c::ERROR_PATH_NOT_FOUND => return NotFound, c::ERROR_NO_DATA => return BrokenPipe, + c::ERROR_INVALID_NAME => return InvalidFilename, c::ERROR_INVALID_PARAMETER => return InvalidInput, c::ERROR_NOT_ENOUGH_MEMORY | c::ERROR_OUTOFMEMORY => return OutOfMemory, c::ERROR_SEM_TIMEOUT @@ -104,7 +105,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { c::ERROR_POSSIBLE_DEADLOCK => return Deadlock, c::ERROR_NOT_SAME_DEVICE => return CrossesDevices, c::ERROR_TOO_MANY_LINKS => return TooManyLinks, - c::ERROR_FILENAME_EXCED_RANGE => return FilenameTooLong, + c::ERROR_FILENAME_EXCED_RANGE => return InvalidFilename, _ => {} } diff --git a/library/std/tests/run-time-detect.rs b/library/std/tests/run-time-detect.rs index 14a9e3acca4..54873f5549b 100644 --- a/library/std/tests/run-time-detect.rs +++ b/library/std/tests/run-time-detect.rs @@ -3,10 +3,9 @@ #![cfg_attr( any( all(target_arch = "arm", any(target_os = "linux", target_os = "android")), - all(target_arch = "aarch64", any(target_os = "linux", target_os = "android")), + all(bootstrap, target_arch = "aarch64", any(target_os = "linux", target_os = "android")), all(target_arch = "powerpc", target_os = "linux"), all(target_arch = "powerpc64", target_os = "linux"), - any(target_arch = "x86", target_arch = "x86_64"), ), feature(stdsimd) )] @@ -46,7 +45,8 @@ fn aarch64_linux() { println!("flagm: {}", is_aarch64_feature_detected!("flagm")); println!("ssbs: {}", is_aarch64_feature_detected!("ssbs")); println!("sb: {}", is_aarch64_feature_detected!("sb")); - println!("pauth: {}", is_aarch64_feature_detected!("pauth")); + println!("paca: {}", is_aarch64_feature_detected!("paca")); + println!("pacg: {}", is_aarch64_feature_detected!("pacg")); println!("dpb: {}", is_aarch64_feature_detected!("dpb")); println!("dpb2: {}", is_aarch64_feature_detected!("dpb2")); println!("sve2: {}", is_aarch64_feature_detected!("sve2")); diff --git a/library/stdarch b/library/stdarch index eaee02ffdf5..863d31b8e13 160000 --- a/library/stdarch +++ b/library/stdarch @@ -1 +1 @@ -Subproject commit eaee02ffdf5d820729ccdf2f95fa08b08c7d24d2 +Subproject commit 863d31b8e1314e15d124384e5eaa9ab21e12bd79 diff --git a/src/test/pretty/use-tree.rs b/src/test/pretty/use-tree.rs new file mode 100644 index 00000000000..5da95235245 --- /dev/null +++ b/src/test/pretty/use-tree.rs @@ -0,0 +1,23 @@ +// pp-exact +// edition:2021 + +#![allow(unused_imports)] + +use ::std::fmt::{self, Debug, Display, Write as _}; + +use core::option::Option::*; + +use core::{ + cmp::{Eq, Ord, PartialEq, PartialOrd}, + convert::{AsMut, AsRef, From, Into}, + iter::{ + DoubleEndedIterator, ExactSizeIterator, Extend, FromIterator, + IntoIterator, Iterator, + }, + marker::{ + Copy as Copy, Send as Send, Sized as Sized, Sync as Sync, Unpin as U, + }, + ops::{*, Drop, Fn, FnMut, FnOnce}, +}; + +fn main() {} diff --git a/src/test/rustdoc-json/type/dyn.rs b/src/test/rustdoc-json/type/dyn.rs new file mode 100644 index 00000000000..f53dc03f4b4 --- /dev/null +++ b/src/test/rustdoc-json/type/dyn.rs @@ -0,0 +1,21 @@ +// ignore-tidy-linelength + +// @count dyn.json "$.index[*][?(@.name=='dyn')].inner.items" 1 +// @set sync_int_gen = - "$.index[*][?(@.name=='SyncIntGen')].id" +// @is - "$.index[*][?(@.name=='dyn')].inner.items[0]" $sync_int_gen + +// @is - "$.index[*][?(@.name=='SyncIntGen')].kind" \"typedef\" +// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.generics" '{"params": [], "where_predicates": []}' +// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.kind" \"resolved_path\" +// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.name" \"Box\" +// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.bindings" [] +// @count - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args" 1 +// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.kind" \"resolved_path\" +// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.kind" \"resolved_path\" +// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.name" \"Fn\" +// @count - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.param_names[*]" 3 +// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.param_names[0].trait_bound.trait.inner.name" \"Send\" +// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.param_names[1].trait_bound.trait.inner.name" \"Sync\" +// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.param_names[2]" "{\"outlives\": \"'static\"}" +// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.args" '{"parenthesized": {"inputs": [],"output": {"inner": "i32","kind": "primitive"}}}' +pub type SyncIntGen = Box i32 + Send + Sync + 'static>; diff --git a/src/test/rustdoc-json/type/fn_lifetime.rs b/src/test/rustdoc-json/type/fn_lifetime.rs new file mode 100644 index 00000000000..e0d1e9649a0 --- /dev/null +++ b/src/test/rustdoc-json/type/fn_lifetime.rs @@ -0,0 +1,28 @@ +// ignore-tidy-linelength + +// @is fn_lifetime.json "$.index[*][?(@.name=='GenericFn')].kind" \"typedef\" + +// @count - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*]" 1 +// @is - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].name" \"\'a\" +// @has - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].kind.lifetime" +// @count - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].kind.lifetime.outlives[*]" 0 +// @count - "$.index[*][?(@.name=='GenericFn')].inner.generics.where_predicates[*]" 0 +// @is - "$.index[*][?(@.name=='GenericFn')].inner.type.kind" \"function_pointer\" +// @count - "$.index[*][?(@.name=='GenericFn')].inner.type.inner.generic_params[*]" 0 +// @count - "$.index[*][?(@.name=='GenericFn')].inner.type.inner.decl.inputs[*]" 1 +// @is - "$.index[*][?(@.name=='GenericFn')].inner.type.inner.decl.inputs[*][1].inner.lifetime" \"\'a\" +// @is - "$.index[*][?(@.name=='GenericFn')].inner.type.inner.decl.output.inner.lifetime" \"\'a\" + +pub type GenericFn<'a> = fn(&'a i32) -> &'a i32; + +// @is fn_lifetime.json "$.index[*][?(@.name=='ForAll')].kind" \"typedef\" +// @count - "$.index[*][?(@.name=='ForAll')].inner.generics.params[*]" 0 +// @count - "$.index[*][?(@.name=='ForAll')].inner.generics.where_predicates[*]" 0 +// @count - "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*]" 1 +// @is - "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*].name" \"\'a\" +// @has - "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*].kind.lifetime" +// @count - "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*].kind.lifetime.outlives[*]" 0 +// @count - "$.index[*][?(@.name=='ForAll')].inner.type.inner.decl.inputs[*]" 1 +// @is - "$.index[*][?(@.name=='ForAll')].inner.type.inner.decl.inputs[*][1].inner.lifetime" \"\'a\" +// @is - "$.index[*][?(@.name=='ForAll')].inner.type.inner.decl.output.inner.lifetime" \"\'a\" +pub type ForAll = for<'a> fn(&'a i32) -> &'a i32; diff --git a/src/test/rustdoc-json/type/generic_default.rs b/src/test/rustdoc-json/type/generic_default.rs new file mode 100644 index 00000000000..b6bb6dcc5fe --- /dev/null +++ b/src/test/rustdoc-json/type/generic_default.rs @@ -0,0 +1,33 @@ +// ignore-tidy-linelength + +// @set result = generic_default.json "$.index[*][?(@.name=='Result')].id" +pub enum Result { + Ok(T), + Err(E), +} + +// @set my_error = - "$.index[*][?(@.name=='MyError')].id" +pub struct MyError {} + +// @is - "$.index[*][?(@.name=='MyResult')].kind" \"typedef\" +// @count - "$.index[*][?(@.name=='MyResult')].inner.generics.where_predicates[*]" 0 +// @count - "$.index[*][?(@.name=='MyResult')].inner.generics.params[*]" 2 +// @is - "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].name" \"T\" +// @is - "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].name" \"E\" +// @has - "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].kind.type" +// @has - "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type" +// @count - "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].kind.type.bounds[*]" 0 +// @count - "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.bounds[*]" 0 +// @is - "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].kind.type.default" null +// @is - "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.default.kind" \"resolved_path\" +// @is - "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.default.inner.id" $my_error +// @is - "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.default.inner.name" \"MyError\" +// @is - "$.index[*][?(@.name=='MyResult')].inner.type.kind" \"resolved_path\" +// @is - "$.index[*][?(@.name=='MyResult')].inner.type.inner.id" $result +// @is - "$.index[*][?(@.name=='MyResult')].inner.type.inner.name" \"Result\" +// @is - "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.bindings" [] +// @is - "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[0].type.kind" \"generic\" +// @is - "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[1].type.kind" \"generic\" +// @is - "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[0].type.inner" \"T\" +// @is - "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[1].type.inner" \"E\" +pub type MyResult = Result; diff --git a/src/test/ui/asm/aarch64/parse-error.stderr b/src/test/ui/asm/aarch64/parse-error.stderr index d80ab921fb8..3f705ba5b64 100644 --- a/src/test/ui/asm/aarch64/parse-error.stderr +++ b/src/test/ui/asm/aarch64/parse-error.stderr @@ -382,7 +382,7 @@ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/parse-error.rs:39:37 | LL | let mut foo = 0; - | ---------- help: consider using `const` instead of `let`: `const foo` + | ----------- help: consider using `const` instead of `let`: `const foo` ... LL | asm!("{}", options(), const foo); | ^^^ non-constant value @@ -391,7 +391,7 @@ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/parse-error.rs:48:44 | LL | let mut foo = 0; - | ---------- help: consider using `const` instead of `let`: `const foo` + | ----------- help: consider using `const` instead of `let`: `const foo` ... LL | asm!("{}", clobber_abi("C"), const foo); | ^^^ non-constant value @@ -400,7 +400,7 @@ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/parse-error.rs:55:31 | LL | let mut foo = 0; - | ---------- help: consider using `const` instead of `let`: `const foo` + | ----------- help: consider using `const` instead of `let`: `const foo` ... LL | asm!("{a}", a = const foo, a = const bar); | ^^^ non-constant value @@ -409,7 +409,7 @@ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/parse-error.rs:55:46 | LL | let mut bar = 0; - | ---------- help: consider using `const` instead of `let`: `const bar` + | ----------- help: consider using `const` instead of `let`: `const bar` ... LL | asm!("{a}", a = const foo, a = const bar); | ^^^ non-constant value @@ -418,7 +418,7 @@ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/parse-error.rs:62:45 | LL | let mut bar = 0; - | ---------- help: consider using `const` instead of `let`: `const bar` + | ----------- help: consider using `const` instead of `let`: `const bar` ... LL | asm!("{a}", in("x0") foo, a = const bar); | ^^^ non-constant value @@ -427,7 +427,7 @@ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/parse-error.rs:65:45 | LL | let mut bar = 0; - | ---------- help: consider using `const` instead of `let`: `const bar` + | ----------- help: consider using `const` instead of `let`: `const bar` ... LL | asm!("{a}", in("x0") foo, a = const bar); | ^^^ non-constant value @@ -436,7 +436,7 @@ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/parse-error.rs:68:41 | LL | let mut bar = 0; - | ---------- help: consider using `const` instead of `let`: `const bar` + | ----------- help: consider using `const` instead of `let`: `const bar` ... LL | asm!("{1}", in("x0") foo, const bar); | ^^^ non-constant value diff --git a/src/test/ui/asm/reg-conflict.rs b/src/test/ui/asm/reg-conflict.rs new file mode 100644 index 00000000000..983788a93cc --- /dev/null +++ b/src/test/ui/asm/reg-conflict.rs @@ -0,0 +1,20 @@ +// compile-flags: --target armv7-unknown-linux-gnueabihf +// needs-llvm-components: arm + +#![feature(no_core, lang_items, rustc_attrs)] +#![no_core] + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} +#[lang = "sized"] +trait Sized {} + +fn main() { + unsafe { + asm!("", out("d0") _, out("d1") _); + asm!("", out("d0") _, out("s1") _); + //~^ ERROR register `s1` conflicts with register `d0` + } +} diff --git a/src/test/ui/asm/reg-conflict.stderr b/src/test/ui/asm/reg-conflict.stderr new file mode 100644 index 00000000000..2395566de39 --- /dev/null +++ b/src/test/ui/asm/reg-conflict.stderr @@ -0,0 +1,10 @@ +error: register `s1` conflicts with register `d0` + --> $DIR/reg-conflict.rs:17:31 + | +LL | asm!("", out("d0") _, out("s1") _); + | ----------- ^^^^^^^^^^^ register `s1` + | | + | register `d0` + +error: aborting due to previous error + diff --git a/src/test/ui/asm/x86_64/parse-error.stderr b/src/test/ui/asm/x86_64/parse-error.stderr index 2d0a7a94d56..194cd66a66e 100644 --- a/src/test/ui/asm/x86_64/parse-error.stderr +++ b/src/test/ui/asm/x86_64/parse-error.stderr @@ -394,7 +394,7 @@ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/parse-error.rs:39:37 | LL | let mut foo = 0; - | ---------- help: consider using `const` instead of `let`: `const foo` + | ----------- help: consider using `const` instead of `let`: `const foo` ... LL | asm!("{}", options(), const foo); | ^^^ non-constant value @@ -403,7 +403,7 @@ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/parse-error.rs:50:44 | LL | let mut foo = 0; - | ---------- help: consider using `const` instead of `let`: `const foo` + | ----------- help: consider using `const` instead of `let`: `const foo` ... LL | asm!("{}", clobber_abi("C"), const foo); | ^^^ non-constant value @@ -412,7 +412,7 @@ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/parse-error.rs:57:31 | LL | let mut foo = 0; - | ---------- help: consider using `const` instead of `let`: `const foo` + | ----------- help: consider using `const` instead of `let`: `const foo` ... LL | asm!("{a}", a = const foo, a = const bar); | ^^^ non-constant value @@ -421,7 +421,7 @@ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/parse-error.rs:57:46 | LL | let mut bar = 0; - | ---------- help: consider using `const` instead of `let`: `const bar` + | ----------- help: consider using `const` instead of `let`: `const bar` ... LL | asm!("{a}", a = const foo, a = const bar); | ^^^ non-constant value @@ -430,7 +430,7 @@ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/parse-error.rs:64:46 | LL | let mut bar = 0; - | ---------- help: consider using `const` instead of `let`: `const bar` + | ----------- help: consider using `const` instead of `let`: `const bar` ... LL | asm!("{a}", in("eax") foo, a = const bar); | ^^^ non-constant value @@ -439,7 +439,7 @@ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/parse-error.rs:67:46 | LL | let mut bar = 0; - | ---------- help: consider using `const` instead of `let`: `const bar` + | ----------- help: consider using `const` instead of `let`: `const bar` ... LL | asm!("{a}", in("eax") foo, a = const bar); | ^^^ non-constant value @@ -448,7 +448,7 @@ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/parse-error.rs:70:42 | LL | let mut bar = 0; - | ---------- help: consider using `const` instead of `let`: `const bar` + | ----------- help: consider using `const` instead of `let`: `const bar` ... LL | asm!("{1}", in("eax") foo, const bar); | ^^^ non-constant value diff --git a/src/test/ui/associated-types/issue-91069.rs b/src/test/ui/associated-types/issue-91069.rs new file mode 100644 index 00000000000..109c2eed27a --- /dev/null +++ b/src/test/ui/associated-types/issue-91069.rs @@ -0,0 +1,24 @@ +// check-pass + +pub trait Associate { + type Associated; +} + +pub struct Wrap<'a> { + pub field: &'a i32, +} + +pub trait Create { + fn create() -> Self; +} + +pub fn oh_no<'a, T>() +where + Wrap<'a>: Associate, + as Associate>::Associated: Create, +{ + as Associate>::Associated::create(); +} + + +pub fn main() {} diff --git a/src/test/ui/const-generics/const-generic-default-wont-borrowck.rs b/src/test/ui/const-generics/const-generic-default-wont-borrowck.rs new file mode 100644 index 00000000000..bb5a2f1766f --- /dev/null +++ b/src/test/ui/const-generics/const-generic-default-wont-borrowck.rs @@ -0,0 +1,6 @@ +struct X; + +fn main() {} diff --git a/src/test/ui/const-generics/const-generic-default-wont-borrowck.stderr b/src/test/ui/const-generics/const-generic-default-wont-borrowck.stderr new file mode 100644 index 00000000000..6c25019b0ce --- /dev/null +++ b/src/test/ui/const-generics/const-generic-default-wont-borrowck.stderr @@ -0,0 +1,9 @@ +error[E0381]: borrow of possibly-uninitialized variable: `s` + --> $DIR/const-generic-default-wont-borrowck.rs:2:26 + | +LL | let s: &'static str; s.len() + | ^^^^^^^ use of possibly-uninitialized `*s` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/src/test/ui/consts/const-fn-error.rs b/src/test/ui/consts/const-fn-error.rs index 948c162e894..065944ea7ea 100644 --- a/src/test/ui/consts/const-fn-error.rs +++ b/src/test/ui/consts/const-fn-error.rs @@ -6,7 +6,6 @@ const fn f(x: usize) -> usize { //~^ ERROR mutable references //~| ERROR calls in constant functions //~| ERROR calls in constant functions - //~| ERROR E0080 //~| ERROR `for` is not allowed in a `const fn` sum += i; } diff --git a/src/test/ui/consts/const-fn-error.stderr b/src/test/ui/consts/const-fn-error.stderr index df24585e555..e4b62f20a33 100644 --- a/src/test/ui/consts/const-fn-error.stderr +++ b/src/test/ui/consts/const-fn-error.stderr @@ -5,7 +5,7 @@ LL | / for i in 0..x { LL | | LL | | LL | | -... | +LL | | LL | | sum += i; LL | | } | |_____^ @@ -34,19 +34,7 @@ error[E0015]: calls in constant functions are limited to constant functions, tup LL | for i in 0..x { | ^^^^ -error[E0080]: evaluation of constant value failed - --> $DIR/const-fn-error.rs:5:14 - | -LL | for i in 0..x { - | ^^^^ - | | - | calling non-const function ` as IntoIterator>::into_iter` - | inside `f` at $DIR/const-fn-error.rs:5:14 -... -LL | let a : [i32; f(X)]; - | ---- inside `main::{constant#0}` at $DIR/const-fn-error.rs:18:19 - -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0015, E0080, E0658. +Some errors have detailed explanations: E0015, E0658. For more information about an error, try `rustc --explain E0015`. diff --git a/src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr b/src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr index a9411fb0e3d..61b00be345f 100644 --- a/src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr +++ b/src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr @@ -19,18 +19,7 @@ error[E0596]: cannot borrow data in a `&` reference as mutable LL | const S: &'static mut str = &mut " hello "; | ^^^^^^^^^^^^^^ cannot borrow as mutable -error[E0080]: it is undefined behavior to use this value - --> $DIR/issue-76510.rs:5:1 - | -LL | const S: &'static mut str = &mut " hello "; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered mutable reference in a `const` - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─alloc3──╼ 07 00 00 00 │ ╾──╼.... - } - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0080, E0596, E0658, E0764. -For more information about an error, try `rustc --explain E0080`. +Some errors have detailed explanations: E0596, E0658, E0764. +For more information about an error, try `rustc --explain E0596`. diff --git a/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr b/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr index 9ad5f20d57c..61b00be345f 100644 --- a/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr +++ b/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr @@ -19,18 +19,7 @@ error[E0596]: cannot borrow data in a `&` reference as mutable LL | const S: &'static mut str = &mut " hello "; | ^^^^^^^^^^^^^^ cannot borrow as mutable -error[E0080]: it is undefined behavior to use this value - --> $DIR/issue-76510.rs:5:1 - | -LL | const S: &'static mut str = &mut " hello "; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered mutable reference in a `const` - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────alloc3────────╼ 07 00 00 00 00 00 00 00 │ ╾──────╼........ - } - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0080, E0596, E0658, E0764. -For more information about an error, try `rustc --explain E0080`. +Some errors have detailed explanations: E0596, E0658, E0764. +For more information about an error, try `rustc --explain E0596`. diff --git a/src/test/ui/consts/const-mut-refs/issue-76510.rs b/src/test/ui/consts/const-mut-refs/issue-76510.rs index 892f6c98116..143d2fb6b9a 100644 --- a/src/test/ui/consts/const-mut-refs/issue-76510.rs +++ b/src/test/ui/consts/const-mut-refs/issue-76510.rs @@ -6,7 +6,6 @@ //~^ ERROR: mutable references are not allowed in the final value of constants //~| ERROR: mutation through a reference is not allowed in constants //~| ERROR: cannot borrow data in a `&` reference as mutable -//~| ERROR: it is undefined behavior to use this value const fn trigger() -> [(); unsafe { let s = transmute::<(*const u8, usize), &ManuallyDrop>((S.as_ptr(), 3)); diff --git a/src/test/ui/consts/issue-78655.rs b/src/test/ui/consts/issue-78655.rs index 066764bc46f..b85e6129925 100644 --- a/src/test/ui/consts/issue-78655.rs +++ b/src/test/ui/consts/issue-78655.rs @@ -1,4 +1,4 @@ -const FOO: *const u32 = { //~ ERROR encountered dangling pointer in final constant +const FOO: *const u32 = { let x; &x //~ ERROR borrow of possibly-uninitialized variable: `x` }; diff --git a/src/test/ui/consts/issue-78655.stderr b/src/test/ui/consts/issue-78655.stderr index cf3fe18f802..734266a3453 100644 --- a/src/test/ui/consts/issue-78655.stderr +++ b/src/test/ui/consts/issue-78655.stderr @@ -4,15 +4,6 @@ error[E0381]: borrow of possibly-uninitialized variable: `x` LL | &x | ^^ use of possibly-uninitialized `x` -error: encountered dangling pointer in final constant - --> $DIR/issue-78655.rs:1:1 - | -LL | / const FOO: *const u32 = { -LL | | let x; -LL | | &x -LL | | }; - | |__^ - error: could not evaluate constant pattern --> $DIR/issue-78655.rs:7:9 | @@ -25,6 +16,6 @@ error: could not evaluate constant pattern LL | let FOO = FOO; | ^^^ -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0381`. diff --git a/src/test/ui/consts/issue-91560.fixed b/src/test/ui/consts/issue-91560.fixed new file mode 100644 index 00000000000..41b9d95734a --- /dev/null +++ b/src/test/ui/consts/issue-91560.fixed @@ -0,0 +1,21 @@ +// Regression test for issue #91560. + +// run-rustfix + +#![allow(unused,non_upper_case_globals)] + +fn foo() { + const length: usize = 2; + //~^ HELP: consider using `const` + let arr = [0; length]; + //~^ ERROR: attempt to use a non-constant value in a constant [E0435] +} + +fn bar() { + const length: usize = 2; + //~^ HELP: consider using `const` + let arr = [0; length]; + //~^ ERROR: attempt to use a non-constant value in a constant [E0435] +} + +fn main() {} diff --git a/src/test/ui/consts/issue-91560.rs b/src/test/ui/consts/issue-91560.rs new file mode 100644 index 00000000000..04592feb505 --- /dev/null +++ b/src/test/ui/consts/issue-91560.rs @@ -0,0 +1,21 @@ +// Regression test for issue #91560. + +// run-rustfix + +#![allow(unused,non_upper_case_globals)] + +fn foo() { + let mut length: usize = 2; + //~^ HELP: consider using `const` + let arr = [0; length]; + //~^ ERROR: attempt to use a non-constant value in a constant [E0435] +} + +fn bar() { + let length: usize = 2; + //~^ HELP: consider using `const` + let arr = [0; length]; + //~^ ERROR: attempt to use a non-constant value in a constant [E0435] +} + +fn main() {} diff --git a/src/test/ui/consts/issue-91560.stderr b/src/test/ui/consts/issue-91560.stderr new file mode 100644 index 00000000000..e1b5d4cacf8 --- /dev/null +++ b/src/test/ui/consts/issue-91560.stderr @@ -0,0 +1,21 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/issue-91560.rs:10:19 + | +LL | let mut length: usize = 2; + | -------------- help: consider using `const` instead of `let`: `const length` +LL | +LL | let arr = [0; length]; + | ^^^^^^ non-constant value + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/issue-91560.rs:17:19 + | +LL | let length: usize = 2; + | ------------ help: consider using `const` instead of `let`: `const length` +LL | +LL | let arr = [0; length]; + | ^^^^^^ non-constant value + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0435`. diff --git a/src/test/ui/generic-associated-types/bugs/issue-80626.rs b/src/test/ui/generic-associated-types/bugs/issue-80626.rs new file mode 100644 index 00000000000..aea8aaf4bb3 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-80626.rs @@ -0,0 +1,17 @@ +// check-fail + +// This should pass, but it requires `Sized` to be coinductive. + +#![feature(generic_associated_types)] + +trait Allocator { + type Allocated; +} + +enum LinkedList { + Head, + Next(A::Allocated) + //~^ overflow +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/bugs/issue-80626.stderr b/src/test/ui/generic-associated-types/bugs/issue-80626.stderr new file mode 100644 index 00000000000..e18af9c257f --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-80626.stderr @@ -0,0 +1,20 @@ +error[E0275]: overflow evaluating the requirement `LinkedList: Sized` + --> $DIR/issue-80626.rs:13:10 + | +LL | Next(A::Allocated) + | ^^^^^^^^^^^^^^^^^^ + | + = note: no field of an enum variant may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | Next(&A::Allocated) + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | Next(Box>) + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/generic-associated-types/bugs/issue-86218.rs b/src/test/ui/generic-associated-types/bugs/issue-86218.rs new file mode 100644 index 00000000000..3f8776a3637 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-86218.rs @@ -0,0 +1,27 @@ +// check-fail + +// This should pass, but seems to run into a TAIT issue. + +#![feature(generic_associated_types)] +#![feature(type_alias_impl_trait)] + +pub trait Stream { + type Item; +} + +impl Stream for () { + type Item = i32; +} + +trait Yay { + type InnerStream<'s>: Stream + 's; + fn foo<'s>() -> Self::InnerStream<'s>; +} + +impl<'a> Yay<&'a ()> for () { + type InnerStream<'s> = impl Stream + 's; + //~^ the type + fn foo<'s>() -> Self::InnerStream<'s> { todo!() } +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/bugs/issue-86218.stderr b/src/test/ui/generic-associated-types/bugs/issue-86218.stderr new file mode 100644 index 00000000000..9f4efc0addb --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-86218.stderr @@ -0,0 +1,15 @@ +error[E0477]: the type `impl Stream` does not fulfill the required lifetime + --> $DIR/issue-86218.rs:22:28 + | +LL | type InnerStream<'s> = impl Stream + 's; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: type must outlive the lifetime `'s` as defined here as required by this binding + --> $DIR/issue-86218.rs:22:22 + | +LL | type InnerStream<'s> = impl Stream + 's; + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0477`. diff --git a/src/test/ui/generic-associated-types/bugs/issue-87735.rs b/src/test/ui/generic-associated-types/bugs/issue-87735.rs new file mode 100644 index 00000000000..5f7a42a740d --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-87735.rs @@ -0,0 +1,45 @@ +// check-fail + +// This should pass, but we need an extension of implied bounds (probably). + +#![feature(generic_associated_types)] + +pub trait AsRef2 { + type Output<'a> where Self: 'a; + + fn as_ref2<'a>(&'a self) -> Self::Output<'a>; +} + +impl AsRef2 for Vec { + type Output<'a> where Self: 'a = &'a [T]; + + fn as_ref2<'a>(&'a self) -> Self::Output<'a> { + &self[..] + } +} + +#[derive(Debug)] +struct Foo(T); +#[derive(Debug)] +struct FooRef<'a, U>(&'a [U]); + +impl<'b, T, U> AsRef2 for Foo //~ the type parameter +where + // * `for<'b, 'c> T: AsRef2 = &'c [U]>>` does not work + // + // * `U` is unconstrained but should be allowed in this context because `Output` is + // an associated type + T: AsRef2 = &'b [U]>, + U: 'b +{ + type Output<'a> where Self: 'a = FooRef<'a, U>; + + fn as_ref2<'a>(&'a self) -> Self::Output<'a> { + FooRef(self.0.as_ref2()) + } +} + +fn main() { + let foo = Foo(vec![1, 2, 3]); + dbg!(foo.as_ref2()); +} diff --git a/src/test/ui/generic-associated-types/bugs/issue-87735.stderr b/src/test/ui/generic-associated-types/bugs/issue-87735.stderr new file mode 100644 index 00000000000..31b3a9619b6 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-87735.stderr @@ -0,0 +1,9 @@ +error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-87735.rs:26:13 + | +LL | impl<'b, T, U> AsRef2 for Foo + | ^ unconstrained type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/src/test/ui/generic-associated-types/bugs/issue-87748.rs b/src/test/ui/generic-associated-types/bugs/issue-87748.rs new file mode 100644 index 00000000000..4dbaf429ead --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-87748.rs @@ -0,0 +1,22 @@ +// check-fail + +// This should pass, but unnormalized input args aren't treated as implied. + +#![feature(generic_associated_types)] + +trait MyTrait { + type Assoc<'a, 'b> where 'b: 'a; + fn do_sth(arg: Self::Assoc<'_, '_>); +} + +struct Foo; + +impl MyTrait for Foo { + type Assoc<'a, 'b> where 'b: 'a = u32; + + fn do_sth(_: u32) {} //~ lifetime bound + // fn do_sth(_: Self::Assoc<'static, 'static>) {} + // fn do_sth(_: Self::Assoc<'_, '_>) {} +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/bugs/issue-87748.stderr b/src/test/ui/generic-associated-types/bugs/issue-87748.stderr new file mode 100644 index 00000000000..c38d4478592 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-87748.stderr @@ -0,0 +1,20 @@ +error[E0478]: lifetime bound not satisfied + --> $DIR/issue-87748.rs:17:5 + | +LL | fn do_sth(_: u32) {} + | ^^^^^^^^^^^^^^^^^ + | +note: lifetime parameter instantiated with the anonymous lifetime #2 defined here + --> $DIR/issue-87748.rs:17:5 + | +LL | fn do_sth(_: u32) {} + | ^^^^^^^^^^^^^^^^^ +note: but lifetime parameter must outlive the anonymous lifetime #1 defined here + --> $DIR/issue-87748.rs:17:5 + | +LL | fn do_sth(_: u32) {} + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0478`. diff --git a/src/test/ui/generic-associated-types/bugs/issue-87755.rs b/src/test/ui/generic-associated-types/bugs/issue-87755.rs new file mode 100644 index 00000000000..1cd3534ba77 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-87755.rs @@ -0,0 +1,21 @@ +// check-fail + +// This should pass. + +#![feature(generic_associated_types)] + +use std::fmt::Debug; + +trait Foo { + type Ass where Self::Ass: Debug; +} + +#[derive(Debug)] +struct Bar; + +impl Foo for Bar { + type Ass = Bar; + //~^ overflow +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/bugs/issue-87755.stderr b/src/test/ui/generic-associated-types/bugs/issue-87755.stderr new file mode 100644 index 00000000000..d2dc991a2b6 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-87755.stderr @@ -0,0 +1,9 @@ +error[E0275]: overflow evaluating the requirement `::Ass == _` + --> $DIR/issue-87755.rs:17:16 + | +LL | type Ass = Bar; + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/generic-associated-types/bugs/issue-87803.rs b/src/test/ui/generic-associated-types/bugs/issue-87803.rs new file mode 100644 index 00000000000..3d2ff38ab04 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-87803.rs @@ -0,0 +1,26 @@ +// check-fail + +// This should pass, but using a type alias vs a reference directly +// changes late-bound -> early-bound. + +#![feature(generic_associated_types)] + +trait Scanner { + type Input<'a>; + type Token<'a>; + + fn scan<'a>(&mut self, i : Self::Input<'a>) -> Self::Token<'a>; +} + +struct IdScanner(); + +impl Scanner for IdScanner { + type Input<'a> = &'a str; + type Token<'a> = &'a str; + + fn scan<'a>(&mut self, s : &'a str) -> &'a str { //~ lifetime parameters + s + } +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/bugs/issue-87803.stderr b/src/test/ui/generic-associated-types/bugs/issue-87803.stderr new file mode 100644 index 00000000000..759c0440d07 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-87803.stderr @@ -0,0 +1,12 @@ +error[E0195]: lifetime parameters or bounds on method `scan` do not match the trait declaration + --> $DIR/issue-87803.rs:21:12 + | +LL | fn scan<'a>(&mut self, i : Self::Input<'a>) -> Self::Token<'a>; + | ---- lifetimes in impl do not match this method in trait +... +LL | fn scan<'a>(&mut self, s : &'a str) -> &'a str { + | ^^^^ lifetimes do not match method in trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0195`. diff --git a/src/test/ui/generic-associated-types/bugs/issue-88382.rs b/src/test/ui/generic-associated-types/bugs/issue-88382.rs new file mode 100644 index 00000000000..f4633ca5169 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-88382.rs @@ -0,0 +1,31 @@ +// check-fail + +// This should pass, but has a missed normalization due to HRTB. + +#![feature(generic_associated_types)] + +trait Iterable { + type Iterator<'a> where Self: 'a; + fn iter(&self) -> Self::Iterator<'_>; +} + +struct SomeImplementation(); + +impl Iterable for SomeImplementation { + type Iterator<'a> = std::iter::Empty; + fn iter(&self) -> Self::Iterator<'_> { + std::iter::empty() + } +} + +fn do_something(i: I, mut f: impl for<'a> Fn(&mut I::Iterator<'a>)) { + f(&mut i.iter()); +} + +fn main() { + do_something(SomeImplementation(), |_| ()); + do_something(SomeImplementation(), test); + //~^ type mismatch +} + +fn test<'a, I: Iterable>(_: &mut I::Iterator<'a>) {} diff --git a/src/test/ui/generic-associated-types/bugs/issue-88382.stderr b/src/test/ui/generic-associated-types/bugs/issue-88382.stderr new file mode 100644 index 00000000000..05bc58cbba4 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-88382.stderr @@ -0,0 +1,20 @@ +error[E0631]: type mismatch in function arguments + --> $DIR/issue-88382.rs:27:40 + | +LL | do_something(SomeImplementation(), test); + | ------------ ^^^^ expected signature of `for<'a> fn(&mut ::Iterator<'a>) -> _` + | | + | required by a bound introduced by this call +... +LL | fn test<'a, I: Iterable>(_: &mut I::Iterator<'a>) {} + | ------------------------------------------------- found signature of `for<'r> fn(&'r mut std::iter::Empty) -> _` + | +note: required by a bound in `do_something` + --> $DIR/issue-88382.rs:21:56 + | +LL | fn do_something(i: I, mut f: impl for<'a> Fn(&mut I::Iterator<'a>)) { + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `do_something` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/generic-associated-types/bugs/issue-88460.rs b/src/test/ui/generic-associated-types/bugs/issue-88460.rs new file mode 100644 index 00000000000..7e62790cc50 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-88460.rs @@ -0,0 +1,31 @@ +// check-fail + +// This should pass, but has a missed normalization due to HRTB. + +#![feature(generic_associated_types)] + +pub trait Marker {} + +pub trait Trait { + type Assoc<'a>; +} + +fn test(value: T) +where + T: Trait, + for<'a> T::Assoc<'a>: Marker, +{ +} + +impl Marker for () {} + +struct Foo; + +impl Trait for Foo { + type Assoc<'a> = (); +} + +fn main() { + test(Foo); + //~^ the trait bound +} diff --git a/src/test/ui/generic-associated-types/bugs/issue-88460.stderr b/src/test/ui/generic-associated-types/bugs/issue-88460.stderr new file mode 100644 index 00000000000..604658da7d2 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-88460.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `for<'a> <_ as Trait>::Assoc<'a>: Marker` is not satisfied + --> $DIR/issue-88460.rs:29:5 + | +LL | test(Foo); + | ^^^^ the trait `for<'a> Marker` is not implemented for `<_ as Trait>::Assoc<'a>` + | +note: required by a bound in `test` + --> $DIR/issue-88460.rs:16:27 + | +LL | fn test(value: T) + | ---- required by a bound in this +... +LL | for<'a> T::Assoc<'a>: Marker, + | ^^^^^^ required by this bound in `test` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generic-associated-types/bugs/issue-88526.rs b/src/test/ui/generic-associated-types/bugs/issue-88526.rs new file mode 100644 index 00000000000..90568fcb401 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-88526.rs @@ -0,0 +1,34 @@ +// check-fail + +// This should pass, but requires more logic. + +#![feature(generic_associated_types)] + +trait A { + type I<'a>; +} + +pub struct TestA +{ + f: F, +} + +impl A for TestA { + type I<'a> = &'a F; +} + +struct TestB +{ + q: Q, + f: F, +} + +impl<'q, Q, I, F> A for TestB //~ the type parameter +where + Q: A = &'q I>, + F: Fn(I), +{ + type I<'a> = (); +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/bugs/issue-88526.stderr b/src/test/ui/generic-associated-types/bugs/issue-88526.stderr new file mode 100644 index 00000000000..ccc5ae0b621 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-88526.stderr @@ -0,0 +1,9 @@ +error[E0207]: the type parameter `I` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-88526.rs:26:13 + | +LL | impl<'q, Q, I, F> A for TestB + | ^ unconstrained type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/src/test/ui/generic-associated-types/bugs/issue-89008.rs b/src/test/ui/generic-associated-types/bugs/issue-89008.rs new file mode 100644 index 00000000000..5d850849fd2 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-89008.rs @@ -0,0 +1,43 @@ +// check-fail +// edition:2021 + +// This should pass, but seems to run into a TAIT bug. + +#![feature(type_alias_impl_trait)] +#![feature(generic_associated_types)] + +use std::future::Future; + +trait Stream { + type Item; +} + +struct Empty(T); +impl Stream for Empty { + type Item = (); +} +fn empty() -> Empty { + todo!() +} + +trait X { + type LineStream<'a, Repr>: Stream where Self: 'a; + + type LineStreamFut<'a,Repr>: Future> where Self: 'a; + + fn line_stream<'a,Repr>(&'a self) -> Self::LineStreamFut<'a,Repr>; +} + +struct Y; + +impl X for Y { + type LineStream<'a, Repr> = impl Stream; //~ could not find + + type LineStreamFut<'a, Repr> = impl Future> ; + + fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> { //~ type mismatch + async {empty()} + } +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/bugs/issue-89008.stderr b/src/test/ui/generic-associated-types/bugs/issue-89008.stderr new file mode 100644 index 00000000000..48745fe0fbd --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-89008.stderr @@ -0,0 +1,21 @@ +error[E0271]: type mismatch resolving ` as Future>::Output == impl Stream` + --> $DIR/issue-89008.rs:38:43 + | +LL | type LineStream<'a, Repr> = impl Stream; + | ------------------------ the expected opaque type +... +LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected opaque type, found struct `Empty` + | + = note: expected opaque type `impl Stream` + found struct `Empty<_>` + +error: could not find defining uses + --> $DIR/issue-89008.rs:34:33 + | +LL | type LineStream<'a, Repr> = impl Stream; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/generic-associated-types/issue-91139.rs b/src/test/ui/generic-associated-types/issue-91139.rs new file mode 100644 index 00000000000..2b82d2946b3 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-91139.rs @@ -0,0 +1,22 @@ +// check-pass + +#![feature(generic_associated_types)] + +trait Foo { + type Type<'a> + where + T: 'a; +} + +impl Foo for () { + type Type<'a> + where + T: 'a, + = (); +} + +fn foo() { + let _: for<'a> fn(<() as Foo>::Type<'a>, &'a T) = |_, _| (); +} + +pub fn main() {} diff --git a/src/test/ui/issues/issue-23036.rs b/src/test/ui/issues/issue-23036.rs index d67f184720e..ac24648e49e 100644 --- a/src/test/ui/issues/issue-23036.rs +++ b/src/test/ui/issues/issue-23036.rs @@ -1,4 +1,5 @@ // run-pass +// ignore-wasm32-bare FIXME(#93923) llvm miscompilation use std::collections::HashMap; use std::path::Path; diff --git a/src/test/ui/parser/issues/issue-93282.rs b/src/test/ui/parser/issues/issue-93282.rs index 7be8b25363e..261fcb5f918 100644 --- a/src/test/ui/parser/issues/issue-93282.rs +++ b/src/test/ui/parser/issues/issue-93282.rs @@ -1,4 +1,15 @@ fn main() { f<'a,> //~^ ERROR expected + //~| ERROR expected +} + +fn bar(a: usize, b: usize) -> usize { + a + b +} + +fn foo() { + let x = 1; + bar('y, x); + //~^ ERROR expected } diff --git a/src/test/ui/parser/issues/issue-93282.stderr b/src/test/ui/parser/issues/issue-93282.stderr index 20e6c3ed8a8..900f21a7cce 100644 --- a/src/test/ui/parser/issues/issue-93282.stderr +++ b/src/test/ui/parser/issues/issue-93282.stderr @@ -1,3 +1,9 @@ +error: expected `while`, `for`, `loop` or `{` after a label + --> $DIR/issue-93282.rs:2:9 + | +LL | f<'a,> + | ^ expected `while`, `for`, `loop` or `{` after a label + error: expected one of `.`, `:`, `;`, `?`, `for`, `loop`, `while`, `{`, `}`, or an operator, found `,` --> $DIR/issue-93282.rs:2:9 | @@ -9,5 +15,11 @@ help: use `::<...>` instead of `<...>` to specify lifetime, type, or const argum LL | f::<'a,> | ++ -error: aborting due to previous error +error: expected `while`, `for`, `loop` or `{` after a label + --> $DIR/issue-93282.rs:13:11 + | +LL | bar('y, x); + | ^ expected `while`, `for`, `loop` or `{` after a label + +error: aborting due to 3 previous errors diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.rs b/src/test/ui/parser/require-parens-for-chained-comparison.rs index 68636f6b907..f29fd7a5472 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.rs +++ b/src/test/ui/parser/require-parens-for-chained-comparison.rs @@ -22,10 +22,12 @@ fn main() { let _ = f<'_, i8>(); //~^ ERROR expected one of //~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + //~| ERROR expected f<'_>(); //~^ comparison operators cannot be chained //~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + //~| ERROR expected let _ = f; //~^ ERROR comparison operators cannot be chained diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.stderr b/src/test/ui/parser/require-parens-for-chained-comparison.stderr index cde6f8c674f..92d700753dc 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.stderr +++ b/src/test/ui/parser/require-parens-for-chained-comparison.stderr @@ -53,6 +53,12 @@ help: use `::<...>` instead of `<...>` to specify lifetime, type, or const argum LL | let _ = f::(); | ++ +error: expected `while`, `for`, `loop` or `{` after a label + --> $DIR/require-parens-for-chained-comparison.rs:22:17 + | +LL | let _ = f<'_, i8>(); + | ^ expected `while`, `for`, `loop` or `{` after a label + error: expected one of `.`, `:`, `;`, `?`, `else`, `for`, `loop`, `while`, `{`, or an operator, found `,` --> $DIR/require-parens-for-chained-comparison.rs:22:17 | @@ -64,8 +70,14 @@ help: use `::<...>` instead of `<...>` to specify lifetime, type, or const argum LL | let _ = f::<'_, i8>(); | ++ +error: expected `while`, `for`, `loop` or `{` after a label + --> $DIR/require-parens-for-chained-comparison.rs:27:9 + | +LL | f<'_>(); + | ^ expected `while`, `for`, `loop` or `{` after a label + error: comparison operators cannot be chained - --> $DIR/require-parens-for-chained-comparison.rs:26:6 + --> $DIR/require-parens-for-chained-comparison.rs:27:6 | LL | f<'_>(); | ^ ^ @@ -76,7 +88,7 @@ LL | f::<'_>(); | ++ error: comparison operators cannot be chained - --> $DIR/require-parens-for-chained-comparison.rs:30:14 + --> $DIR/require-parens-for-chained-comparison.rs:32:14 | LL | let _ = f; | ^ ^ @@ -84,5 +96,5 @@ LL | let _ = f; = help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments = help: or use `(...)` if you meant to specify fn arguments -error: aborting due to 8 previous errors +error: aborting due to 10 previous errors diff --git a/src/test/ui/target-feature/tied-features-cli.one.stderr b/src/test/ui/target-feature/tied-features-cli.one.stderr new file mode 100644 index 00000000000..2bc64a76aae --- /dev/null +++ b/src/test/ui/target-feature/tied-features-cli.one.stderr @@ -0,0 +1,4 @@ +error: Target features paca, pacg must all be enabled or disabled together + +error: aborting due to previous error + diff --git a/src/test/ui/target-feature/tied-features-cli.rs b/src/test/ui/target-feature/tied-features-cli.rs new file mode 100644 index 00000000000..ea09d4fc460 --- /dev/null +++ b/src/test/ui/target-feature/tied-features-cli.rs @@ -0,0 +1,9 @@ +// only-aarch64 +// revisions: one two three four +//[one] compile-flags: -C target-feature=+paca +//[two] compile-flags: -C target-feature=-pacg,+pacg +//[three] compile-flags: -C target-feature=+paca,+pacg,-paca +//[four] check-pass +//[four] compile-flags: -C target-feature=-paca,+pacg -C target-feature=+paca + +fn main() {} diff --git a/src/test/ui/target-feature/tied-features-cli.three.stderr b/src/test/ui/target-feature/tied-features-cli.three.stderr new file mode 100644 index 00000000000..2bc64a76aae --- /dev/null +++ b/src/test/ui/target-feature/tied-features-cli.three.stderr @@ -0,0 +1,4 @@ +error: Target features paca, pacg must all be enabled or disabled together + +error: aborting due to previous error + diff --git a/src/test/ui/target-feature/tied-features-cli.two.stderr b/src/test/ui/target-feature/tied-features-cli.two.stderr new file mode 100644 index 00000000000..2bc64a76aae --- /dev/null +++ b/src/test/ui/target-feature/tied-features-cli.two.stderr @@ -0,0 +1,4 @@ +error: Target features paca, pacg must all be enabled or disabled together + +error: aborting due to previous error + diff --git a/src/test/ui/target-feature/tied-features.rs b/src/test/ui/target-feature/tied-features.rs new file mode 100644 index 00000000000..86400361db3 --- /dev/null +++ b/src/test/ui/target-feature/tied-features.rs @@ -0,0 +1,29 @@ +// only-aarch64 +// build-fail + +#![feature(aarch64_target_feature, target_feature_11)] + +fn main() { + #[target_feature(enable = "pacg")] + //~^ ERROR must all be either enabled or disabled together + unsafe fn inner() {} + + unsafe { + foo(); + bar(); + baz(); + inner(); + } +} + +#[target_feature(enable = "paca")] +//~^ ERROR must all be either enabled or disabled together +unsafe fn foo() {} + + +#[target_feature(enable = "paca,pacg")] +unsafe fn bar() {} + +#[target_feature(enable = "paca")] +#[target_feature(enable = "pacg")] +unsafe fn baz() {} diff --git a/src/test/ui/target-feature/tied-features.stderr b/src/test/ui/target-feature/tied-features.stderr new file mode 100644 index 00000000000..0b1460e0b75 --- /dev/null +++ b/src/test/ui/target-feature/tied-features.stderr @@ -0,0 +1,18 @@ +error: the target features paca, pacg must all be either enabled or disabled together + --> $DIR/tied-features.rs:7:5 + | +LL | #[target_feature(enable = "pacg")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add the missing features in a `target_feature` attribute + +error: the target features paca, pacg must all be either enabled or disabled together + --> $DIR/tied-features.rs:19:1 + | +LL | #[target_feature(enable = "paca")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add the missing features in a `target_feature` attribute + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.rs b/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.rs index 3e336933937..1314f9cb093 100644 --- a/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.rs +++ b/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.rs @@ -34,20 +34,20 @@ fn main() { Qux.clone(); //~^ ERROR no method named `clone` found for struct `Qux` //~| NOTE method not found in `Qux` - //~| NOTE `Clone` defines an item `clone`, but is explicitely unimplemented + //~| NOTE `Clone` defines an item `clone`, but is explicitly unimplemented 0_u32.bar(); //~^ ERROR no method named `bar` found for type `u32` //~| NOTE method not found in `u32` - //~| NOTE `Bar` defines an item `bar`, but is explicitely unimplemented + //~| NOTE `Bar` defines an item `bar`, but is explicitly unimplemented Qux.foo(); //~^ ERROR no method named `foo` found for struct `Qux` //~| NOTE method not found in `Qux` - //~| NOTE the following traits define an item `foo`, but are explicitely unimplemented + //~| NOTE the following traits define an item `foo`, but are explicitly unimplemented 0_u32.foo(); //~^ ERROR no method named `foo` found for type `u32` //~| NOTE method not found in `u32` - //~| NOTE `FooBar` defines an item `foo`, but is explicitely unimplemented + //~| NOTE `FooBar` defines an item `foo`, but is explicitly unimplemented } diff --git a/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr b/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr index 01e36a4a62a..c18abf95083 100644 --- a/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr +++ b/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr @@ -8,7 +8,7 @@ LL | Qux.clone(); | ^^^^^ method not found in `Qux` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the trait `Clone` defines an item `clone`, but is explicitely unimplemented + = note: the trait `Clone` defines an item `clone`, but is explicitly unimplemented error[E0599]: no method named `bar` found for type `u32` in the current scope --> $DIR/explicitly-unimplemented-error-message.rs:39:11 @@ -17,7 +17,7 @@ LL | 0_u32.bar(); | ^^^ method not found in `u32` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the trait `Bar` defines an item `bar`, but is explicitely unimplemented + = note: the trait `Bar` defines an item `bar`, but is explicitly unimplemented error[E0599]: no method named `foo` found for struct `Qux` in the current scope --> $DIR/explicitly-unimplemented-error-message.rs:44:9 @@ -29,7 +29,7 @@ LL | Qux.foo(); | ^^^ method not found in `Qux` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following traits define an item `foo`, but are explicitely unimplemented: + = note: the following traits define an item `foo`, but are explicitly unimplemented: Foo FooBar @@ -45,7 +45,7 @@ note: `Foo` defines an item `foo`, perhaps you need to implement it | LL | trait Foo { | ^^^^^^^^^ - = note: the trait `FooBar` defines an item `foo`, but is explicitely unimplemented + = note: the trait `FooBar` defines an item `foo`, but is explicitly unimplemented error: aborting due to 4 previous errors diff --git a/src/tools/jsondocck/src/main.rs b/src/tools/jsondocck/src/main.rs index b8ea10f3d22..d0f476955e1 100644 --- a/src/tools/jsondocck/src/main.rs +++ b/src/tools/jsondocck/src/main.rs @@ -231,7 +231,21 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> { let val = cache.get_value(&command.args[0])?; let results = select(&val, &command.args[1]).unwrap(); - results.len() == expected + let eq = results.len() == expected; + if !command.negated && !eq { + return Err(CkError::FailedCheck( + format!( + "`{}` matched to `{:?}` with length {}, but expected length {}", + &command.args[1], + results, + results.len(), + expected + ), + command, + )); + } else { + eq + } } CommandKind::Is => { // @has = check *exactly one* item matched by path, and it equals value @@ -317,6 +331,6 @@ fn string_to_value<'a>(s: &str, cache: &'a Cache) -> Cow<'a, Value> { panic!("No variable: `{}`. Current state: `{:?}`", &s[1..], cache.variables) })) } else { - Cow::Owned(serde_json::from_str(s).unwrap()) + Cow::Owned(serde_json::from_str(s).expect(&format!("Cannot convert `{}` to json", s))) } } diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index 94e82e3d9f7..46daaf42883 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -182,8 +182,9 @@ impl Checker { fn walk(&mut self, dir: &Path, report: &mut Report) { for entry in t!(dir.read_dir()).map(|e| t!(e)) { let path = entry.path(); - let kind = t!(entry.file_type()); - if kind.is_dir() { + // Goes through symlinks + let metadata = t!(fs::metadata(&path)); + if metadata.is_dir() { self.walk(&path, report); } else { self.check(&path, report); diff --git a/src/tools/miri b/src/tools/miri index a284d4f551e..0db40903769 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit a284d4f551ee12f7761128998efccdabebc4922f +Subproject commit 0db40903769f38669936c5ebb0b882b18c27f449 diff --git a/src/tools/tidy/src/error_codes_check.rs b/src/tools/tidy/src/error_codes_check.rs index 8ea6bb308b7..2a23d72edc0 100644 --- a/src/tools/tidy/src/error_codes_check.rs +++ b/src/tools/tidy/src/error_codes_check.rs @@ -1,7 +1,7 @@ //! Checks that all error codes have at least one test to prevent having error //! codes that are silently not thrown by the compiler anymore. -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::ffi::OsStr; use std::fs::read_to_string; use std::path::Path; @@ -205,6 +205,7 @@ pub fn check(paths: &[&Path], bad: &mut bool) { let mut found_explanations = 0; let mut found_tests = 0; let mut error_codes: HashMap = HashMap::new(); + let mut explanations: HashSet = HashSet::new(); // We want error codes which match the following cases: // // * foo(a, E0111, a) @@ -218,17 +219,27 @@ pub fn check(paths: &[&Path], bad: &mut bool) { for path in paths { super::walk(path, &mut |path| super::filter_dirs(path), &mut |entry, contents| { let file_name = entry.file_name(); + let entry_path = entry.path(); + if file_name == "error_codes.rs" { extract_error_codes(contents, &mut error_codes, entry.path(), &mut errors); found_explanations += 1; - } else if entry.path().extension() == Some(OsStr::new("stderr")) { + } else if entry_path.extension() == Some(OsStr::new("stderr")) { extract_error_codes_from_tests(contents, &mut error_codes); found_tests += 1; - } else if entry.path().extension() == Some(OsStr::new("rs")) { + } else if entry_path.extension() == Some(OsStr::new("rs")) { let path = entry.path().to_string_lossy(); if PATHS_TO_IGNORE_FOR_EXTRACTION.iter().all(|c| !path.contains(c)) { extract_error_codes_from_source(contents, &mut error_codes, ®ex); } + } else if entry_path + .parent() + .and_then(|p| p.file_name()) + .map(|p| p == "error_codes") + .unwrap_or(false) + && entry_path.extension() == Some(OsStr::new("md")) + { + explanations.insert(file_name.to_str().unwrap().replace(".md", "")); } }); } @@ -240,6 +251,10 @@ pub fn check(paths: &[&Path], bad: &mut bool) { eprintln!("No error code was found in compilation errors!"); *bad = true; } + if explanations.is_empty() { + eprintln!("No error code explanation was found!"); + *bad = true; + } if errors.is_empty() { println!("Found {} error codes", error_codes.len()); @@ -282,11 +297,21 @@ pub fn check(paths: &[&Path], bad: &mut bool) { } } } + if errors.is_empty() { + for explanation in explanations { + if !error_codes.contains_key(&explanation) { + errors.push(format!( + "{} error code explanation should be listed in `error_codes.rs`", + explanation + )); + } + } + } errors.sort(); for err in &errors { eprintln!("{}", err); } - println!("Found {} error codes with no tests", errors.len()); + println!("Found {} error(s) in error codes", errors.len()); if !errors.is_empty() { *bad = true; }