]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #91403 - cjgillot:inherit-async, r=oli-obk
authorbors <bors@rust-lang.org>
Sat, 12 Feb 2022 21:42:10 +0000 (21:42 +0000)
committerbors <bors@rust-lang.org>
Sat, 12 Feb 2022 21:42:10 +0000 (21:42 +0000)
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<Output = &'1 u8>;
```
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<Output = &'1 u8>;
```
following the TAIT model.

Fixes https://github.com/rust-lang/rust/issues/61949

118 files changed:
RELEASES.md
compiler/rustc_ast_lowering/src/asm.rs
compiler/rustc_ast_pretty/src/pp/convenience.rs
compiler/rustc_ast_pretty/src/pprust/state/expr.rs
compiler/rustc_ast_pretty/src/pprust/state/item.rs
compiler/rustc_borrowck/src/borrowck_errors.rs
compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
compiler/rustc_borrowck/src/diagnostics/move_errors.rs
compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs
compiler/rustc_borrowck/src/diagnostics/region_errors.rs
compiler/rustc_borrowck/src/lib.rs
compiler/rustc_borrowck/src/nll.rs
compiler/rustc_builtin_macros/src/standard_library_imports.rs
compiler/rustc_codegen_llvm/src/attributes.rs
compiler/rustc_codegen_llvm/src/llvm_util.rs
compiler/rustc_codegen_ssa/src/target_features.rs
compiler/rustc_const_eval/src/const_eval/eval_queries.rs
compiler/rustc_const_eval/src/const_eval/machine.rs
compiler/rustc_const_eval/src/interpret/eval_context.rs
compiler/rustc_const_eval/src/transform/check_consts/check.rs
compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
compiler/rustc_const_eval/src/transform/promote_consts.rs
compiler/rustc_data_structures/src/sip128.rs
compiler/rustc_data_structures/src/stable_hasher.rs
compiler/rustc_error_codes/src/error_codes.rs
compiler/rustc_error_codes/src/error_codes/E0192.md
compiler/rustc_hir/src/itemlikevisit.rs
compiler/rustc_interface/src/passes.rs
compiler/rustc_interface/src/util.rs
compiler/rustc_middle/src/mir/mod.rs
compiler/rustc_middle/src/mir/query.rs
compiler/rustc_middle/src/ty/context.rs
compiler/rustc_middle/src/ty/structural_impls.rs
compiler/rustc_mir_build/src/build/mod.rs
compiler/rustc_mir_transform/src/const_prop.rs
compiler/rustc_mir_transform/src/lib.rs
compiler/rustc_mir_transform/src/shim.rs
compiler/rustc_parse/src/parser/expr.rs
compiler/rustc_resolve/src/diagnostics.rs
compiler/rustc_session/src/config.rs
compiler/rustc_session/src/options.rs
compiler/rustc_span/src/source_map.rs
compiler/rustc_typeck/src/check/method/suggest.rs
library/std/src/env.rs
library/std/src/io/error.rs
library/std/src/io/error/repr_bitpacked.rs
library/std/src/lib.rs
library/std/src/os/fd/owned.rs
library/std/src/os/unix/fs.rs
library/std/src/os/windows/io/handle.rs
library/std/src/os/windows/io/socket.rs
library/std/src/path.rs
library/std/src/path/tests.rs
library/std/src/sys/unix/mod.rs
library/std/src/sys/windows/mod.rs
library/std/tests/run-time-detect.rs
library/stdarch
src/test/pretty/use-tree.rs [new file with mode: 0644]
src/test/rustdoc-json/type/dyn.rs [new file with mode: 0644]
src/test/rustdoc-json/type/fn_lifetime.rs [new file with mode: 0644]
src/test/rustdoc-json/type/generic_default.rs [new file with mode: 0644]
src/test/ui/asm/aarch64/parse-error.stderr
src/test/ui/asm/reg-conflict.rs [new file with mode: 0644]
src/test/ui/asm/reg-conflict.stderr [new file with mode: 0644]
src/test/ui/asm/x86_64/parse-error.stderr
src/test/ui/associated-types/issue-91069.rs [new file with mode: 0644]
src/test/ui/const-generics/const-generic-default-wont-borrowck.rs [new file with mode: 0644]
src/test/ui/const-generics/const-generic-default-wont-borrowck.stderr [new file with mode: 0644]
src/test/ui/consts/const-fn-error.rs
src/test/ui/consts/const-fn-error.stderr
src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr
src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr
src/test/ui/consts/const-mut-refs/issue-76510.rs
src/test/ui/consts/issue-78655.rs
src/test/ui/consts/issue-78655.stderr
src/test/ui/consts/issue-91560.fixed [new file with mode: 0644]
src/test/ui/consts/issue-91560.rs [new file with mode: 0644]
src/test/ui/consts/issue-91560.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/bugs/issue-80626.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/bugs/issue-80626.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/bugs/issue-86218.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/bugs/issue-86218.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/bugs/issue-87735.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/bugs/issue-87735.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/bugs/issue-87748.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/bugs/issue-87748.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/bugs/issue-87755.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/bugs/issue-87755.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/bugs/issue-87803.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/bugs/issue-87803.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/bugs/issue-88382.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/bugs/issue-88382.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/bugs/issue-88460.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/bugs/issue-88460.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/bugs/issue-88526.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/bugs/issue-88526.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/bugs/issue-89008.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/bugs/issue-89008.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-91139.rs [new file with mode: 0644]
src/test/ui/issues/issue-23036.rs
src/test/ui/parser/issues/issue-93282.rs
src/test/ui/parser/issues/issue-93282.stderr
src/test/ui/parser/require-parens-for-chained-comparison.rs
src/test/ui/parser/require-parens-for-chained-comparison.stderr
src/test/ui/target-feature/tied-features-cli.one.stderr [new file with mode: 0644]
src/test/ui/target-feature/tied-features-cli.rs [new file with mode: 0644]
src/test/ui/target-feature/tied-features-cli.three.stderr [new file with mode: 0644]
src/test/ui/target-feature/tied-features-cli.two.stderr [new file with mode: 0644]
src/test/ui/target-feature/tied-features.rs [new file with mode: 0644]
src/test/ui/target-feature/tied-features.stderr [new file with mode: 0644]
src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.rs
src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr
src/tools/jsondocck/src/main.rs
src/tools/linkchecker/main.rs
src/tools/miri
src/tools/tidy/src/error_codes_check.rs

index aae2a669650141cbd4fb421b99c399f043383b42..a9422fa103ed83006cf055d19060b59395138a8a 100644 (file)
@@ -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/
index 89d411d4b36fe78a2f60e5bac14f7417e56bb5d3..5a85356d96daa065ea0b2022da73cb571cb21006 100644 (file)
@@ -373,7 +373,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                                     err.emit();
                                 }
                                 Entry::Vacant(v) => {
-                                    v.insert(idx);
+                                    if r == reg {
+                                        v.insert(idx);
+                                    }
                                 }
                             }
                         };
index 785e6886d8a3841ecac46ee1eeed4a9e033eeaa8..93310dd45c575783e54e04eaa72c3d85105466f6 100644 (file)
@@ -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(','),
index 44116fa76a0c1e0265d39cd8217cf5a1022644bf..6435f1b6141e35a66c82211ab67a2b27883ad402 100644 (file)
@@ -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 {
index dac84ae9d5fc87fcbf4fda40a9f247d88e29bd5e..d7e9ef0e50dd864e92700acdaa9d6a1809f0fa77 100644 (file)
@@ -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("}");
             }
         }
     }
index 5702203d7c4ffba938aea53c89e71a1dbf7ba9bf..7140cda8e4e51d42e7b9fa5850962f15460a80ea 100644 (file)
@@ -327,7 +327,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
         verb: &str,
         optional_adverb_for_moved: &str,
         moved_path: Option<String>,
-    ) -> DiagnosticBuilder<'cx> {
+    ) -> DiagnosticBuilder<'tcx> {
         let moved_path = moved_path.map(|mp| format!(": `{}`", mp)).unwrap_or_default();
 
         struct_span_err!(
index 96326ef2d5a07aa7ad0e07bb4a5d4a594a778c34..ac9950241bfe3a7d2b558fcf5791b2266ea82a61 100644 (file)
@@ -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));
         }
     }
 }
index ba111d394ec26bc20dd81ddd1ae4aa2a5f5d200a..7b8b5974fe758c2eaa103efea01391ef0e6ac807 100644 (file)
@@ -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> {
index 692c20d7dfe34ebed24443a863b7966d356528c7..2934d921868a8ec76c96d8d0508c6d934fa3a2b0 100644 (file)
@@ -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(
index e6c057cc8eea5daf2d9e15b1af58ed8502cfde25..5963904aa0b514e1f6b9fffb55833fd1fdd2b41e 100644 (file)
@@ -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
index 723b57ed970ad6bb16bac57787f39029e9ea4f4f..21f00af5c0cef1bd3efecde471d2fbd20fc23a4b 100644 (file)
@@ -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);
     }
 }
index df23eaf24bc6da8136d53abf83f04f078ba1d49b..31c977cc78d3a9a77e990c8ce8e07b1c79c92b24 100644 (file)
@@ -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.
index 5597a8b091554769adc7dd0f07be095b02ea8739..459b03b0fad65017746ed5c33738f6cf5aa5b335 100644 (file)
@@ -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>(
         &regioncx,
         &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(&regioncx),
         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<BorrowIndex, (Place<'tcx>, 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<Vec<MoveOutIndex>, (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<PlaceRef<'tcx>>,
-    /// Errors to be reported buffer
-    errors_buffer: Vec<Diagnostic>,
     /// 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<Local>,
@@ -604,6 +577,8 @@ struct MirBorrowckCtxt<'cx, 'tcx> {
 
     /// Results of Polonius analysis.
     polonius_output: Option<Rc<PoloniusOutput>>,
+
+    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<Field>
     }
 }
 
+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<Vec<MoveOutIndex>, (PlaceRef<'tcx>, DiagnosticBuilder<'tcx>)>,
+        /// Errors to be reported buffer
+        buffered: Vec<Diagnostic>,
+        /// Set to Some if we emit an error during borrowck
+        tainted_by_errors: Option<ErrorReported>,
+    }
+
+    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<MoveOutIndex>,
+            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<ErrorReported> {
+            // 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
index 6ffab16577908fcbc747a0a4ff2d5b72620628fb..7fc1fe1130b1446d62fe1551e5403a48bb48e798 100644 (file)
@@ -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<ClosureRegionRequirements<'_>>,
     opaque_type_values: &VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
-    errors_buffer: &mut Vec<Diagnostic>,
+    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(
index e106f6014a31d597a0a84f18db3473a43d79b9b1..3571517d2b258a8162ab6fc69bb0e5e658015e7e 100644 (file)
@@ -11,7 +11,6 @@ pub fn inject(
     mut krate: ast::Crate,
     resolver: &mut dyn ResolverExpand,
     sess: &Session,
-    alt_std_name: Option<Symbol>,
 ) -> 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),
             ),
         );
     }
index 7f82ce307d5263ba1f829fd9850fbccb021fcf64..2472789601e70dc1c1da8d98be08cb1682744369 100644 (file)
@@ -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::<Vec<&str>>();
+
+    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::<Vec<String>>()
index f91fad2d9c9635b796069fec0e32ab3820eb0486..727d079d83d937452ab3f3db0c44857a433f69a1 100644 (file)
@@ -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<Symbol> {
     let target_machine = create_informational_target_machine(sess);
     supported_target_features(sess)
@@ -395,15 +415,19 @@ pub fn llvm_global_features(sess: &Session) -> Vec<String> {
         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<String> {
     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
 }
 
index 63cc6faf9ec5ea01de532406e44fcc2b98ff9f84..f31b0ee592e9cb9b98acededf52e8b6543239cee 100644 (file)
     ("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
     ("v8.7a", Some(sym::aarch64_target_feature)),
 ];
 
+const AARCH64_TIED_FEATURES: &[&[&str]] = &[&["paca", "pacg"]];
+
 const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
     ("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);
index 9dc34260de76697047c831da46ec30ec24d6ca40..bfb9c40be57df0e6d09c34b2caee8b8d63bfdad7 100644 (file)
@@ -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(
index 89717b75f12815abea8069f2d36d695b7ff3b205..e157b584052128790b90db8300725e56b7fcf7ad 100644 (file)
@@ -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))
index 0a8112da2aba8fbe4ccd596e05a14da16e970773..1b86bcfa8c9ad6ed9cef72d69ff896226e79043e 100644 (file)
@@ -509,20 +509,18 @@ pub fn load_mir(
         instance: ty::InstanceDef<'tcx>,
         promoted: Option<mir::Promoted>,
     ) -> 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
index 6799514a4490db098206e2958dff72304158fb10..12a8b8c6d77905a745870cb529f08f1fc9b337e9 100644 (file)
@@ -120,7 +120,7 @@ pub fn has_mut_interior(
     fn in_return_place(
         &mut self,
         ccx: &'mir ConstCx<'mir, 'tcx>,
-        error_occured: Option<ErrorReported>,
+        tainted_by_errors: Option<ErrorReported>,
     ) -> 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,
         }
     }
 }
index 91610b15eb9998d022dea2fd34fb886a564c7a21..c3fa98b000f4a3cacedd51599e423c9851b01dec 100644 (file)
 pub fn in_any_value_of_ty<'tcx>(
     cx: &ConstCx<'_, 'tcx>,
     ty: Ty<'tcx>,
-    error_occured: Option<ErrorReported>,
+    tainted_by_errors: Option<ErrorReported>,
 ) -> 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,
     }
 }
 
index ac282a5ecc82c281454dcc0c83a31a4662bd7f3d..92d1f5bceefe41eaef7b01efc4c826adc1e0e4ca 100644 (file)
@@ -974,6 +974,7 @@ pub fn promote_candidates<'tcx>(
             vec![],
             body.span,
             body.generator_kind(),
+            body.tainted_by_errors,
         );
 
         let promoter = Promoter {
index 53062b9c20da8b8e6e6118730a518ff98c3bbf3f..6e5c0617bf34cb089c3942c5ca4831d874e7129b 100644 (file)
@@ -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<T>(&mut self, x: T) {
-        let size = mem::size_of::<T>();
+    pub fn short_write<const LEN: usize>(&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<T>(&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<T>(&mut self, x: T) {
-        let size = mem::size_of::<T>();
+    unsafe fn short_write_process_buffer<const LEN: usize>(&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<T>(&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]
index a121bbcedc8f70080eb633d78d7eb7d2f8f74070..31d6a42cf288405d8e624f2fc40247227135b6cc 100644 (file)
@@ -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 {
index c401f65eddaedde02a099bc37ac22533871b9e0d..a72681dbf4e7ede9866d2b620ec9e071cdf3627a 100644 (file)
@@ -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"),
 //  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,
index 5fd951b2e86cb906c8f92ec8ec74b9b53b1ca157..deca042a91a5054b30c4a7e29cac91c5f8e31a11 100644 (file)
@@ -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() {}
 ```
index 0db562f91a6a5499a50b8ed647fdb0326e840a1a..db70002c2d66ac97d99d57ebb2f6da49403e6350 100644 (file)
@@ -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
index f5a4e11de16c07c52b79e0ac8534b137b91fb922..66e1e78b2856c8972539e349684e0e1a70a61093 100644 (file)
@@ -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());
index 6d9183eda9d32e9a00c6fa0fbc6773b96640a7c0..f74cadfebacba748f4b38976884f0119cb1db976 100644 (file)
@@ -118,7 +118,7 @@ fn get_stack_size() -> Option<usize> {
 /// Like a `thread::Builder::spawn` followed by a `join()`, but avoids the need
 /// for `'static` bounds.
 #[cfg(not(parallel_compiler))]
-pub fn scoped_thread<F: FnOnce() -> R + Send, R: Send>(cfg: thread::Builder, f: F) -> R {
+fn scoped_thread<F: FnOnce() -> 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<PathBuf> {
     }
 }
 
-pub fn get_codegen_sysroot(maybe_sysroot: &Option<PathBuf>, backend_name: &str) -> MakeBackendFn {
+fn get_codegen_sysroot(maybe_sysroot: &Option<PathBuf>, 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`,
index 33fb1e570b1c0cb85e588267c49acc53d74f28a1..0688d7d2569f55248a5b1a39832baad327a8e88c 100644 (file)
@@ -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<ErrorReported>,
 }
 
 impl<'tcx> Body<'tcx> {
@@ -297,6 +300,7 @@ pub fn new(
         var_debug_info: Vec<VarDebugInfo<'tcx>>,
         span: Span,
         generator_kind: Option<GeneratorKind>,
+        tainted_by_errors: Option<ErrorReported>,
     ) -> 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<BasicBlock, BasicBlockData<'tcx>>) ->
             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
index 4b8eb3fbd96075193bbda54bf49245f041b5ce5b..6e2b060e7ddcf3789e1abf9107ebd0fb629c81e3 100644 (file)
@@ -214,6 +214,7 @@ pub struct BorrowCheckResult<'tcx> {
     pub concrete_opaque_types: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
     pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
     pub used_mut_upvars: SmallVec<[Field; 8]>,
+    pub tainted_by_errors: Option<ErrorReported>,
 }
 
 /// 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<ErrorReported>,
+    pub tainted_by_errors: Option<ErrorReported>,
 }
 
 /// After we borrow check a closure, we are left with various
index a119655a90b20a53d260c8b6a873b959fefda8b1..4a3efb5c1b8ef3a295395b79832c8e06b7e31c70 100644 (file)
@@ -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<LocalDefId>,
+    ) -> &'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<Thir<'tcx>> {
         self.arena.alloc(Steal::new(thir))
     }
index 1c5bc7860db2de7280f0446399e3f3ec796fa051..39efc006d9d0fa4bda67f3d1ed1d055f044f5307 100644 (file)
@@ -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,
 }
 
 ///////////////////////////////////////////////////////////////////////////
index 88d994e32fe0c452122002a81e2be8fa1de4e34c..10807d432764341c782caecf3984da222c3da9e0 100644 (file)
@@ -104,8 +104,8 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> 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,
         )
     }
 
index 98de64cd97c9c49140d806f213359ce64bcb4063..0d314a109bac72c437f64e3be6251cc9905db8db 100644 (file)
@@ -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
index 991d10a8547ff3d4eb87424322889666e33cfddd..e7d5bab8fd9d45e6bce054f0d7c75e8f4e754ee8 100644 (file)
@@ -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);
     }
 
index 919171db39e3160ac15bfe61f13b8cf523c8acf5..a4927c467cfc3116357a4af30caec8e19ac4635b 100644 (file)
@@ -235,6 +235,8 @@ fn new_body<'tcx>(
         vec![],
         span,
         None,
+        // FIXME(compiler-errors): is this correct?
+        None,
     )
 }
 
index 4898a4844b9f779b6549ad7641b0381bd95eab6a..e9aa4adcaf79bae5faddf019378d84bf3f8b5e29 100644 (file)
@@ -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 {
index c7edcb077b917ec7a0582ae891aae2138fd66efe..1f657218a64a980591098e040e33e5e7dc58c2af 100644 (file)
@@ -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 {
index 8630ffec241f947199a4ae56131823180174bc2f..79962d5db891826e30cacac0389ab937d0ba8d10 100644 (file)
@@ -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,
index 550da9e05804fecc42e3fe6eec420bb8c3b4f60d..ae1b638c34467ec0f0542cf0895ac2cb03e88009 100644 (file)
@@ -184,10 +184,6 @@ pub struct Options {
         externs: Externs [UNTRACKED],
         extern_dep_specs: ExternDepSpecs [UNTRACKED],
         crate_name: Option<String> [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<String> [TRACKED],
         /// Indicates how the compiler should treat unstable features.
         unstable_features: UnstableFeatures [TRACKED],
 
index 7414d201f511d099b79cba7748fdfc8abe47fe79..95177102dcf8678df118ab6d58cc65750219d8be 100644 (file)
@@ -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<Span> {
         // 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<Span> {
-        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<Span> {
     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
index a17553b920f03971056c1532fb49b300e822d0e4..8aa22852a6ffdc35574dd68ec2d63a7b65dae3d5 100644 (file)
@@ -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 {
index c06928647d3897761ee40c2a5b941f60576b4d5d..5ed9fa9d6f0fd1a956c3a0ce84e16066d33befa8 100644 (file)
 
 /// 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<PathBuf> {
 
 /// 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
index 4b55324a2424cf45d424e44154b291db5ed3bd20..1aa6d657889129c0fedae5aa4ce0c7472c8a9843 100644 (file)
@@ -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",
index f317368e8e59dec5138f35fd71dda97c03f38863..4301e941b3dce1b57efbe10f446b078e744a23e4 100644 (file)
@@ -315,7 +315,7 @@ macro_rules! from_prim {
         Deadlock,
         CrossesDevices,
         TooManyLinks,
-        FilenameTooLong,
+        InvalidFilename,
         ArgumentListTooLong,
         Interrupted,
         Other,
index 2aae29f21544da6be1979cb452149ca1313ab232..82f0291decb97fd115ccf180f1437a56b7a4dbd3 100644 (file)
@@ -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,
     };
 }
 
index b53c3e79b0fe6e7a9046a434ef3623ec313baa31..71c660e7186751be890291f7d5d1127a1d23b850 100644 (file)
@@ -200,6 +200,22 @@ pub trait AsFd {
     fn as_fd(&self) -> BorrowedFd<'_>;
 }
 
+#[unstable(feature = "io_safety", issue = "87074")]
+impl<T: AsFd> AsFd for &T {
+    #[inline]
+    fn as_fd(&self) -> BorrowedFd<'_> {
+        T::as_fd(self)
+    }
+}
+
+#[unstable(feature = "io_safety", issue = "87074")]
+impl<T: AsFd> 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]
index db7edcd057432563b925d1118690ab7a5817b459..75d65e6d5fc036bff10c39ab60f6cd2636b62a79 100644 (file)
@@ -966,7 +966,7 @@ pub fn chown<P: AsRef<Path>>(dir: P, uid: Option<u32>, gid: Option<u32>) -> 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(())
 /// }
 /// ```
index e37ce633a129a77f231af65ffff172824d358adc..8df6c54a4144e9f42c1314bbb07d12d333d16cdf 100644 (file)
@@ -316,6 +316,22 @@ pub trait AsHandle {
     fn as_handle(&self) -> BorrowedHandle<'_>;
 }
 
+#[unstable(feature = "io_safety", issue = "87074")]
+impl<T: AsHandle> AsHandle for &T {
+    #[inline]
+    fn as_handle(&self) -> BorrowedHandle<'_> {
+        T::as_handle(self)
+    }
+}
+
+#[unstable(feature = "io_safety", issue = "87074")]
+impl<T: AsHandle> AsHandle for &mut T {
+    #[inline]
+    fn as_handle(&self) -> BorrowedHandle<'_> {
+        T::as_handle(self)
+    }
+}
+
 impl AsHandle for BorrowedHandle<'_> {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
index d3a5b6dcc76c6847125ac630d2e04a036e928b21..2f13eb77a1b948519bb93e51ceda78e8cfe20f5c 100644 (file)
@@ -210,6 +210,22 @@ pub trait AsSocket {
     fn as_socket(&self) -> BorrowedSocket<'_>;
 }
 
+#[unstable(feature = "io_safety", issue = "87074")]
+impl<T: AsSocket> AsSocket for &T {
+    #[inline]
+    fn as_socket(&self) -> BorrowedSocket<'_> {
+        T::as_socket(self)
+    }
+}
+
+#[unstable(feature = "io_safety", issue = "87074")]
+impl<T: AsSocket> AsSocket for &mut T {
+    #[inline]
+    fn as_socket(&self) -> BorrowedSocket<'_> {
+        T::as_socket(self)
+    }
+}
+
 impl AsSocket for BorrowedSocket<'_> {
     #[inline]
     fn as_socket(&self) -> BorrowedSocket<'_> {
index 85cad65da6a30670f9ff1cd3ee78b97e04cdab7d..551b66891c92fb537ccaf519c8c2f6a719bbc92e 100644 (file)
@@ -2922,12 +2922,12 @@ fn eq(&self, other: &Path) -> bool {
 impl Hash for Path {
     fn hash<H: Hasher>(&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<H: Hasher>(&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<H: Hasher>(&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,
+                    };
+                }
             }
         }
 
index 2bf499e1ab823b656aefaab444a876fdcdd08b8a..0ab5956e1bc6beb45c43768678da5dac5f268d86 100644 (file)
@@ -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
+        );
     }
 }
 
index 6382354eb6ebd050e218a059eb786d24a807020b..605cc499b3c92670c7faf9afbbebb338c2ae2f32 100644 (file)
@@ -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,
index c70f254cf39f8d734354a11c5400f864bb117f4d..dc288176346bcb4dfe4413836e031478060b6f30 100644 (file)
@@ -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,
         _ => {}
     }
 
index 14a9e3acca499e89ceaa3ca54e25702e855b0388..54873f5549bfda37e7d2fd4f988cabbbd916e2c8 100644 (file)
@@ -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"));
index eaee02ffdf5d820729ccdf2f95fa08b08c7d24d2..863d31b8e1314e15d124384e5eaa9ab21e12bd79 160000 (submodule)
@@ -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 (file)
index 0000000..5da9523
--- /dev/null
@@ -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 (file)
index 0000000..f53dc03
--- /dev/null
@@ -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<dyn Fn() -> 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 (file)
index 0000000..e0d1e96
--- /dev/null
@@ -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 (file)
index 0000000..b6bb6dc
--- /dev/null
@@ -0,0 +1,33 @@
+// ignore-tidy-linelength
+
+// @set result = generic_default.json "$.index[*][?(@.name=='Result')].id"
+pub enum Result<T, E> {
+    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<T, E = MyError> = Result<T, E>;
index d80ab921fb83ef97284acb76e15b8746cca94eec..3f705ba5b64c2995eeddfc8d1c10da25f94f9b78 100644 (file)
@@ -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 (file)
index 0000000..983788a
--- /dev/null
@@ -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 (file)
index 0000000..2395566
--- /dev/null
@@ -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
+
index 2d0a7a94d56765d8d1b4cea1c7ed370b142d99aa..194cd66a66e96325ae9e63e4201d96fe616f56ec 100644 (file)
@@ -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 (file)
index 0000000..109c2ee
--- /dev/null
@@ -0,0 +1,24 @@
+// check-pass
+
+pub trait Associate {
+    type Associated;
+}
+
+pub struct Wrap<'a> {
+    pub field: &'a i32,
+}
+
+pub trait Create<T> {
+    fn create() -> Self;
+}
+
+pub fn oh_no<'a, T>()
+where
+    Wrap<'a>: Associate,
+    <Wrap<'a> as Associate>::Associated: Create<T>,
+{
+    <Wrap<'a> 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 (file)
index 0000000..bb5a2f1
--- /dev/null
@@ -0,0 +1,6 @@
+struct X<const N: usize = {
+    let s: &'static str; s.len()
+    //~^ ERROR borrow of possibly-uninitialized variable
+}>;
+
+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 (file)
index 0000000..6c25019
--- /dev/null
@@ -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`.
index 948c162e8946d8c3a8a54d8ff6445b55727ebee5..065944ea7eaadd222c0a0efb809dd99252771b62 100644 (file)
@@ -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;
     }
index df24585e5551ac0e0018d09f6d125428666685dd..e4b62f20a3318cfda146314a6f9e72d803dad77c 100644 (file)
@@ -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 `<std::ops::Range<usize> 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`.
index a9411fb0e3d4c23c726540be5dc9879a6321541d..61b00be345feee4bb0cf3a42aaa397097a8de029 100644 (file)
@@ -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`.
index 9ad5f20d57cb2f2ea7b73a583fc599f6b40efa28..61b00be345feee4bb0cf3a42aaa397097a8de029 100644 (file)
@@ -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`.
index 892f6c98116c2184953bc3fba45ad2e6f368876f..143d2fb6b9a3a1a599f36edcc222f4f1d7d34e83 100644 (file)
@@ -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<str>>((S.as_ptr(), 3));
index 066764bc46fc4ca158168c9006c4cac16d495b8f..b85e612992549fdd3f78eded1cb9fc4dca92b83d 100644 (file)
@@ -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`
 };
index cf3fe18f802fbafb058a639f771d03fa031c7d31..734266a3453b580d2204657d1677d9635334417d 100644 (file)
@@ -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 (file)
index 0000000..41b9d95
--- /dev/null
@@ -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 (file)
index 0000000..04592fe
--- /dev/null
@@ -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 (file)
index 0000000..e1b5d4c
--- /dev/null
@@ -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 (file)
index 0000000..aea8aaf
--- /dev/null
@@ -0,0 +1,17 @@
+// check-fail
+
+// This should pass, but it requires `Sized` to be coinductive.
+
+#![feature(generic_associated_types)]
+
+trait Allocator {
+    type Allocated<T>;
+}
+
+enum LinkedList<A: Allocator> {
+    Head,
+    Next(A::Allocated<Self>)
+    //~^ 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 (file)
index 0000000..e18af9c
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0275]: overflow evaluating the requirement `LinkedList<A>: Sized`
+  --> $DIR/issue-80626.rs:13:10
+   |
+LL |     Next(A::Allocated<Self>)
+   |          ^^^^^^^^^^^^^^^^^^
+   |
+   = 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<Self>)
+   |          +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+   |
+LL |     Next(Box<A::Allocated<Self>>)
+   |          ++++                  +
+
+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 (file)
index 0000000..3f8776a
--- /dev/null
@@ -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<AdditionalValue> {
+    type InnerStream<'s>: Stream<Item = i32> + 's;
+    fn foo<'s>() -> Self::InnerStream<'s>;
+}
+
+impl<'a> Yay<&'a ()> for () {
+    type InnerStream<'s> = impl Stream<Item = i32> + '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 (file)
index 0000000..9f4efc0
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0477]: the type `impl Stream<Item = i32>` does not fulfill the required lifetime
+  --> $DIR/issue-86218.rs:22:28
+   |
+LL |     type InnerStream<'s> = impl Stream<Item = i32> + '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<Item = i32> + '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 (file)
index 0000000..5f7a42a
--- /dev/null
@@ -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<T> AsRef2 for Vec<T> {
+  type Output<'a> where Self: 'a = &'a [T];
+
+  fn as_ref2<'a>(&'a self) -> Self::Output<'a> {
+    &self[..]
+  }
+}
+
+#[derive(Debug)]
+struct Foo<T>(T);
+#[derive(Debug)]
+struct FooRef<'a, U>(&'a [U]);
+
+impl<'b, T, U> AsRef2 for Foo<T> //~ the type parameter
+where
+    // * `for<'b, 'c> T: AsRef2<Output<'b> = &'c [U]>>` does not work
+    //
+    // * `U` is unconstrained but should be allowed in this context because `Output` is
+    // an associated type
+    T: AsRef2<Output<'b> = &'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 (file)
index 0000000..31b3a96
--- /dev/null
@@ -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<T>
+   |             ^ 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 (file)
index 0000000..4dbaf42
--- /dev/null
@@ -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 (file)
index 0000000..c38d447
--- /dev/null
@@ -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 (file)
index 0000000..1cd3534
--- /dev/null
@@ -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 (file)
index 0000000..d2dc991
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0275]: overflow evaluating the requirement `<Bar as Foo>::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 (file)
index 0000000..3d2ff38
--- /dev/null
@@ -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 (file)
index 0000000..759c044
--- /dev/null
@@ -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 (file)
index 0000000..f4633ca
--- /dev/null
@@ -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<usize>;
+    fn iter(&self) -> Self::Iterator<'_> {
+        std::iter::empty()
+    }
+}
+
+fn do_something<I: Iterable>(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 (file)
index 0000000..05bc58c
--- /dev/null
@@ -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 <SomeImplementation as Iterable>::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<usize>) -> _`
+   |
+note: required by a bound in `do_something`
+  --> $DIR/issue-88382.rs:21:56
+   |
+LL | fn do_something<I: Iterable>(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 (file)
index 0000000..7e62790
--- /dev/null
@@ -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<T>(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 (file)
index 0000000..604658d
--- /dev/null
@@ -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<T>(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 (file)
index 0000000..90568fc
--- /dev/null
@@ -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: F,
+}
+
+impl<F> A for TestA<F> {
+    type I<'a> = &'a F;
+}
+
+struct TestB<Q, F>
+{
+    q: Q,
+    f: F,
+}
+
+impl<'q, Q, I, F> A for TestB<Q, F> //~ the type parameter
+where
+    Q: A<I<'q> = &'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 (file)
index 0000000..ccc5ae0
--- /dev/null
@@ -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<Q, F>
+   |             ^ 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 (file)
index 0000000..5d85084
--- /dev/null
@@ -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>(T);
+impl<T> Stream for Empty<T> {
+    type Item = ();
+}
+fn empty<T>() -> Empty<T> {
+    todo!()
+}
+
+trait X {
+    type LineStream<'a, Repr>: Stream<Item = Repr> where Self: 'a;
+
+    type LineStreamFut<'a,Repr>: Future<Output = Self::LineStream<'a, Repr>> 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<Item = Repr>; //~ could not find
+
+    type LineStreamFut<'a, Repr> = impl Future<Output = Self::LineStream<'a, Repr>> ;
+
+    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 (file)
index 0000000..48745fe
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0271]: type mismatch resolving `<impl Future<Output = [async output]> as Future>::Output == impl Stream<Item = Repr>`
+  --> $DIR/issue-89008.rs:38:43
+   |
+LL |     type LineStream<'a, Repr> = impl Stream<Item = Repr>;
+   |                                 ------------------------ 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<Item = Repr>`
+                   found struct `Empty<_>`
+
+error: could not find defining uses
+  --> $DIR/issue-89008.rs:34:33
+   |
+LL |     type LineStream<'a, Repr> = impl Stream<Item = Repr>;
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^
+
+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 (file)
index 0000000..2b82d29
--- /dev/null
@@ -0,0 +1,22 @@
+// check-pass
+
+#![feature(generic_associated_types)]
+
+trait Foo<T> {
+    type Type<'a>
+    where
+        T: 'a;
+}
+
+impl<T> Foo<T> for () {
+    type Type<'a>
+    where
+        T: 'a,
+    = ();
+}
+
+fn foo<T>() {
+    let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
+}
+
+pub fn main() {}
index d67f184720e6cb82be639057fdc5bc888390bdcd..ac24648e49e915fda9e1e08a72cb55744c1c3155 100644 (file)
@@ -1,4 +1,5 @@
 // run-pass
+// ignore-wasm32-bare FIXME(#93923) llvm miscompilation
 
 use std::collections::HashMap;
 use std::path::Path;
index 7be8b25363e09e750e294c98fe61bc5b40e0c364..261fcb5f9183e9a34b42b74ac1c1ecc95e44c556 100644 (file)
@@ -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
 }
index 20e6c3ed8a8d5d7a45e053c8717a1d46040ff76a..900f21a7ccef461ae7465a9c8f3d846439dadd5e 100644 (file)
@@ -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
 
index 68636f6b907ef7448d2dc922408ff2f544a424d8..f29fd7a5472d45ce75e870a02b78979c0e94f921 100644 (file)
@@ -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<u8>;
     //~^ ERROR comparison operators cannot be chained
index cde6f8c674f4b5c53c61a5e43c70f046456a7f83..92d700753dc1b24665bce4e45eb9e056f363e215 100644 (file)
@@ -53,6 +53,12 @@ help: use `::<...>` instead of `<...>` to specify lifetime, type, or const argum
 LL |     let _ = f::<u8, i8>();
    |              ++
 
+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<u8>;
    |              ^  ^
@@ -84,5 +96,5 @@ LL |     let _ = f<u8>;
    = 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 (file)
index 0000000..2bc64a7
--- /dev/null
@@ -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 (file)
index 0000000..ea09d4f
--- /dev/null
@@ -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 (file)
index 0000000..2bc64a7
--- /dev/null
@@ -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 (file)
index 0000000..2bc64a7
--- /dev/null
@@ -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 (file)
index 0000000..8640036
--- /dev/null
@@ -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 (file)
index 0000000..0b1460e
--- /dev/null
@@ -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
+
index 3e336933937d04dcd782adf318e3b3bc189737e9..1314f9cb0932d6b98ef0842b0f950dc9bc324350 100644 (file)
@@ -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
 }
index 01e36a4a62a1bcc01715166670471d9f3f1e6d38..c18abf95083da5feff467f8b1f5adb7ea63e060d 100644 (file)
@@ -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
 
index b8ea10f3d22778e6a96032bdecc729f8ba1b2376..d0f476955e1f79dbd2ded1263c3b2c67c8d80897 100644 (file)
@@ -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 <path> <jsonpath> <value> = 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)))
     }
 }
index 94e82e3d9f7664f993ea6fcb2db1e0a9a156d1df..46daaf42883f026a2e675247ae3fd3c4c6f79d12 100644 (file)
@@ -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);
index a284d4f551ee12f7761128998efccdabebc4922f..0db40903769f38669936c5ebb0b882b18c27f449 160000 (submodule)
@@ -1 +1 @@
-Subproject commit a284d4f551ee12f7761128998efccdabebc4922f
+Subproject commit 0db40903769f38669936c5ebb0b882b18c27f449
index 8ea6bb308b7bac4a2bad4c12672b0fa9c9810af6..2a23d72edc06409029ebc5f1d631c662f56b833b 100644 (file)
@@ -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<String, ErrorCodeStatus> = HashMap::new();
+    let mut explanations: HashSet<String> = 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, &regex);
                 }
+            } 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;
     }