Auto merge of #94081 - oli-obk:lazy_tait_take_two, r=nikomatsakis
Lazy type-alias-impl-trait take two
### user visible change 1: RPIT inference from recursive call sites
Lazy TAIT has an insta-stable change. The following snippet now compiles, because opaque types can now have their hidden type set from wherever the opaque type is mentioned.
```rust
fn bar(b: bool) -> impl std::fmt::Debug {
if b {
return 42
}
let x: u32 = bar(false); // this errors on stable
99
}
```
The return type of `bar` stays opaque, you can't do `bar(false) + 42`, you need to actually mention the hidden type.
### user visible change 2: divergence between RPIT and TAIT in return statements
Note that `return` statements and the trailing return expression are special with RPIT (but not TAIT). So
```rust
#![feature(type_alias_impl_trait)]
type Foo = impl std::fmt::Debug;
fn foo(b: bool) -> Foo {
if b {
return vec![42];
}
std::iter::empty().collect() //~ ERROR `Foo` cannot be built from an iterator
}
fn bar(b: bool) -> impl std::fmt::Debug {
if b {
return vec![42]
}
std::iter::empty().collect() // Works, magic (accidentally stabilized, not intended)
}
```
But when we are working with the return value of a recursive call, the behavior of RPIT and TAIT is the same:
```rust
type Foo = impl std::fmt::Debug;
fn foo(b: bool) -> Foo {
if b {
return vec![];
}
let mut x = foo(false);
x = std::iter::empty().collect(); //~ ERROR `Foo` cannot be built from an iterator
vec![]
}
fn bar(b: bool) -> impl std::fmt::Debug {
if b {
return vec![];
}
let mut x = bar(false);
x = std::iter::empty().collect(); //~ ERROR `impl Debug` cannot be built from an iterator
vec![]
}
```
### user visible change 3: TAIT does not merge types across branches
In contrast to RPIT, TAIT does not merge types across branches, so the following does not compile.
```rust
type Foo = impl std::fmt::Debug;
fn foo(b: bool) -> Foo {
if b {
vec![42_i32]
} else {
std::iter::empty().collect()
//~^ ERROR `Foo` cannot be built from an iterator over elements of type `_`
}
}
```
It is easy to support, but we should make an explicit decision to include the additional complexity in the implementation (it's not much, see a721052457cf513487fb4266e3ade65c29b272d2 which needs to be reverted to enable this).
### PR formalities
previous attempt: #92007
This PR also includes #92306 and #93783, as they were reverted along with #92007 in #93893
fixes #93411
fixes #88236
fixes #89312
fixes #87340
fixes #86800
fixes #86719
fixes #84073
fixes #83919
fixes #82139
fixes #77987
fixes #74282
fixes #67830
fixes #62742
fixes #54895
diff --git a/compiler/rustc/Cargo.toml b/compiler/rustc/Cargo.toml
index 696c003..b642e89 100644
--- a/compiler/rustc/Cargo.toml
+++ b/compiler/rustc/Cargo.toml
@@ -19,3 +19,4 @@
jemalloc = ['tikv-jemalloc-sys']
llvm = ['rustc_driver/llvm']
max_level_info = ['rustc_driver/max_level_info']
+rustc_use_parallel_compiler = ['rustc_driver/rustc_use_parallel_compiler']
diff --git a/compiler/rustc_ast/src/ast_like.rs b/compiler/rustc_ast/src/ast_like.rs
index 9a24158..1a271b0 100644
--- a/compiler/rustc_ast/src/ast_like.rs
+++ b/compiler/rustc_ast/src/ast_like.rs
@@ -51,7 +51,6 @@ fn attrs(&self) -> &[Attribute] {
| Nonterminal::NtMeta(_)
| Nonterminal::NtPath(_)
| Nonterminal::NtVis(_)
- | Nonterminal::NtTT(_)
| Nonterminal::NtBlock(_)
| Nonterminal::NtIdent(..)
| Nonterminal::NtLifetime(_) => &[],
@@ -67,7 +66,6 @@ fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
| Nonterminal::NtMeta(_)
| Nonterminal::NtPath(_)
| Nonterminal::NtVis(_)
- | Nonterminal::NtTT(_)
| Nonterminal::NtBlock(_)
| Nonterminal::NtIdent(..)
| Nonterminal::NtLifetime(_) => {}
@@ -84,7 +82,7 @@ fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
Nonterminal::NtPath(path) => path.tokens_mut(),
Nonterminal::NtVis(vis) => vis.tokens_mut(),
Nonterminal::NtBlock(block) => block.tokens_mut(),
- Nonterminal::NtIdent(..) | Nonterminal::NtLifetime(..) | Nonterminal::NtTT(..) => None,
+ Nonterminal::NtIdent(..) | Nonterminal::NtLifetime(..) => None,
}
}
}
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 9d79fe5..32621eb 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -787,7 +787,6 @@ pub fn visit_interpolated<T: MutVisitor>(nt: &mut token::Nonterminal, vis: &mut
visit_lazy_tts(tokens, vis);
}
token::NtPath(path) => vis.visit_path(path),
- token::NtTT(tt) => visit_tt(tt, vis),
token::NtVis(visib) => vis.visit_vis(visib),
}
}
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index c367573..7df3858 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -6,7 +6,6 @@
use crate::ast;
use crate::ptr::P;
-use crate::tokenstream::TokenTree;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::Lrc;
@@ -680,7 +679,6 @@ pub enum Nonterminal {
NtMeta(P<ast::AttrItem>),
NtPath(ast::Path),
NtVis(ast::Visibility),
- NtTT(TokenTree),
}
// `Nonterminal` is used a lot. Make sure it doesn't unintentionally get bigger.
@@ -778,7 +776,6 @@ pub fn span(&self) -> Span {
NtMeta(attr_item) => attr_item.span(),
NtPath(path) => path.span,
NtVis(vis) => vis.span,
- NtTT(tt) => tt.span(),
}
}
}
@@ -790,7 +787,6 @@ fn eq(&self, rhs: &Self) -> bool {
ident_lhs == ident_rhs && is_raw_lhs == is_raw_rhs
}
(NtLifetime(ident_lhs), NtLifetime(ident_rhs)) => ident_lhs == ident_rhs,
- (NtTT(tt_lhs), NtTT(tt_rhs)) => tt_lhs == tt_rhs,
// FIXME: Assume that all "complex" nonterminal are not equal, we can't compare them
// correctly based on data from AST. This will prevent them from matching each other
// in macros. The comparison will become possible only when each nonterminal has an
@@ -813,7 +809,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
NtLiteral(..) => f.pad("NtLiteral(..)"),
NtMeta(..) => f.pad("NtMeta(..)"),
NtPath(..) => f.pad("NtPath(..)"),
- NtTT(..) => f.pad("NtTT(..)"),
NtVis(..) => f.pad("NtVis(..)"),
NtLifetime(..) => f.pad("NtLifetime(..)"),
}
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 8ba6a91..aba0b6a 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -122,7 +122,10 @@ fn ban_let_expr(&self, expr: &'a Expr, forbidden_let_reason: ForbiddenLetReason)
diag.note("only supported directly in conditions of `if` and `while` expressions");
diag.note("as well as when nested within `&&` and parentheses in those conditions");
if let ForbiddenLetReason::ForbiddenWithOr(span) = forbidden_let_reason {
- diag.span_note(span, "`||` operators are not allowed in let chain expressions");
+ diag.span_note(
+ span,
+ "`||` operators are not currently supported in let chain expressions",
+ );
}
diag.emit();
} else {
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index b2c6238..719fd27 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -714,7 +714,6 @@ fn nonterminal_to_string(&self, nt: &Nonterminal) -> String {
token::NtIdent(e, is_raw) => IdentPrinter::for_ast_ident(e, is_raw).to_string(),
token::NtLifetime(e) => e.to_string(),
token::NtLiteral(ref e) => self.expr_to_string(e),
- token::NtTT(ref tree) => self.tt_to_string(tree),
token::NtVis(ref e) => self.vis_to_string(e),
}
}
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 66a23eb..883f711 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -12,7 +12,7 @@
FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef,
ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm,
};
-use rustc_middle::ty::{self, suggest_constraining_type_params, PredicateKind, Ty};
+use rustc_middle::ty::{self, subst::Subst, suggest_constraining_type_params, PredicateKind, Ty};
use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
use rustc_span::symbol::sym;
use rustc_span::{BytePos, MultiSpan, Span};
@@ -151,6 +151,7 @@ pub(crate) fn report_use_of_moved_or_uninitialized(
.args_or_use()
})
.collect::<Vec<Span>>();
+
let reinits = maybe_reinitialized_locations.len();
if reinits == 1 {
err.span_label(reinit_spans[0], "this reinitialization might get skipped");
@@ -276,76 +277,23 @@ pub(crate) fn report_use_of_moved_or_uninitialized(
}
}
+ let opt_name =
+ self.describe_place_with_options(place.as_ref(), IncludingDowncast(true));
+ let note_msg = match opt_name {
+ Some(ref name) => format!("`{}`", name),
+ None => "value".to_owned(),
+ };
+ if self.suggest_borrow_fn_like(&mut err, ty, &move_site_vec, ¬e_msg) {
+ // Suppress the next suggestion since we don't want to put more bounds onto
+ // something that already has `Fn`-like bounds (or is a closure), so we can't
+ // restrict anyways.
+ } else {
+ self.suggest_adding_copy_bounds(&mut err, ty, span);
+ }
+
if needs_note {
- let opt_name =
- self.describe_place_with_options(place.as_ref(), IncludingDowncast(true));
- let note_msg = match opt_name {
- Some(ref name) => format!("`{}`", name),
- None => "value".to_owned(),
- };
-
- // Try to find predicates on *generic params* that would allow copying `ty`
- let tcx = self.infcx.tcx;
- let generics = tcx.generics_of(self.mir_def_id());
- if let Some(hir_generics) = tcx
- .typeck_root_def_id(self.mir_def_id().to_def_id())
- .as_local()
- .and_then(|def_id| tcx.hir().get_generics(def_id))
- {
- let predicates: Result<Vec<_>, _> = tcx.infer_ctxt().enter(|infcx| {
- let mut fulfill_cx =
- <dyn rustc_infer::traits::TraitEngine<'_>>::new(infcx.tcx);
-
- let copy_did = infcx.tcx.lang_items().copy_trait().unwrap();
- let cause = ObligationCause::new(
- span,
- self.mir_hir_id(),
- rustc_infer::traits::ObligationCauseCode::MiscObligation,
- );
- fulfill_cx.register_bound(
- &infcx,
- self.param_env,
- // Erase any region vids from the type, which may not be resolved
- infcx.tcx.erase_regions(ty),
- copy_did,
- cause,
- );
- // Select all, including ambiguous predicates
- let errors = fulfill_cx.select_all_or_error(&infcx);
-
- // Only emit suggestion if all required predicates are on generic
- errors
- .into_iter()
- .map(|err| match err.obligation.predicate.kind().skip_binder() {
- PredicateKind::Trait(predicate) => {
- match predicate.self_ty().kind() {
- ty::Param(param_ty) => Ok((
- generics.type_param(param_ty, tcx),
- predicate.trait_ref.print_only_trait_path().to_string(),
- )),
- _ => Err(()),
- }
- }
- _ => Err(()),
- })
- .collect()
- });
-
- if let Ok(predicates) = predicates {
- suggest_constraining_type_params(
- tcx,
- hir_generics,
- &mut err,
- predicates.iter().map(|(param, constraint)| {
- (param.name.as_str(), &**constraint, None)
- }),
- );
- }
- }
-
let span = if let Some(local) = place.as_local() {
- let decl = &self.body.local_decls[local];
- Some(decl.source_info.span)
+ Some(self.body.local_decls[local].source_info.span)
} else {
None
};
@@ -373,6 +321,144 @@ pub(crate) fn report_use_of_moved_or_uninitialized(
}
}
+ fn suggest_borrow_fn_like(
+ &self,
+ err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
+ ty: Ty<'tcx>,
+ move_sites: &[MoveSite],
+ value_name: &str,
+ ) -> bool {
+ let tcx = self.infcx.tcx;
+
+ // Find out if the predicates show that the type is a Fn or FnMut
+ let find_fn_kind_from_did = |predicates: &[(ty::Predicate<'tcx>, Span)], substs| {
+ predicates.iter().find_map(|(pred, _)| {
+ let pred = if let Some(substs) = substs {
+ pred.subst(tcx, substs).kind().skip_binder()
+ } else {
+ pred.kind().skip_binder()
+ };
+ if let ty::PredicateKind::Trait(pred) = pred && pred.self_ty() == ty {
+ if Some(pred.def_id()) == tcx.lang_items().fn_trait() {
+ return Some(hir::Mutability::Not);
+ } else if Some(pred.def_id()) == tcx.lang_items().fn_mut_trait() {
+ return Some(hir::Mutability::Mut);
+ }
+ }
+ None
+ })
+ };
+
+ // If the type is opaque/param/closure, and it is Fn or FnMut, let's suggest (mutably)
+ // borrowing the type, since `&mut F: FnMut` iff `F: FnMut` and similarly for `Fn`.
+ // These types seem reasonably opaque enough that they could be substituted with their
+ // borrowed variants in a function body when we see a move error.
+ let borrow_level = match ty.kind() {
+ ty::Param(_) => find_fn_kind_from_did(
+ tcx.explicit_predicates_of(self.mir_def_id().to_def_id()).predicates,
+ None,
+ ),
+ ty::Opaque(did, substs) => {
+ find_fn_kind_from_did(tcx.explicit_item_bounds(*did), Some(*substs))
+ }
+ ty::Closure(_, substs) => match substs.as_closure().kind() {
+ ty::ClosureKind::Fn => Some(hir::Mutability::Not),
+ ty::ClosureKind::FnMut => Some(hir::Mutability::Mut),
+ _ => None,
+ },
+ _ => None,
+ };
+
+ let Some(borrow_level) = borrow_level else { return false; };
+ let sugg = move_sites
+ .iter()
+ .map(|move_site| {
+ let move_out = self.move_data.moves[(*move_site).moi];
+ let moved_place = &self.move_data.move_paths[move_out.path].place;
+ let move_spans = self.move_spans(moved_place.as_ref(), move_out.source);
+ let move_span = move_spans.args_or_use();
+ let suggestion = if borrow_level == hir::Mutability::Mut {
+ "&mut ".to_string()
+ } else {
+ "&".to_string()
+ };
+ (move_span.shrink_to_lo(), suggestion)
+ })
+ .collect();
+ err.multipart_suggestion_verbose(
+ &format!(
+ "consider {}borrowing {value_name}",
+ if borrow_level == hir::Mutability::Mut { "mutably " } else { "" }
+ ),
+ sugg,
+ Applicability::MaybeIncorrect,
+ );
+ true
+ }
+
+ fn suggest_adding_copy_bounds(
+ &self,
+ err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
+ ty: Ty<'tcx>,
+ span: Span,
+ ) {
+ let tcx = self.infcx.tcx;
+ let generics = tcx.generics_of(self.mir_def_id());
+
+ let Some(hir_generics) = tcx
+ .typeck_root_def_id(self.mir_def_id().to_def_id())
+ .as_local()
+ .and_then(|def_id| tcx.hir().get_generics(def_id))
+ else { return; };
+ // Try to find predicates on *generic params* that would allow copying `ty`
+ let predicates: Result<Vec<_>, _> = tcx.infer_ctxt().enter(|infcx| {
+ let mut fulfill_cx = <dyn rustc_infer::traits::TraitEngine<'_>>::new(infcx.tcx);
+
+ let copy_did = infcx.tcx.lang_items().copy_trait().unwrap();
+ let cause = ObligationCause::new(
+ span,
+ self.mir_hir_id(),
+ rustc_infer::traits::ObligationCauseCode::MiscObligation,
+ );
+ fulfill_cx.register_bound(
+ &infcx,
+ self.param_env,
+ // Erase any region vids from the type, which may not be resolved
+ infcx.tcx.erase_regions(ty),
+ copy_did,
+ cause,
+ );
+ // Select all, including ambiguous predicates
+ let errors = fulfill_cx.select_all_or_error(&infcx);
+
+ // Only emit suggestion if all required predicates are on generic
+ errors
+ .into_iter()
+ .map(|err| match err.obligation.predicate.kind().skip_binder() {
+ PredicateKind::Trait(predicate) => match predicate.self_ty().kind() {
+ ty::Param(param_ty) => Ok((
+ generics.type_param(param_ty, tcx),
+ predicate.trait_ref.print_only_trait_path().to_string(),
+ )),
+ _ => Err(()),
+ },
+ _ => Err(()),
+ })
+ .collect()
+ });
+
+ if let Ok(predicates) = predicates {
+ suggest_constraining_type_params(
+ tcx,
+ hir_generics,
+ err,
+ predicates
+ .iter()
+ .map(|(param, constraint)| (param.name.as_str(), &**constraint, None)),
+ );
+ }
+ }
+
pub(crate) fn report_move_out_while_borrowed(
&mut self,
location: Location,
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index c77bbeb..6e551e9 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -787,7 +787,12 @@ fn maybe_body_id_of_fn(hir_map: Map<'_>, id: HirId) -> Option<BodyId> {
_,
[
Expr {
- kind: MethodCall(path_segment, ..),
+ kind:
+ MethodCall(
+ path_segment,
+ _args,
+ span,
+ ),
hir_id,
..
},
@@ -831,7 +836,7 @@ fn maybe_body_id_of_fn(hir_map: Map<'_>, id: HirId) -> Option<BodyId> {
if let Some(mut suggestions) = opt_suggestions {
if suggestions.peek().is_some() {
err.span_suggestions(
- path_segment.ident.span,
+ *span,
"use mutable method",
suggestions,
Applicability::MaybeIncorrect,
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 0b31e4b..0105602 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -14,6 +14,8 @@
use rustc_attr as attr;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
+
+#[cfg(parallel_compiler)]
use rustc_data_structures::sync::{par_iter, ParallelIterator};
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
@@ -622,34 +624,34 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
// This likely is a temporary measure. Once we don't have to support the
// non-parallel compiler anymore, we can compile CGUs end-to-end in
// parallel and get rid of the complicated scheduling logic.
+ #[cfg(parallel_compiler)]
let pre_compile_cgus = |cgu_reuse: &[CguReuse]| {
- if cfg!(parallel_compiler) {
- tcx.sess.time("compile_first_CGU_batch", || {
- // Try to find one CGU to compile per thread.
- let cgus: Vec<_> = cgu_reuse
- .iter()
- .enumerate()
- .filter(|&(_, reuse)| reuse == &CguReuse::No)
- .take(tcx.sess.threads())
- .collect();
+ tcx.sess.time("compile_first_CGU_batch", || {
+ // Try to find one CGU to compile per thread.
+ let cgus: Vec<_> = cgu_reuse
+ .iter()
+ .enumerate()
+ .filter(|&(_, reuse)| reuse == &CguReuse::No)
+ .take(tcx.sess.threads())
+ .collect();
- // Compile the found CGUs in parallel.
- let start_time = Instant::now();
+ // Compile the found CGUs in parallel.
+ let start_time = Instant::now();
- let pre_compiled_cgus = par_iter(cgus)
- .map(|(i, _)| {
- let module = backend.compile_codegen_unit(tcx, codegen_units[i].name());
- (i, module)
- })
- .collect();
+ let pre_compiled_cgus = par_iter(cgus)
+ .map(|(i, _)| {
+ let module = backend.compile_codegen_unit(tcx, codegen_units[i].name());
+ (i, module)
+ })
+ .collect();
- (pre_compiled_cgus, start_time.elapsed())
- })
- } else {
- (FxHashMap::default(), Duration::new(0, 0))
- }
+ (pre_compiled_cgus, start_time.elapsed())
+ })
};
+ #[cfg(not(parallel_compiler))]
+ let pre_compile_cgus = |_: &[CguReuse]| (FxHashMap::default(), Duration::new(0, 0));
+
let mut cgu_reuse = Vec::new();
let mut pre_compiled_cgus: Option<FxHashMap<usize, _>> = None;
let mut total_codegen_time = Duration::new(0, 0);
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index 2b8fa3b..17cfb6c 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -441,11 +441,19 @@ pub fn codegen_place(
.find(|elem| matches!(elem.1, mir::ProjectionElem::Deref))
{
base = elem.0 + 1;
- self.codegen_consume(
+ let cg_base = self.codegen_consume(
bx,
mir::PlaceRef { projection: &place_ref.projection[..elem.0], ..place_ref },
- )
- .deref(bx.cx())
+ );
+
+ // a box with a non-zst allocator should not be directly dereferenced
+ if cg_base.layout.ty.is_box() && !cg_base.layout.field(cx, 1).is_zst() {
+ let ptr = cg_base.extract_field(bx, 0).extract_field(bx, 0);
+
+ ptr.deref(bx.cx())
+ } else {
+ cg_base.deref(bx.cx())
+ }
} else {
bug!("using operand local {:?} as place", place_ref);
}
@@ -454,10 +462,8 @@ pub fn codegen_place(
for elem in place_ref.projection[base..].iter() {
cg_base = match elem.clone() {
mir::ProjectionElem::Deref => {
- // custom allocators can change box's abi, making it unable to be derefed directly
- if cg_base.layout.ty.is_box()
- && matches!(cg_base.layout.abi, Abi::Aggregate { .. } | Abi::Uninhabited)
- {
+ // a box with a non-zst allocator should not be directly dereferenced
+ if cg_base.layout.ty.is_box() && !cg_base.layout.field(cx, 1).is_zst() {
let ptr = cg_base.project_field(bx, 0).project_field(bx, 0);
bx.load_operand(ptr).deref(bx.cx())
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index b82e971..7cc8b5c 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -9,7 +9,7 @@
[dependencies]
arrayvec = { version = "0.7", default-features = false }
ena = "0.14"
-indexmap = { version = "1.8.0", features = ["rustc-rayon"] }
+indexmap = { version = "1.8.0" }
tracing = "0.1"
jobserver_crate = { version = "0.1.13", package = "jobserver" }
rustc_serialize = { path = "../rustc_serialize" }
@@ -17,8 +17,8 @@
rustc_graphviz = { path = "../rustc_graphviz" }
cfg-if = "0.1.2"
stable_deref_trait = "1.0.0"
-rayon = { version = "0.3.2", package = "rustc-rayon" }
-rayon-core = { version = "0.3.2", package = "rustc-rayon-core" }
+rayon = { version = "0.3.2", package = "rustc-rayon", optional = true }
+rayon-core = { version = "0.3.2", package = "rustc-rayon-core", optional = true }
rustc-hash = "1.1.0"
smallvec = { version = "1.6.1", features = ["const_generics", "union", "may_dangle"] }
rustc_index = { path = "../rustc_index", package = "rustc_index" }
@@ -36,3 +36,6 @@
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
memmap2 = "0.2.1"
+
+[features]
+rustc_use_parallel_compiler = ["indexmap/rustc-rayon", "rayon", "rayon-core"]
diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml
index 872f946..fd2ca5b 100644
--- a/compiler/rustc_driver/Cargo.toml
+++ b/compiler/rustc_driver/Cargo.toml
@@ -39,3 +39,5 @@
[features]
llvm = ['rustc_interface/llvm']
max_level_info = ['rustc_log/max_level_info']
+rustc_use_parallel_compiler = ['rustc_data_structures/rustc_use_parallel_compiler', 'rustc_interface/rustc_use_parallel_compiler',
+ 'rustc_middle/rustc_use_parallel_compiler']
diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs
index 5e97fc90..5a6a2b2 100644
--- a/compiler/rustc_expand/src/mbe/macro_parser.rs
+++ b/compiler/rustc_expand/src/mbe/macro_parser.rs
@@ -76,7 +76,7 @@
use crate::mbe::{self, SequenceRepetition, TokenTree};
use rustc_ast::token::{self, DocComment, Nonterminal, Token};
-use rustc_parse::parser::Parser;
+use rustc_parse::parser::{NtOrTt, Parser};
use rustc_session::parse::ParseSess;
use rustc_span::symbol::MacroRulesNormalizedIdent;
@@ -275,7 +275,7 @@ pub(super) fn count_names(ms: &[TokenTree]) -> usize {
}
/// `NamedMatch` is a pattern-match result for a single metavar. All
-/// `MatchedNtNonTt`s in the `NamedMatch` have the same non-terminal type
+/// `MatchedNonterminal`s in the `NamedMatch` have the same non-terminal type
/// (expr, item, etc).
///
/// The in-memory structure of a particular `NamedMatch` represents the match
@@ -306,17 +306,17 @@ pub(super) fn count_names(ms: &[TokenTree]) -> usize {
/// ```rust
/// MatchedSeq([
/// MatchedSeq([
-/// MatchedNtNonTt(a),
-/// MatchedNtNonTt(b),
-/// MatchedNtNonTt(c),
-/// MatchedNtNonTt(d),
+/// MatchedNonterminal(a),
+/// MatchedNonterminal(b),
+/// MatchedNonterminal(c),
+/// MatchedNonterminal(d),
/// ]),
/// MatchedSeq([
-/// MatchedNtNonTt(a),
-/// MatchedNtNonTt(b),
-/// MatchedNtNonTt(c),
-/// MatchedNtNonTt(d),
-/// MatchedNtNonTt(e),
+/// MatchedNonterminal(a),
+/// MatchedNonterminal(b),
+/// MatchedNonterminal(c),
+/// MatchedNonterminal(d),
+/// MatchedNonterminal(e),
/// ])
/// ])
/// ```
@@ -324,14 +324,11 @@ pub(super) fn count_names(ms: &[TokenTree]) -> usize {
crate enum NamedMatch {
MatchedSeq(Lrc<NamedMatchVec>),
- // This variant should never hold an `NtTT`. `MatchedNtTt` should be used
- // for that case.
- MatchedNtNonTt(Lrc<Nonterminal>),
+ // A metavar match of type `tt`.
+ MatchedTokenTree(rustc_ast::tokenstream::TokenTree),
- // `NtTT` is handled without any cloning when transcribing, unlike other
- // nonterminals. Therefore, an `Lrc` isn't helpful and causes unnecessary
- // allocations. Hence this separate variant.
- MatchedNtTt(rustc_ast::tokenstream::TokenTree),
+ // A metavar match of any type other than `tt`.
+ MatchedNonterminal(Lrc<Nonterminal>),
}
/// Takes a slice of token trees `ms` representing a matcher which successfully matched input
@@ -519,13 +516,14 @@ fn parse_tt_inner(
}
TokenTree::Token(t) => {
- // Doc comments cannot appear in a matcher.
- debug_assert!(!matches!(t, Token { kind: DocComment(..), .. }));
-
- // If the token matches, we can just advance the parser. Otherwise, this
- // match hash failed, there is nothing to do, and hopefully another item in
- // `cur_items` will match.
- if token_name_eq(&t, token) {
+ // If it's a doc comment, we just ignore it and move on to the next tt in
+ // the matcher. If the token matches, we can just advance the parser.
+ // Otherwise, this match has failed, there is nothing to do, and hopefully
+ // another item in `cur_items` will match.
+ if matches!(t, Token { kind: DocComment(..), .. }) {
+ item.idx += 1;
+ self.cur_items.push(item);
+ } else if token_name_eq(&t, token) {
item.idx += 1;
self.next_items.push(item);
}
@@ -677,8 +675,8 @@ pub(super) fn parse_tt(
Ok(nt) => nt,
};
let m = match nt {
- Nonterminal::NtTT(tt) => MatchedNtTt(tt),
- _ => MatchedNtNonTt(Lrc::new(nt)),
+ NtOrTt::Nt(nt) => MatchedNonterminal(Lrc::new(nt)),
+ NtOrTt::Tt(tt) => MatchedTokenTree(tt),
};
item.push_match(match_cur, m);
item.idx += 1;
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 7837de5..10b2b9f 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -4,7 +4,7 @@
use crate::mbe;
use crate::mbe::macro_check;
use crate::mbe::macro_parser::{Error, ErrorReported, Failure, Success, TtParser};
-use crate::mbe::macro_parser::{MatchedNtTt, MatchedSeq};
+use crate::mbe::macro_parser::{MatchedSeq, MatchedTokenTree};
use crate::mbe::transcribe::transcribe;
use rustc_ast as ast;
@@ -470,7 +470,7 @@ pub fn compile_declarative_macro(
MatchedSeq(ref s) => s
.iter()
.map(|m| {
- if let MatchedNtTt(ref tt) = *m {
+ if let MatchedTokenTree(ref tt) = *m {
let mut tts = vec![];
mbe::quoted::parse(
tt.clone().into(),
@@ -495,7 +495,7 @@ pub fn compile_declarative_macro(
MatchedSeq(ref s) => s
.iter()
.map(|m| {
- if let MatchedNtTt(ref tt) = *m {
+ if let MatchedTokenTree(ref tt) = *m {
let mut tts = vec![];
mbe::quoted::parse(
tt.clone().into(),
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index 228ed04..cd016bf 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -1,8 +1,8 @@
use crate::base::ExtCtxt;
-use crate::mbe::macro_parser::{MatchedNtNonTt, MatchedNtTt, MatchedSeq, NamedMatch};
+use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, MatchedTokenTree, NamedMatch};
use crate::mbe::{self, MetaVarExpr};
use rustc_ast::mut_visit::{self, MutVisitor};
-use rustc_ast::token::{self, Nonterminal, Token, TokenKind};
+use rustc_ast::token::{self, Token, TokenKind};
use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndSpacing};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::Lrc;
@@ -234,17 +234,16 @@ pub(super) fn transcribe<'a>(
let ident = MacroRulesNormalizedIdent::new(orignal_ident);
if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) {
match cur_matched {
- MatchedNtTt(ref tt) => {
+ MatchedTokenTree(ref tt) => {
// `tt`s are emitted into the output stream directly as "raw tokens",
// without wrapping them into groups.
let token = tt.clone();
result.push(token.into());
}
- MatchedNtNonTt(ref nt) => {
+ MatchedNonterminal(ref nt) => {
// Other variables are emitted into the output stream as groups with
// `Delimiter::None` to maintain parsing priorities.
// `Interpolated` is currently used for such groups in rustc parser.
- debug_assert!(!matches!(**nt, Nonterminal::NtTT(_)));
marker.visit_span(&mut sp);
let token = TokenTree::token(token::Interpolated(nt.clone()), sp);
result.push(token.into());
@@ -312,7 +311,7 @@ fn lookup_cur_matched<'a>(
let mut matched = matched;
for &(idx, _) in repeats {
match matched {
- MatchedNtTt(_) | MatchedNtNonTt(_) => break,
+ MatchedTokenTree(_) | MatchedNonterminal(_) => break,
MatchedSeq(ref ads) => matched = ads.get(idx).unwrap(),
}
}
@@ -402,7 +401,7 @@ fn lockstep_iter_size(
let name = MacroRulesNormalizedIdent::new(name);
match lookup_cur_matched(name, interpolations, repeats) {
Some(matched) => match matched {
- MatchedNtTt(_) | MatchedNtNonTt(_) => LockstepIterSize::Unconstrained,
+ MatchedTokenTree(_) | MatchedNonterminal(_) => LockstepIterSize::Unconstrained,
MatchedSeq(ref ads) => LockstepIterSize::Constraint(ads.len(), name),
},
_ => LockstepIterSize::Unconstrained,
@@ -449,7 +448,7 @@ fn count<'a>(
sp: &DelimSpan,
) -> PResult<'a, usize> {
match matched {
- MatchedNtTt(_) | MatchedNtNonTt(_) => {
+ MatchedTokenTree(_) | MatchedNonterminal(_) => {
if declared_lhs_depth == 0 {
return Err(cx.struct_span_err(
sp.entire(),
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 238145c..6e007b1 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -65,6 +65,7 @@
use rustc_hir::lang_items::LangItem;
use rustc_hir::{Item, ItemKind, Node};
use rustc_middle::dep_graph::DepContext;
+use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{
self,
error::TypeError,
@@ -1736,6 +1737,7 @@ enum Mismatch<'a> {
};
if should_suggest_fixes {
+ self.suggest_tuple_pattern(cause, &exp_found, diag);
self.suggest_as_ref_where_appropriate(span, &exp_found, diag);
self.suggest_accessing_field_where_appropriate(cause, &exp_found, diag);
self.suggest_await_on_expect_found(cause, span, &exp_found, diag);
@@ -1766,6 +1768,73 @@ enum Mismatch<'a> {
self.note_error_origin(diag, cause, exp_found, terr);
}
+ fn suggest_tuple_pattern(
+ &self,
+ cause: &ObligationCause<'tcx>,
+ exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
+ diag: &mut Diagnostic,
+ ) {
+ // Heavily inspired by `FnCtxt::suggest_compatible_variants`, with
+ // some modifications due to that being in typeck and this being in infer.
+ if let ObligationCauseCode::Pattern { .. } = cause.code() {
+ if let ty::Adt(expected_adt, substs) = exp_found.expected.kind() {
+ let compatible_variants: Vec<_> = expected_adt
+ .variants()
+ .iter()
+ .filter(|variant| {
+ variant.fields.len() == 1 && variant.ctor_kind == hir::def::CtorKind::Fn
+ })
+ .filter_map(|variant| {
+ let sole_field = &variant.fields[0];
+ let sole_field_ty = sole_field.ty(self.tcx, substs);
+ if same_type_modulo_infer(sole_field_ty, exp_found.found) {
+ let variant_path =
+ with_no_trimmed_paths!(self.tcx.def_path_str(variant.def_id));
+ // FIXME #56861: DRYer prelude filtering
+ if let Some(path) = variant_path.strip_prefix("std::prelude::") {
+ if let Some((_, path)) = path.split_once("::") {
+ return Some(path.to_string());
+ }
+ }
+ Some(variant_path)
+ } else {
+ None
+ }
+ })
+ .collect();
+ match &compatible_variants[..] {
+ [] => {}
+ [variant] => {
+ diag.multipart_suggestion_verbose(
+ &format!("try wrapping the pattern in `{}`", variant),
+ vec![
+ (cause.span.shrink_to_lo(), format!("{}(", variant)),
+ (cause.span.shrink_to_hi(), ")".to_string()),
+ ],
+ Applicability::MaybeIncorrect,
+ );
+ }
+ _ => {
+ // More than one matching variant.
+ diag.multipart_suggestions(
+ &format!(
+ "try wrapping the pattern in a variant of `{}`",
+ self.tcx.def_path_str(expected_adt.did())
+ ),
+ compatible_variants.into_iter().map(|variant| {
+ vec![
+ (cause.span.shrink_to_lo(), format!("{}(", variant)),
+ (cause.span.shrink_to_hi(), ")".to_string()),
+ ]
+ }),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ }
+ }
+ }
+ }
+
pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Binder<'tcx, Ty<'tcx>>> {
if let ty::Opaque(def_id, substs) = ty.kind() {
let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml
index e31119c..29d1cd0 100644
--- a/compiler/rustc_interface/Cargo.toml
+++ b/compiler/rustc_interface/Cargo.toml
@@ -10,8 +10,8 @@
libc = "0.2"
libloading = "0.7.1"
tracing = "0.1"
-rustc-rayon-core = "0.3.2"
-rayon = { version = "0.3.2", package = "rustc-rayon" }
+rustc-rayon-core = { version = "0.3.2", optional = true }
+rayon = { version = "0.3.2", package = "rustc-rayon", optional = true }
smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
rustc_ast = { path = "../rustc_ast" }
rustc_attr = { path = "../rustc_attr" }
@@ -57,3 +57,4 @@
[features]
llvm = ['rustc_codegen_llvm']
+rustc_use_parallel_compiler = ['rayon', 'rustc-rayon-core', 'rustc_query_impl/rustc_use_parallel_compiler']
diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml
index 9cfc5f5..cd281ea 100644
--- a/compiler/rustc_middle/Cargo.toml
+++ b/compiler/rustc_middle/Cargo.toml
@@ -12,8 +12,8 @@
either = "1.5.0"
gsgdt = "0.1.2"
tracing = "0.1"
-rustc-rayon = "0.3.2"
-rustc-rayon-core = "0.3.2"
+rustc-rayon = { version = "0.3.2", optional = true }
+rustc-rayon-core = { version = "0.3.2", optional = true }
polonius-engine = "0.13.0"
rustc_apfloat = { path = "../rustc_apfloat" }
rustc_attr = { path = "../rustc_attr" }
@@ -35,3 +35,6 @@
rustc_type_ir = { path = "../rustc_type_ir" }
rand = "0.8.4"
rand_xoshiro = "0.6.0"
+
+[features]
+rustc_use_parallel_compiler = ["rustc-rayon", "rustc-rayon-core"]
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index 1118caf..28c2a63 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -290,7 +290,6 @@ pub fn nt_to_tokenstream(
Nonterminal::NtMeta(ref attr) => convert_tokens(attr.tokens.as_ref()),
Nonterminal::NtPath(ref path) => convert_tokens(path.tokens.as_ref()),
Nonterminal::NtVis(ref vis) => convert_tokens(vis.tokens.as_ref()),
- Nonterminal::NtTT(ref tt) => Some(tt.clone().into()),
Nonterminal::NtExpr(ref expr) | Nonterminal::NtLiteral(ref expr) => {
prepend_attrs(&expr.attrs, expr.tokens.as_ref())
}
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index b5b628a..534fd0d 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -2369,6 +2369,34 @@ pub(super) fn incorrect_move_async_order_found(
Err(err)
}
+ crate fn maybe_recover_bounds_doubled_colon(&mut self, ty: &Ty) -> PResult<'a, ()> {
+ let TyKind::Path(qself, path) = &ty.kind else { return Ok(()) };
+ let qself_position = qself.as_ref().map(|qself| qself.position);
+ for (i, segments) in path.segments.windows(2).enumerate() {
+ if qself_position.map(|pos| i < pos).unwrap_or(false) {
+ continue;
+ }
+ if let [a, b] = segments {
+ let (a_span, b_span) = (a.span(), b.span());
+ let between_span = a_span.shrink_to_hi().to(b_span.shrink_to_lo());
+ if self.span_to_snippet(between_span).as_ref().map(|a| &a[..]) == Ok(":: ") {
+ let mut err = self.struct_span_err(
+ path.span.shrink_to_hi(),
+ "expected `:` followed by trait or lifetime",
+ );
+ err.span_suggestion(
+ between_span,
+ "use single colon",
+ ": ".to_owned(),
+ Applicability::MachineApplicable,
+ );
+ return Err(err);
+ }
+ }
+ }
+ Ok(())
+ }
+
/// Parse and throw away a parenthesized comma separated
/// sequence of patterns until `)` is reached.
fn skip_pat_list(&mut self) -> PResult<'a, ()> {
diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs
index d625080..29fe2b7 100644
--- a/compiler/rustc_parse/src/parser/generics.rs
+++ b/compiler/rustc_parse/src/parser/generics.rs
@@ -312,6 +312,7 @@ fn parse_ty_where_predicate(&mut self) -> PResult<'a, ast::WherePredicate> {
id: ast::DUMMY_NODE_ID,
}))
} else {
+ self.maybe_recover_bounds_doubled_colon(&ty)?;
self.unexpected()
}
}
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 3a2f193..5d244ef 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -19,7 +19,7 @@
pub use path::PathStyle;
use rustc_ast::ptr::P;
-use rustc_ast::token::{self, DelimToken, Token, TokenKind};
+use rustc_ast::token::{self, DelimToken, Nonterminal, Token, TokenKind};
use rustc_ast::tokenstream::AttributesData;
use rustc_ast::tokenstream::{self, DelimSpan, Spacing};
use rustc_ast::tokenstream::{TokenStream, TokenTree};
@@ -1507,3 +1507,9 @@ pub enum FlatToken {
/// handling of replace ranges.
Empty,
}
+
+#[derive(Debug)]
+pub enum NtOrTt {
+ Nt(Nonterminal),
+ Tt(TokenTree),
+}
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index 40902fa..c105fbf 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -1,12 +1,12 @@
use rustc_ast::ptr::P;
-use rustc_ast::token::{self, Nonterminal, NonterminalKind, Token};
+use rustc_ast::token::{self, NonterminalKind, Token};
use rustc_ast::AstLike;
use rustc_ast_pretty::pprust;
use rustc_errors::PResult;
use rustc_span::symbol::{kw, Ident};
use crate::parser::pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
-use crate::parser::{FollowedByType, ForceCollect, Parser, PathStyle};
+use crate::parser::{FollowedByType, ForceCollect, NtOrTt, Parser, PathStyle};
impl<'a> Parser<'a> {
/// Checks whether a non-terminal may begin with a particular token.
@@ -85,7 +85,7 @@ fn may_be_ident(nt: &token::Nonterminal) -> bool {
NonterminalKind::Lifetime => match token.kind {
token::Lifetime(_) => true,
token::Interpolated(ref nt) => {
- matches!(**nt, token::NtLifetime(_) | token::NtTT(_))
+ matches!(**nt, token::NtLifetime(_))
}
_ => false,
},
@@ -96,7 +96,7 @@ fn may_be_ident(nt: &token::Nonterminal) -> bool {
}
/// Parse a non-terminal (e.g. MBE `:pat` or `:ident`).
- pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, Nonterminal> {
+ pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, NtOrTt> {
// Any `Nonterminal` which stores its tokens (currently `NtItem` and `NtExpr`)
// needs to have them force-captured here.
// A `macro_rules!` invocation may pass a captured item/expr to a proc-macro,
@@ -104,6 +104,8 @@ pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, Nonter
// in advance whether or not a proc-macro will be (transitively) invoked,
// we always capture tokens for any `Nonterminal` which needs them.
let mut nt = match kind {
+ // Note that TT is treated differently to all the others.
+ NonterminalKind::TT => return Ok(NtOrTt::Tt(self.parse_token_tree())),
NonterminalKind::Item => match self.parse_item(ForceCollect::Yes)? {
Some(item) => token::NtItem(item),
None => {
@@ -124,9 +126,12 @@ pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, Nonter
NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr { .. } => {
token::NtPat(self.collect_tokens_no_attrs(|this| match kind {
NonterminalKind::PatParam { .. } => this.parse_pat_no_top_alt(None),
- NonterminalKind::PatWithOr { .. } => {
- this.parse_pat_allow_top_alt(None, RecoverComma::No, RecoverColon::No, CommaRecoveryMode::EitherTupleOrPipe)
- }
+ NonterminalKind::PatWithOr { .. } => this.parse_pat_allow_top_alt(
+ None,
+ RecoverComma::No,
+ RecoverColon::No,
+ CommaRecoveryMode::EitherTupleOrPipe,
+ ),
_ => unreachable!(),
})?)
}
@@ -139,9 +144,10 @@ pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, Nonter
)
}
- NonterminalKind::Ty => {
- token::NtTy(self.collect_tokens_no_attrs(|this| this.parse_no_question_mark_recover())?)
- }
+ NonterminalKind::Ty => token::NtTy(
+ self.collect_tokens_no_attrs(|this| this.parse_no_question_mark_recover())?,
+ ),
+
// this could be handled like a token, since it is one
NonterminalKind::Ident
if let Some((ident, is_raw)) = get_macro_ident(&self.token) =>
@@ -158,7 +164,6 @@ pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, Nonter
self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?,
),
NonterminalKind::Meta => token::NtMeta(P(self.parse_attr_item(true)?)),
- NonterminalKind::TT => token::NtTT(self.parse_token_tree()),
NonterminalKind::Vis => token::NtVis(
self.collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?,
),
@@ -183,7 +188,7 @@ pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, Nonter
);
}
- Ok(nt)
+ Ok(NtOrTt::Nt(nt))
}
}
diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml
index f1899a6..b7502c4 100644
--- a/compiler/rustc_query_impl/Cargo.toml
+++ b/compiler/rustc_query_impl/Cargo.toml
@@ -8,7 +8,7 @@
[dependencies]
measureme = "10.0.0"
-rustc-rayon-core = "0.3.2"
+rustc-rayon-core = { version = "0.3.2", optional = true }
rustc_ast = { path = "../rustc_ast" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
@@ -20,3 +20,6 @@
rustc_serialize = { path = "../rustc_serialize" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
+
+[features]
+rustc_use_parallel_compiler = ["rustc-rayon-core", "rustc_query_system/rustc_use_parallel_compiler"]
diff --git a/compiler/rustc_query_system/Cargo.toml b/compiler/rustc_query_system/Cargo.toml
index 79f791e..8a35121 100644
--- a/compiler/rustc_query_system/Cargo.toml
+++ b/compiler/rustc_query_system/Cargo.toml
@@ -9,7 +9,7 @@
[dependencies]
rustc_arena = { path = "../rustc_arena" }
tracing = "0.1"
-rustc-rayon-core = "0.3.2"
+rustc-rayon-core = { version = "0.3.2", optional = true }
rustc_ast = { path = "../rustc_ast" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
@@ -23,3 +23,6 @@
rustc_target = { path = "../rustc_target" }
parking_lot = "0.11"
smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+
+[features]
+rustc_use_parallel_compiler = ["rustc-rayon-core"]
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 038ba22..c8ca513 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -696,14 +696,7 @@ fn restrict_assoc_type_in_where_clause(&mut self, span: Span, err: &mut Diagnost
) = &bounded_ty.kind
{
// use this to verify that ident is a type param.
- let Ok(Some(partial_res)) = self.resolve_qpath_anywhere(
- None,
- &Segment::from_path(path),
- Namespace::TypeNS,
- span,
- true,
- Finalize::No,
- ) else {
+ let Some(partial_res) = self.r.partial_res_map.get(&bounded_ty.id) else {
return false;
};
if !(matches!(
@@ -718,16 +711,10 @@ fn restrict_assoc_type_in_where_clause(&mut self, span: Span, err: &mut Diagnost
return false;
};
- if let ast::TyKind::Path(None, type_param_path) = &ty.peel_refs().kind {
+ let peeled_ty = ty.peel_refs();
+ if let ast::TyKind::Path(None, type_param_path) = &peeled_ty.kind {
// Confirm that the `SelfTy` is a type parameter.
- let Ok(Some(partial_res)) = self.resolve_qpath_anywhere(
- None,
- &Segment::from_path(type_param_path),
- Namespace::TypeNS,
- span,
- true,
- Finalize::No,
- ) else {
+ let Some(partial_res) = self.r.partial_res_map.get(&peeled_ty.id) else {
return false;
};
if !(matches!(
diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs
index 58e5c93..7f5ab8e 100644
--- a/compiler/rustc_typeck/src/check/demand.rs
+++ b/compiler/rustc_typeck/src/check/demand.rs
@@ -268,10 +268,6 @@ fn suggest_compatible_variants(
expr_ty: Ty<'tcx>,
) {
if let ty::Adt(expected_adt, substs) = expected.kind() {
- if !expected_adt.is_enum() {
- return;
- }
-
// If the expression is of type () and it's the return expression of a block,
// we suggest adding a separate return expression instead.
// (To avoid things like suggesting `Ok(while .. { .. })`.)
@@ -336,7 +332,9 @@ fn suggest_compatible_variants(
let compatible_variants: Vec<String> = expected_adt
.variants()
.iter()
- .filter(|variant| variant.fields.len() == 1)
+ .filter(|variant| {
+ variant.fields.len() == 1 && variant.ctor_kind == hir::def::CtorKind::Fn
+ })
.filter_map(|variant| {
let sole_field = &variant.fields[0];
let sole_field_ty = sole_field.ty(self.tcx, substs);
diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs
index e0dbe02..9b37985 100644
--- a/compiler/rustc_typeck/src/check/op.rs
+++ b/compiler/rustc_typeck/src/check/op.rs
@@ -299,52 +299,52 @@ fn check_overloaded_binop(
IsAssign::No => {
let (message, missing_trait, use_output) = match op.node {
hir::BinOpKind::Add => (
- format!("cannot add `{}` to `{}`", rhs_ty, lhs_ty),
+ format!("cannot add `{rhs_ty}` to `{lhs_ty}`"),
Some("std::ops::Add"),
true,
),
hir::BinOpKind::Sub => (
- format!("cannot subtract `{}` from `{}`", rhs_ty, lhs_ty),
+ format!("cannot subtract `{rhs_ty}` from `{lhs_ty}`"),
Some("std::ops::Sub"),
true,
),
hir::BinOpKind::Mul => (
- format!("cannot multiply `{}` by `{}`", lhs_ty, rhs_ty),
+ format!("cannot multiply `{lhs_ty}` by `{rhs_ty}`"),
Some("std::ops::Mul"),
true,
),
hir::BinOpKind::Div => (
- format!("cannot divide `{}` by `{}`", lhs_ty, rhs_ty),
+ format!("cannot divide `{lhs_ty}` by `{rhs_ty}`"),
Some("std::ops::Div"),
true,
),
hir::BinOpKind::Rem => (
- format!("cannot mod `{}` by `{}`", lhs_ty, rhs_ty),
+ format!("cannot mod `{lhs_ty}` by `{rhs_ty}`"),
Some("std::ops::Rem"),
true,
),
hir::BinOpKind::BitAnd => (
- format!("no implementation for `{} & {}`", lhs_ty, rhs_ty),
+ format!("no implementation for `{lhs_ty} & {rhs_ty}`"),
Some("std::ops::BitAnd"),
true,
),
hir::BinOpKind::BitXor => (
- format!("no implementation for `{} ^ {}`", lhs_ty, rhs_ty),
+ format!("no implementation for `{lhs_ty} ^ {rhs_ty}`"),
Some("std::ops::BitXor"),
true,
),
hir::BinOpKind::BitOr => (
- format!("no implementation for `{} | {}`", lhs_ty, rhs_ty),
+ format!("no implementation for `{lhs_ty} | {rhs_ty}`"),
Some("std::ops::BitOr"),
true,
),
hir::BinOpKind::Shl => (
- format!("no implementation for `{} << {}`", lhs_ty, rhs_ty),
+ format!("no implementation for `{lhs_ty} << {rhs_ty}`"),
Some("std::ops::Shl"),
true,
),
hir::BinOpKind::Shr => (
- format!("no implementation for `{} >> {}`", lhs_ty, rhs_ty),
+ format!("no implementation for `{lhs_ty} >> {rhs_ty}`"),
Some("std::ops::Shr"),
true,
),
@@ -477,8 +477,7 @@ fn check_overloaded_binop(
// When we know that a missing bound is responsible, we don't show
// this note as it is redundant.
err.note(&format!(
- "the trait `{}` is not implemented for `{}`",
- missing_trait, lhs_ty
+ "the trait `{missing_trait}` is not implemented for `{lhs_ty}`"
));
}
} else {
@@ -679,19 +678,17 @@ pub fn check_user_unop(
};
let mut visitor = TypeParamVisitor(vec![]);
visitor.visit_ty(operand_ty);
- if let [ty] = &visitor.0[..] {
- if let ty::Param(p) = *operand_ty.kind() {
- suggest_constraining_param(
- self.tcx,
- self.body_id,
- &mut err,
- *ty,
- operand_ty,
- missing_trait,
- p,
- true,
- );
- }
+ if let [ty] = &visitor.0[..] && let ty::Param(p) = *operand_ty.kind() {
+ suggest_constraining_param(
+ self.tcx,
+ self.body_id,
+ &mut err,
+ *ty,
+ operand_ty,
+ missing_trait,
+ p,
+ true,
+ );
}
let sp = self.tcx.sess.source_map().start_point(ex.span);
@@ -722,10 +719,9 @@ pub fn check_user_unop(
err.span_suggestion(
ex.span,
&format!(
- "you may have meant the maximum value of `{}`",
- actual
+ "you may have meant the maximum value of `{actual}`",
),
- format!("{}::MAX", actual),
+ format!("{actual}::MAX"),
Applicability::MaybeIncorrect,
);
}
@@ -988,7 +984,7 @@ fn suggest_constraining_param(
set_output: bool,
) {
let hir = tcx.hir();
- let msg = &format!("`{}` might need a bound for `{}`", lhs_ty, missing_trait);
+ let msg = &format!("`{lhs_ty}` might need a bound for `{missing_trait}`");
// Try to find the def-id and details for the parameter p. We have only the index,
// so we have to find the enclosing function's def-id, then look through its declared
// generic parameters to get the declaration.
@@ -1002,13 +998,13 @@ fn suggest_constraining_param(
.as_ref()
.and_then(|node| node.generics())
{
- let output = if set_output { format!("<Output = {}>", rhs_ty) } else { String::new() };
+ let output = if set_output { format!("<Output = {rhs_ty}>") } else { String::new() };
suggest_constraining_type_param(
tcx,
generics,
&mut err,
- &format!("{}", lhs_ty),
- &format!("{}{}", missing_trait, output),
+ &lhs_ty.to_string(),
+ &format!("{missing_trait}{output}"),
None,
);
} else {
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index ea651c0..3ddc9ac 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -895,7 +895,7 @@ pub unsafe fn from_raw(ptr: *const T) -> Self {
// Reverse the offset to find the original RcBox.
let rc_ptr =
- unsafe { (ptr as *mut RcBox<T>).set_ptr_value((ptr as *mut u8).offset(-offset)) };
+ unsafe { (ptr as *mut u8).offset(-offset).with_metadata_of(ptr as *mut RcBox<T>) };
unsafe { Self::from_ptr(rc_ptr) }
}
@@ -1338,7 +1338,7 @@ unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox<T> {
Self::allocate_for_layout(
Layout::for_value(&*ptr),
|layout| Global.allocate(layout),
- |mem| (ptr as *mut RcBox<T>).set_ptr_value(mem),
+ |mem| mem.with_metadata_of(ptr as *mut RcBox<T>),
)
}
}
@@ -2264,7 +2264,7 @@ pub unsafe fn from_raw(ptr: *const T) -> Self {
let offset = unsafe { data_offset(ptr) };
// Thus, we reverse the offset to get the whole RcBox.
// SAFETY: the pointer originated from a Weak, so this offset is safe.
- unsafe { (ptr as *mut RcBox<T>).set_ptr_value((ptr as *mut u8).offset(-offset)) }
+ unsafe { (ptr as *mut u8).offset(-offset).with_metadata_of(ptr as *mut RcBox<T>) }
};
// SAFETY: we now have recovered the original Weak pointer, so can create the Weak.
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index ba31872..e2b9890 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -895,7 +895,8 @@ pub unsafe fn from_raw(ptr: *const T) -> Self {
let offset = data_offset(ptr);
// Reverse the offset to find the original ArcInner.
- let arc_ptr = (ptr as *mut ArcInner<T>).set_ptr_value((ptr as *mut u8).offset(-offset));
+ let arc_ptr =
+ (ptr as *mut u8).offset(-offset).with_metadata_of(ptr as *mut ArcInner<T>);
Self::from_ptr(arc_ptr)
}
@@ -1182,7 +1183,7 @@ unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner<T> {
Self::allocate_for_layout(
Layout::for_value(&*ptr),
|layout| Global.allocate(layout),
- |mem| (ptr as *mut ArcInner<T>).set_ptr_value(mem) as *mut ArcInner<T>,
+ |mem| mem.with_metadata_of(ptr as *mut ArcInner<T>),
)
}
}
@@ -1888,7 +1889,7 @@ pub unsafe fn from_raw(ptr: *const T) -> Self {
let offset = unsafe { data_offset(ptr) };
// Thus, we reverse the offset to get the whole RcBox.
// SAFETY: the pointer originated from a Weak, so this offset is safe.
- unsafe { (ptr as *mut ArcInner<T>).set_ptr_value((ptr as *mut u8).offset(-offset)) }
+ unsafe { (ptr as *mut u8).offset(-offset).with_metadata_of(ptr as *mut ArcInner<T>) }
};
// SAFETY: we now have recovered the original Weak pointer, so can create the Weak.
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index dca8ffa..c09f642 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -809,6 +809,7 @@ pub fn escape_ascii(self) -> ascii::EscapeDefault {
ascii::escape_default(self)
}
+ #[inline]
pub(crate) const fn is_utf8_char_boundary(self) -> bool {
// This is bit magic equivalent to: b < 128 || b >= 192
(self as i8) >= -0x40
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 8cdd981..74c6437 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -48,6 +48,50 @@ pub const fn cast<U>(self) -> *const U {
self as _
}
+ /// Use the pointer value in a new pointer of another type.
+ ///
+ /// In case `val` is a (fat) pointer to an unsized type, this operation
+ /// will ignore the pointer part, whereas for (thin) pointers to sized
+ /// types, this has the same effect as a simple cast.
+ ///
+ /// The resulting pointer will have provenance of `self`, i.e., for a fat
+ /// pointer, this operation is semantically the same as creating a new
+ /// fat pointer with the data pointer value of `self` but the metadata of
+ /// `val`.
+ ///
+ /// # Examples
+ ///
+ /// This function is primarily useful for allowing byte-wise pointer
+ /// arithmetic on potentially fat pointers:
+ ///
+ /// ```
+ /// #![feature(set_ptr_value)]
+ /// # use core::fmt::Debug;
+ /// let arr: [i32; 3] = [1, 2, 3];
+ /// let mut ptr = arr.as_ptr() as *const dyn Debug;
+ /// let thin = ptr as *const u8;
+ /// unsafe {
+ /// ptr = thin.add(8).with_metadata_of(ptr);
+ /// # assert_eq!(*(ptr as *const i32), 3);
+ /// println!("{:?}", &*ptr); // will print "3"
+ /// }
+ /// ```
+ #[unstable(feature = "set_ptr_value", issue = "75091")]
+ #[must_use = "returns a new pointer rather than modifying its argument"]
+ #[inline]
+ pub fn with_metadata_of<U>(self, mut val: *const U) -> *const U
+ where
+ U: ?Sized,
+ {
+ let target = &mut val as *mut *const U as *mut *const u8;
+ // SAFETY: In case of a thin pointer, this operations is identical
+ // to a simple assignment. In case of a fat pointer, with the current
+ // fat pointer layout implementation, the first field of such a
+ // pointer is always the data pointer, which is likewise assigned.
+ unsafe { *target = self as *const u8 };
+ val
+ }
+
/// Changes constness without changing the type.
///
/// This is a bit safer than `as` because it wouldn't silently change the type if the code is
@@ -764,47 +808,6 @@ pub const fn wrapping_sub(self, count: usize) -> Self
self.wrapping_offset((count as isize).wrapping_neg())
}
- /// Sets the pointer value to `ptr`.
- ///
- /// In case `self` is a (fat) pointer to an unsized type, this operation
- /// will only affect the pointer part, whereas for (thin) pointers to
- /// sized types, this has the same effect as a simple assignment.
- ///
- /// The resulting pointer will have provenance of `val`, i.e., for a fat
- /// pointer, this operation is semantically the same as creating a new
- /// fat pointer with the data pointer value of `val` but the metadata of
- /// `self`.
- ///
- /// # Examples
- ///
- /// This function is primarily useful for allowing byte-wise pointer
- /// arithmetic on potentially fat pointers:
- ///
- /// ```
- /// #![feature(set_ptr_value)]
- /// # use core::fmt::Debug;
- /// let arr: [i32; 3] = [1, 2, 3];
- /// let mut ptr = arr.as_ptr() as *const dyn Debug;
- /// let thin = ptr as *const u8;
- /// unsafe {
- /// ptr = ptr.set_ptr_value(thin.add(8));
- /// # assert_eq!(*(ptr as *const i32), 3);
- /// println!("{:?}", &*ptr); // will print "3"
- /// }
- /// ```
- #[unstable(feature = "set_ptr_value", issue = "75091")]
- #[must_use = "returns a new pointer rather than modifying its argument"]
- #[inline]
- pub fn set_ptr_value(mut self, val: *const u8) -> Self {
- let thin = &mut self as *mut *const T as *mut *const u8;
- // SAFETY: In case of a thin pointer, this operations is identical
- // to a simple assignment. In case of a fat pointer, with the current
- // fat pointer layout implementation, the first field of such a
- // pointer is always the data pointer, which is likewise assigned.
- unsafe { *thin = val };
- self
- }
-
/// Reads the value from `self` without moving it. This leaves the
/// memory in `self` unchanged.
///
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 0c5b16a..7e48eac 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -47,6 +47,50 @@ pub const fn cast<U>(self) -> *mut U {
self as _
}
+ /// Use the pointer value in a new pointer of another type.
+ ///
+ /// In case `val` is a (fat) pointer to an unsized type, this operation
+ /// will ignore the pointer part, whereas for (thin) pointers to sized
+ /// types, this has the same effect as a simple cast.
+ ///
+ /// The resulting pointer will have provenance of `self`, i.e., for a fat
+ /// pointer, this operation is semantically the same as creating a new
+ /// fat pointer with the data pointer value of `self` but the metadata of
+ /// `val`.
+ ///
+ /// # Examples
+ ///
+ /// This function is primarily useful for allowing byte-wise pointer
+ /// arithmetic on potentially fat pointers:
+ ///
+ /// ```
+ /// #![feature(set_ptr_value)]
+ /// # use core::fmt::Debug;
+ /// let mut arr: [i32; 3] = [1, 2, 3];
+ /// let mut ptr = arr.as_mut_ptr() as *mut dyn Debug;
+ /// let thin = ptr as *mut u8;
+ /// unsafe {
+ /// ptr = thin.add(8).with_metadata_of(ptr);
+ /// # assert_eq!(*(ptr as *mut i32), 3);
+ /// println!("{:?}", &*ptr); // will print "3"
+ /// }
+ /// ```
+ #[unstable(feature = "set_ptr_value", issue = "75091")]
+ #[must_use = "returns a new pointer rather than modifying its argument"]
+ #[inline]
+ pub fn with_metadata_of<U>(self, mut val: *mut U) -> *mut U
+ where
+ U: ?Sized,
+ {
+ let target = &mut val as *mut *mut U as *mut *mut u8;
+ // SAFETY: In case of a thin pointer, this operations is identical
+ // to a simple assignment. In case of a fat pointer, with the current
+ // fat pointer layout implementation, the first field of such a
+ // pointer is always the data pointer, which is likewise assigned.
+ unsafe { *target = self as *mut u8 };
+ val
+ }
+
/// Changes constness without changing the type.
///
/// This is a bit safer than `as` because it wouldn't silently change the type if the code is
@@ -878,47 +922,6 @@ pub const fn wrapping_sub(self, count: usize) -> Self
self.wrapping_offset((count as isize).wrapping_neg())
}
- /// Sets the pointer value to `ptr`.
- ///
- /// In case `self` is a (fat) pointer to an unsized type, this operation
- /// will only affect the pointer part, whereas for (thin) pointers to
- /// sized types, this has the same effect as a simple assignment.
- ///
- /// The resulting pointer will have provenance of `val`, i.e., for a fat
- /// pointer, this operation is semantically the same as creating a new
- /// fat pointer with the data pointer value of `val` but the metadata of
- /// `self`.
- ///
- /// # Examples
- ///
- /// This function is primarily useful for allowing byte-wise pointer
- /// arithmetic on potentially fat pointers:
- ///
- /// ```
- /// #![feature(set_ptr_value)]
- /// # use core::fmt::Debug;
- /// let mut arr: [i32; 3] = [1, 2, 3];
- /// let mut ptr = arr.as_mut_ptr() as *mut dyn Debug;
- /// let thin = ptr as *mut u8;
- /// unsafe {
- /// ptr = ptr.set_ptr_value(thin.add(8));
- /// # assert_eq!(*(ptr as *mut i32), 3);
- /// println!("{:?}", &*ptr); // will print "3"
- /// }
- /// ```
- #[unstable(feature = "set_ptr_value", issue = "75091")]
- #[must_use = "returns a new pointer rather than modifying its argument"]
- #[inline]
- pub fn set_ptr_value(mut self, val: *mut u8) -> Self {
- let thin = &mut self as *mut *mut T as *mut *mut u8;
- // SAFETY: In case of a thin pointer, this operations is identical
- // to a simple assignment. In case of a fat pointer, with the current
- // fat pointer layout implementation, the first field of such a
- // pointer is always the data pointer, which is likewise assigned.
- unsafe { *thin = val };
- self
- }
-
/// Reads the value from `self` without moving it. This leaves the
/// memory in `self` unchanged.
///
diff --git a/library/std/src/env.rs b/library/std/src/env.rs
index 05f08c4..f03d298 100644
--- a/library/std/src/env.rs
+++ b/library/std/src/env.rs
@@ -25,9 +25,11 @@
///
/// # Platform-specific behavior
///
-/// This function currently corresponds to the `getcwd` function on Unix
+/// This function [currently] corresponds to the `getcwd` function on Unix
/// and the `GetCurrentDirectoryW` function on Windows.
///
+/// [currently]: crate::io#platform-specific-behavior
+///
/// # Errors
///
/// Returns an [`Err`] if the current working directory value is invalid.
@@ -56,11 +58,13 @@ pub fn current_dir() -> io::Result<PathBuf> {
///
/// # Platform-specific behavior
///
-/// This function currently corresponds to the `chdir` function on Unix
+/// This function [currently] corresponds to the `chdir` function on Unix
/// and the `SetCurrentDirectoryW` function on Windows.
///
/// Returns an [`Err`] if the operation fails.
///
+/// [currently]: crate::io#platform-specific-behavior
+///
/// # Examples
///
/// ```
diff --git a/library/std/src/io/error/repr_bitpacked.rs b/library/std/src/io/error/repr_bitpacked.rs
index 1a0538f..208d5a8 100644
--- a/library/std/src/io/error/repr_bitpacked.rs
+++ b/library/std/src/io/error/repr_bitpacked.rs
@@ -104,6 +104,7 @@
use super::{Custom, ErrorData, ErrorKind, SimpleMessage};
use alloc::boxed::Box;
+use core::marker::PhantomData;
use core::mem::{align_of, size_of};
use core::ptr::NonNull;
@@ -114,8 +115,17 @@
const TAG_OS: usize = 0b10;
const TAG_SIMPLE: usize = 0b11;
+/// The internal representation.
+///
+/// See the module docs for more, this is just a way to hack in a check that we
+/// indeed are not unwind-safe.
+///
+/// ```compile_fail,E0277
+/// fn is_unwind_safe<T: core::panic::UnwindSafe>() {}
+/// is_unwind_safe::<std::io::Error>();
+/// ```
#[repr(transparent)]
-pub(super) struct Repr(NonNull<()>);
+pub(super) struct Repr(NonNull<()>, PhantomData<ErrorData<Box<Custom>>>);
// All the types `Repr` stores internally are Send + Sync, and so is it.
unsafe impl Send for Repr {}
@@ -145,7 +155,7 @@ pub(super) fn new_custom(b: Box<Custom>) -> Self {
// box, and `TAG_CUSTOM` just... isn't zero -- it's `0b01`). Therefore,
// `TAG_CUSTOM + p` isn't zero and so `tagged` can't be, and the
// `new_unchecked` is safe.
- let res = Self(unsafe { NonNull::new_unchecked(tagged) });
+ let res = Self(unsafe { NonNull::new_unchecked(tagged) }, PhantomData);
// quickly smoke-check we encoded the right thing (This generally will
// only run in libstd's tests, unless the user uses -Zbuild-std)
debug_assert!(matches!(res.data(), ErrorData::Custom(_)), "repr(custom) encoding failed");
@@ -156,7 +166,7 @@ pub(super) fn new_custom(b: Box<Custom>) -> Self {
pub(super) fn new_os(code: i32) -> Self {
let utagged = ((code as usize) << 32) | TAG_OS;
// Safety: `TAG_OS` is not zero, so the result of the `|` is not 0.
- let res = Self(unsafe { NonNull::new_unchecked(utagged as *mut ()) });
+ let res = Self(unsafe { NonNull::new_unchecked(utagged as *mut ()) }, PhantomData);
// quickly smoke-check we encoded the right thing (This generally will
// only run in libstd's tests, unless the user uses -Zbuild-std)
debug_assert!(
@@ -170,7 +180,7 @@ pub(super) fn new_os(code: i32) -> Self {
pub(super) fn new_simple(kind: ErrorKind) -> Self {
let utagged = ((kind as usize) << 32) | TAG_SIMPLE;
// Safety: `TAG_SIMPLE` is not zero, so the result of the `|` is not 0.
- let res = Self(unsafe { NonNull::new_unchecked(utagged as *mut ()) });
+ let res = Self(unsafe { NonNull::new_unchecked(utagged as *mut ()) }, PhantomData);
// quickly smoke-check we encoded the right thing (This generally will
// only run in libstd's tests, unless the user uses -Zbuild-std)
debug_assert!(
@@ -184,7 +194,7 @@ pub(super) fn new_simple(kind: ErrorKind) -> Self {
#[inline]
pub(super) const fn new_simple_message(m: &'static SimpleMessage) -> Self {
// Safety: References are never null.
- Self(unsafe { NonNull::new_unchecked(m as *const _ as *mut ()) })
+ Self(unsafe { NonNull::new_unchecked(m as *const _ as *mut ()) }, PhantomData)
}
#[inline]
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index b6edf8b..d3c8d86 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -1417,6 +1417,15 @@ fn from(file: fs::File) -> Stdio {
/// For proper error reporting of failed processes, print the value of `ExitStatus` or
/// `ExitStatusError` using their implementations of [`Display`](crate::fmt::Display).
///
+/// # Differences from `ExitStatus`
+///
+/// `ExitCode` is intended for terminating the currently running process, via
+/// the `Termination` trait, in contrast to [`ExitStatus`], which represents the
+/// termination of a child process. These APIs are separate due to platform
+/// compatibility differences and their expected usage; it is not generally
+/// possible to exactly reproduce an ExitStatus from a child for the current
+/// process after the fact.
+///
/// [`status`]: Command::status
/// [`wait`]: Child::wait
//
@@ -1649,8 +1658,16 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
#[unstable(feature = "exit_status_error", issue = "84908")]
impl crate::error::Error for ExitStatusError {}
-/// This type represents the status code a process can return to its
-/// parent under normal termination.
+/// This type represents the status code the current process can return
+/// to its parent under normal termination.
+///
+/// `ExitCode` is intended to be consumed only by the standard library (via
+/// [`Termination::report()`]), and intentionally does not provide accessors like
+/// `PartialEq`, `Eq`, or `Hash`. Instead the standard library provides the
+/// canonical `SUCCESS` and `FAILURE` exit codes as well as `From<u8> for
+/// ExitCode` for constructing other arbitrary exit codes.
+///
+/// # Portability
///
/// Numeric values used in this type don't have portable meanings, and
/// different platforms may mask different amounts of them.
@@ -1661,52 +1678,78 @@ impl crate::error::Error for ExitStatusError {}
/// [`SUCCESS`]: ExitCode::SUCCESS
/// [`FAILURE`]: ExitCode::FAILURE
///
-/// **Warning**: While various forms of this were discussed in [RFC #1937],
-/// it was ultimately cut from that RFC, and thus this type is more subject
-/// to change even than the usual unstable item churn.
+/// # Differences from `ExitStatus`
///
-/// [RFC #1937]: https://github.com/rust-lang/rfcs/pull/1937
+/// `ExitCode` is intended for terminating the currently running process, via
+/// the `Termination` trait, in contrast to [`ExitStatus`], which represents the
+/// termination of a child process. These APIs are separate due to platform
+/// compatibility differences and their expected usage; it is not generally
+/// possible to exactly reproduce an ExitStatus from a child for the current
+/// process after the fact.
+///
+/// # Examples
+///
+/// `ExitCode` can be returned from the `main` function of a crate, as it implements
+/// [`Termination`]:
+///
+/// ```
+/// use std::process::ExitCode;
+/// # fn check_foo() -> bool { true }
+///
+/// fn main() -> ExitCode {
+/// if !check_foo() {
+/// return ExitCode::from(42);
+/// }
+///
+/// ExitCode::SUCCESS
+/// }
+/// ```
#[derive(Clone, Copy, Debug)]
-#[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
+#[stable(feature = "process_exitcode", since = "1.60.0")]
pub struct ExitCode(imp::ExitCode);
-#[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
+#[stable(feature = "process_exitcode", since = "1.60.0")]
impl ExitCode {
- /// The canonical ExitCode for successful termination on this platform.
+ /// The canonical `ExitCode` for successful termination on this platform.
///
/// Note that a `()`-returning `main` implicitly results in a successful
/// termination, so there's no need to return this from `main` unless
/// you're also returning other possible codes.
- #[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
+ #[stable(feature = "process_exitcode", since = "1.60.0")]
pub const SUCCESS: ExitCode = ExitCode(imp::ExitCode::SUCCESS);
- /// The canonical ExitCode for unsuccessful termination on this platform.
+ /// The canonical `ExitCode` for unsuccessful termination on this platform.
///
/// If you're only returning this and `SUCCESS` from `main`, consider
/// instead returning `Err(_)` and `Ok(())` respectively, which will
/// return the same codes (but will also `eprintln!` the error).
- #[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
+ #[stable(feature = "process_exitcode", since = "1.60.0")]
pub const FAILURE: ExitCode = ExitCode(imp::ExitCode::FAILURE);
}
impl ExitCode {
- // This should not be stabilized when stabilizing ExitCode, we don't know that i32 will serve
+ // This is private/perma-unstable because ExitCode is opaque; we don't know that i32 will serve
// all usecases, for example windows seems to use u32, unix uses the 8-15th bits of an i32, we
// likely want to isolate users anything that could restrict the platform specific
// representation of an ExitCode
//
// More info: https://internals.rust-lang.org/t/mini-pre-rfc-redesigning-process-exitstatus/5426
- /// Convert an ExitCode into an i32
- #[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
+ /// Convert an `ExitCode` into an i32
+ #[unstable(
+ feature = "process_exitcode_internals",
+ reason = "exposed only for libstd",
+ issue = "none"
+ )]
#[inline]
+ #[doc(hidden)]
pub fn to_i32(self) -> i32 {
self.0.as_i32()
}
}
-#[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
+#[stable(feature = "process_exitcode", since = "1.60.0")]
impl From<u8> for ExitCode {
- /// Construct an exit code from an arbitrary u8 value.
+ /// Construct an `ExitCode` from an arbitrary u8 value.
fn from(code: u8) -> Self {
ExitCode(imp::ExitCode::from(code))
}
@@ -2049,7 +2092,7 @@ pub fn id() -> u32 {
/// standard library's runtime for convenience. Other runtimes are not required
/// to provide similar functionality.
#[cfg_attr(not(test), lang = "termination")]
-#[unstable(feature = "termination_trait_lib", issue = "43301")]
+#[stable(feature = "termination_trait_lib", since = "1.60.0")]
#[rustc_on_unimplemented(
message = "`main` has invalid return type `{Self}`",
label = "`main` can only return types that implement `{Termination}`"
@@ -2057,10 +2100,11 @@ pub fn id() -> u32 {
pub trait Termination {
/// Is called to get the representation of the value as status code.
/// This status code is returned to the operating system.
+ #[stable(feature = "termination_trait_lib", since = "1.60.0")]
fn report(self) -> ExitCode;
}
-#[unstable(feature = "termination_trait_lib", issue = "43301")]
+#[stable(feature = "termination_trait_lib", since = "1.60.0")]
impl Termination for () {
#[inline]
fn report(self) -> ExitCode {
@@ -2068,7 +2112,7 @@ fn report(self) -> ExitCode {
}
}
-#[unstable(feature = "termination_trait_lib", issue = "43301")]
+#[stable(feature = "termination_trait_lib", since = "1.60.0")]
impl<E: fmt::Debug> Termination for Result<(), E> {
fn report(self) -> ExitCode {
match self {
@@ -2078,14 +2122,14 @@ fn report(self) -> ExitCode {
}
}
-#[unstable(feature = "termination_trait_lib", issue = "43301")]
+#[stable(feature = "termination_trait_lib", since = "1.60.0")]
impl Termination for ! {
fn report(self) -> ExitCode {
self
}
}
-#[unstable(feature = "termination_trait_lib", issue = "43301")]
+#[stable(feature = "termination_trait_lib", since = "1.60.0")]
impl<E: fmt::Debug> Termination for Result<!, E> {
fn report(self) -> ExitCode {
let Err(err) = self;
@@ -2094,7 +2138,7 @@ fn report(self) -> ExitCode {
}
}
-#[unstable(feature = "termination_trait_lib", issue = "43301")]
+#[stable(feature = "termination_trait_lib", since = "1.60.0")]
impl<E: fmt::Debug> Termination for Result<Infallible, E> {
fn report(self) -> ExitCode {
let Err(err) = self;
@@ -2102,7 +2146,7 @@ fn report(self) -> ExitCode {
}
}
-#[unstable(feature = "termination_trait_lib", issue = "43301")]
+#[stable(feature = "termination_trait_lib", since = "1.60.0")]
impl Termination for ExitCode {
#[inline]
fn report(self) -> ExitCode {
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index b93a3d6..7181451 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -1535,12 +1535,12 @@ mod remove_dir_impl {
use crate::sync::Arc;
use crate::sys::{cvt, cvt_r};
- #[cfg(not(all(target_os = "macos", target_arch = "x86_64"),))]
+ #[cfg(not(all(target_os = "macos", not(target_arch = "aarch64")),))]
use libc::{fdopendir, openat, unlinkat};
- #[cfg(all(target_os = "macos", target_arch = "x86_64"))]
+ #[cfg(all(target_os = "macos", not(target_arch = "aarch64")))]
use macos_weak::{fdopendir, openat, unlinkat};
- #[cfg(all(target_os = "macos", target_arch = "x86_64"))]
+ #[cfg(all(target_os = "macos", not(target_arch = "aarch64")))]
mod macos_weak {
use crate::sys::weak::weak;
use libc::{c_char, c_int, DIR};
@@ -1562,6 +1562,9 @@ pub unsafe fn openat(dirfd: c_int, pathname: *const c_char, flags: c_int) -> c_i
}
pub unsafe fn fdopendir(fd: c_int) -> *mut DIR {
+ #[cfg(all(target_os = "macos", target_arch = "x86"))]
+ weak!(fn fdopendir(c_int) -> *mut DIR, "fdopendir$INODE64$UNIX2003");
+ #[cfg(all(target_os = "macos", target_arch = "x86_64"))]
weak!(fn fdopendir(c_int) -> *mut DIR, "fdopendir$INODE64");
fdopendir.get().map(|fdopendir| fdopendir(fd)).unwrap_or_else(|| {
crate::sys::unix::os::set_errno(libc::ENOSYS);
@@ -1699,12 +1702,12 @@ fn remove_dir_all_modern(p: &Path) -> io::Result<()> {
}
}
- #[cfg(not(all(target_os = "macos", target_arch = "x86_64")))]
+ #[cfg(not(all(target_os = "macos", not(target_arch = "aarch64"))))]
pub fn remove_dir_all(p: &Path) -> io::Result<()> {
remove_dir_all_modern(p)
}
- #[cfg(all(target_os = "macos", target_arch = "x86_64"))]
+ #[cfg(all(target_os = "macos", not(target_arch = "aarch64")))]
pub fn remove_dir_all(p: &Path) -> io::Result<()> {
if macos_weak::has_openat() {
// openat() is available with macOS 10.10+, just like unlinkat() and fdopendir()
diff --git a/library/std/src/time.rs b/library/std/src/time.rs
index 2f8eb55..708e406 100644
--- a/library/std/src/time.rs
+++ b/library/std/src/time.rs
@@ -101,7 +101,9 @@
/// ```
///
/// # Underlying System calls
-/// Currently, the following system calls are being used to get the current time using `now()`:
+///
+/// The following system calls are [currently] being used by `now()` to find out
+/// the current time:
///
/// | Platform | System call |
/// |-----------|----------------------------------------------------------------------|
@@ -113,6 +115,7 @@
/// | WASI | [__wasi_clock_time_get (Monotonic Clock)] |
/// | Windows | [QueryPerformanceCounter] |
///
+/// [currently]: crate::io#platform-specific-behavior
/// [QueryPerformanceCounter]: https://docs.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancecounter
/// [`insecure_time` usercall]: https://edp.fortanix.com/docs/api/fortanix_sgx_abi/struct.Usercalls.html#method.insecure_time
/// [timekeeping in SGX]: https://edp.fortanix.com/docs/concepts/rust-std/#codestdtimecode
@@ -203,7 +206,8 @@
/// For example, on Windows the time is represented in 100 nanosecond intervals whereas Linux
/// can represent nanosecond intervals.
///
-/// Currently, the following system calls are being used to get the current time using `now()`:
+/// The following system calls are [currently] being used by `now()` to find out
+/// the current time:
///
/// | Platform | System call |
/// |-----------|----------------------------------------------------------------------|
@@ -215,6 +219,7 @@
/// | WASI | [__wasi_clock_time_get (Realtime Clock)] |
/// | Windows | [GetSystemTimePreciseAsFileTime] / [GetSystemTimeAsFileTime] |
///
+/// [currently]: crate::io#platform-specific-behavior
/// [`insecure_time` usercall]: https://edp.fortanix.com/docs/api/fortanix_sgx_abi/struct.Usercalls.html#method.insecure_time
/// [timekeeping in SGX]: https://edp.fortanix.com/docs/concepts/rust-std/#codestdtimecode
/// [gettimeofday]: https://man7.org/linux/man-pages/man2/gettimeofday.2.html
diff --git a/library/test/src/console.rs b/library/test/src/console.rs
index c7e8507..56eef83 100644
--- a/library/test/src/console.rs
+++ b/library/test/src/console.rs
@@ -118,7 +118,7 @@ pub fn write_log_result(
TestResult::TrIgnored => {
#[cfg(not(bootstrap))]
if let Some(msg) = ignore_message {
- format!("ignored, {msg}")
+ format!("ignored: {msg}")
} else {
"ignored".to_owned()
}
diff --git a/library/test/src/formatters/json.rs b/library/test/src/formatters/json.rs
index c089bfc..737921c 100644
--- a/library/test/src/formatters/json.rs
+++ b/library/test/src/formatters/json.rs
@@ -121,6 +121,19 @@ fn write_result(
),
TestResult::TrIgnored => {
+ #[cfg(not(bootstrap))]
+ return self.write_event(
+ "test",
+ desc.name.as_slice(),
+ "ignored",
+ exec_time,
+ stdout,
+ desc.ignore_message
+ .map(|msg| format!(r#""message": "{}""#, EscapedString(msg)))
+ .as_deref(),
+ );
+
+ #[cfg(bootstrap)]
self.write_event("test", desc.name.as_slice(), "ignored", exec_time, stdout, None)
}
diff --git a/library/test/src/formatters/pretty.rs b/library/test/src/formatters/pretty.rs
index f55d390..9b407df 100644
--- a/library/test/src/formatters/pretty.rs
+++ b/library/test/src/formatters/pretty.rs
@@ -45,8 +45,12 @@ pub fn write_failed(&mut self) -> io::Result<()> {
self.write_short_result("FAILED", term::color::RED)
}
- pub fn write_ignored(&mut self) -> io::Result<()> {
- self.write_short_result("ignored", term::color::YELLOW)
+ pub fn write_ignored(&mut self, message: Option<&'static str>) -> io::Result<()> {
+ if let Some(message) = message {
+ self.write_short_result(&format!("ignored, {}", message), term::color::YELLOW)
+ } else {
+ self.write_short_result("ignored", term::color::YELLOW)
+ }
}
pub fn write_time_failed(&mut self) -> io::Result<()> {
@@ -214,7 +218,12 @@ fn write_result(
match *result {
TestResult::TrOk => self.write_ok()?,
TestResult::TrFailed | TestResult::TrFailedMsg(_) => self.write_failed()?,
- TestResult::TrIgnored => self.write_ignored()?,
+ TestResult::TrIgnored => {
+ #[cfg(not(bootstrap))]
+ self.write_ignored(desc.ignore_message)?;
+ #[cfg(bootstrap)]
+ self.write_ignored(None)?;
+ }
TestResult::TrBench(ref bs) => {
self.write_bench()?;
self.write_plain(&format!(": {}", fmt_bench_samples(bs)))?;
diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs
index 088e3a2..889f7cb 100644
--- a/library/test/src/lib.rs
+++ b/library/test/src/lib.rs
@@ -19,8 +19,7 @@
#![feature(bench_black_box)]
#![feature(internal_output_capture)]
#![feature(staged_api)]
-#![feature(termination_trait_lib)]
-#![feature(process_exitcode_placeholder)]
+#![feature(process_exitcode_internals)]
#![feature(test)]
#![feature(total_cmp)]
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 32ccca8..e751188 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -231,10 +231,10 @@ fn is_excluded(&self, builder: &Builder<'_>, pathset: &PathSet) -> bool {
}
if !builder.config.exclude.is_empty() {
- eprintln!(
+ builder.verbose(&format!(
"{:?} not skipped for {:?} -- not in {:?}",
pathset, self.name, builder.config.exclude
- );
+ ));
}
false
}
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index e030e0b..00fc1f0 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -689,6 +689,8 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS
}
if builder.config.rustc_parallel {
+ // keep in sync with `bootstrap/lib.rs:Build::rustc_features`
+ // `cfg` option for rustc, `features` option for cargo, for conditional compilation
cargo.rustflag("--cfg=parallel_compiler");
cargo.rustdocflag("--cfg=parallel_compiler");
}
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index be55871..5f16716 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -432,6 +432,12 @@ fn run(self, builder: &Builder<'_>) {
let stage = self.stage;
let target = self.target;
builder.info(&format!("Documenting stage{} std ({})", stage, target));
+ if builder.no_std(target) == Some(true) {
+ panic!(
+ "building std documentation for no_std target {target} is not supported\n\
+ Set `docs = false` in the config to disable documentation."
+ );
+ }
let out = builder.doc_out(target);
t!(fs::create_dir_all(&out));
let compiler = builder.compiler(stage, builder.config.build);
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 41e2e97..8f076ad 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -729,12 +729,16 @@ fn std_features(&self, target: TargetSelection) -> String {
/// Gets the space-separated set of activated features for the compiler.
fn rustc_features(&self, kind: Kind) -> String {
- let mut features = String::new();
+ let mut features = vec![];
if self.config.jemalloc {
- features.push_str("jemalloc");
+ features.push("jemalloc");
}
if self.config.llvm_enabled() || kind == Kind::Check {
- features.push_str(" llvm");
+ features.push("llvm");
+ }
+ // keep in sync with `bootstrap/compile.rs:rustc_cargo_env`
+ if self.config.rustc_parallel {
+ features.push("rustc_use_parallel_compiler");
}
// If debug logging is on, then we want the default for tracing:
@@ -743,10 +747,10 @@ fn rustc_features(&self, kind: Kind) -> String {
// if its unset, if debug_assertions is on, then debug_logging will also be on
// as well as tracing *ignoring* this feature when debug_assertions is on
if !self.config.rust_debug_logging {
- features.push_str(" max_level_info");
+ features.push("max_level_info");
}
- features
+ features.join(" ")
}
/// Component directory that Cargo will produce output into (e.g.
diff --git a/src/doc/book b/src/doc/book
index 036e88a..ea90bba 160000
--- a/src/doc/book
+++ b/src/doc/book
@@ -1 +1 @@
-Subproject commit 036e88a4f135365de85358febe5324976a56030a
+Subproject commit ea90bbaf53ba64ef4e2da9ac2352b298aec6bec8
diff --git a/src/doc/embedded-book b/src/doc/embedded-book
index d5fc1bc..a6de8b6 160000
--- a/src/doc/embedded-book
+++ b/src/doc/embedded-book
@@ -1 +1 @@
-Subproject commit d5fc1bce3f8eb398f9c25f1b15e0257d7537cd41
+Subproject commit a6de8b6e3ea5d4f0de8b7b9a7e5c1405dc2c2ddb
diff --git a/src/doc/nomicon b/src/doc/nomicon
index f6d6126..11f1165 160000
--- a/src/doc/nomicon
+++ b/src/doc/nomicon
@@ -1 +1 @@
-Subproject commit f6d6126fc96ecf4a7f7d22da330df9506293b0d0
+Subproject commit 11f1165e8a2f5840467e748c8108dc53c948ee9a
diff --git a/src/doc/reference b/src/doc/reference
index 0a2fe66..c97d14f 160000
--- a/src/doc/reference
+++ b/src/doc/reference
@@ -1 +1 @@
-Subproject commit 0a2fe6651fbccc6416c5110fdf5b93fb3cb29247
+Subproject commit c97d14fa6fed0baa9255432b8a93cb70614f80e3
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
index d504324..ec954f3 160000
--- a/src/doc/rust-by-example
+++ b/src/doc/rust-by-example
@@ -1 +1 @@
-Subproject commit d504324f1e7dc7edb918ac39baae69f1f1513b8e
+Subproject commit ec954f35eedf592cd173b21c05a7f80a65b61d8a
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
index 0e4b961..155126b 160000
--- a/src/doc/rustc-dev-guide
+++ b/src/doc/rustc-dev-guide
@@ -1 +1 @@
-Subproject commit 0e4b961a9c708647bca231430ce1b199993e0196
+Subproject commit 155126b1d2e2cb01ddb1d7ba9489b90d7cd173ad
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index ec538f1..b681df3 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -221,9 +221,6 @@
fn build_external_function(cx: &mut DocContext<'_>, did: DefId) -> clean::Function {
let sig = cx.tcx.fn_sig(did);
- let constness =
- if cx.tcx.is_const_fn_raw(did) { hir::Constness::Const } else { hir::Constness::NotConst };
- let asyncness = cx.tcx.asyncness(did);
let predicates = cx.tcx.predicates_of(did);
let (generics, decl) = clean::enter_impl_trait(cx, |cx| {
// NOTE: generics need to be cleaned before the decl!
@@ -231,11 +228,7 @@ fn build_external_function(cx: &mut DocContext<'_>, did: DefId) -> clean::Functi
let decl = clean_fn_decl_from_did_and_sig(cx, Some(did), sig);
(generics, decl)
});
- clean::Function {
- decl,
- generics,
- header: hir::FnHeader { unsafety: sig.unsafety(), abi: sig.abi(), constness, asyncness },
- }
+ clean::Function { decl, generics }
}
fn build_enum(cx: &mut DocContext<'_>, did: DefId) -> clean::Enum {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 1e3260c..37c2473 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -12,7 +12,6 @@
use rustc_ast as ast;
use rustc_attr as attr;
-use rustc_const_eval::const_eval::is_unstable_const_fn;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
@@ -26,8 +25,6 @@
use rustc_span::hygiene::{AstPass, MacroKind};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{self, ExpnKind};
-use rustc_target::spec::abi::Abi;
-use rustc_typeck::check::intrinsic::intrinsic_operation_unsafety;
use rustc_typeck::hir_ty_to_ty;
use std::assert_matches::assert_matches;
@@ -813,13 +810,6 @@ fn clean_fn_or_proc_macro(
}
None => {
let mut func = clean_function(cx, sig, generics, body_id);
- let def_id = item.def_id.to_def_id();
- func.header.constness =
- if cx.tcx.is_const_fn(def_id) && is_unstable_const_fn(cx.tcx, def_id).is_none() {
- hir::Constness::Const
- } else {
- hir::Constness::NotConst
- };
clean_fn_decl_legacy_const_generics(&mut func, attrs);
FunctionItem(func)
}
@@ -869,7 +859,7 @@ fn clean_function(
let decl = clean_fn_decl_with_args(cx, sig.decl, args);
(generics, decl)
});
- Function { decl, generics, header: sig.header }
+ Function { decl, generics }
}
fn clean_args_from_types_and_names(
@@ -998,12 +988,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
AssocConstItem(ty.clean(cx), default)
}
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
- let mut m = clean_function(cx, sig, &self.generics, body);
- if m.header.constness == hir::Constness::Const
- && is_unstable_const_fn(cx.tcx, local_did).is_some()
- {
- m.header.constness = hir::Constness::NotConst;
- }
+ let m = clean_function(cx, sig, &self.generics, body);
MethodItem(m, None)
}
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(names)) => {
@@ -1014,13 +999,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
let decl = clean_fn_decl_with_args(cx, sig.decl, args);
(generics, decl)
});
- let mut t = Function { header: sig.header, decl, generics };
- if t.header.constness == hir::Constness::Const
- && is_unstable_const_fn(cx.tcx, local_did).is_some()
- {
- t.header.constness = hir::Constness::NotConst;
- }
- TyMethodItem(t)
+ TyMethodItem(Function { decl, generics })
}
hir::TraitItemKind::Type(bounds, ref default) => {
let generics = enter_impl_trait(cx, |cx| self.generics.clean(cx));
@@ -1047,12 +1026,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
AssocConstItem(ty.clean(cx), default)
}
hir::ImplItemKind::Fn(ref sig, body) => {
- let mut m = clean_function(cx, sig, &self.generics, body);
- if m.header.constness == hir::Constness::Const
- && is_unstable_const_fn(cx.tcx, local_did).is_some()
- {
- m.header.constness = hir::Constness::NotConst;
- }
+ let m = clean_function(cx, sig, &self.generics, body);
let defaultness = cx.tcx.associated_item(self.def_id).defaultness;
MethodItem(m, Some(defaultness))
}
@@ -1127,40 +1101,13 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
ty::TraitContainer(_) => self.defaultness.has_value(),
};
if provided {
- let constness = if tcx.is_const_fn_raw(self.def_id) {
- hir::Constness::Const
- } else {
- hir::Constness::NotConst
- };
- let asyncness = tcx.asyncness(self.def_id);
let defaultness = match self.container {
ty::ImplContainer(_) => Some(self.defaultness),
ty::TraitContainer(_) => None,
};
- MethodItem(
- Function {
- generics,
- decl,
- header: hir::FnHeader {
- unsafety: sig.unsafety(),
- abi: sig.abi(),
- constness,
- asyncness,
- },
- },
- defaultness,
- )
+ MethodItem(Function { generics, decl }, defaultness)
} else {
- TyMethodItem(Function {
- generics,
- decl,
- header: hir::FnHeader {
- unsafety: sig.unsafety(),
- abi: sig.abi(),
- constness: hir::Constness::NotConst,
- asyncness: hir::IsAsync::NotAsync,
- },
- })
+ TyMethodItem(Function { generics, decl })
}
}
ty::AssocKind::Type => {
@@ -2192,7 +2139,6 @@ fn clean_maybe_renamed_foreign_item(
cx.with_param_env(def_id, |cx| {
let kind = match item.kind {
hir::ForeignItemKind::Fn(decl, names, ref generics) => {
- let abi = cx.tcx.hir().get_foreign_abi(item.hir_id());
let (generics, decl) = enter_impl_trait(cx, |cx| {
// NOTE: generics must be cleaned before args
let generics = generics.clean(cx);
@@ -2200,20 +2146,7 @@ fn clean_maybe_renamed_foreign_item(
let decl = clean_fn_decl_with_args(cx, decl, args);
(generics, decl)
});
- ForeignFunctionItem(Function {
- decl,
- generics,
- header: hir::FnHeader {
- unsafety: if abi == Abi::RustIntrinsic {
- intrinsic_operation_unsafety(item.ident.name)
- } else {
- hir::Unsafety::Unsafe
- },
- abi,
- constness: hir::Constness::NotConst,
- asyncness: hir::IsAsync::NotAsync,
- },
- })
+ ForeignFunctionItem(Function { decl, generics })
}
hir::ForeignItemKind::Static(ref ty, mutability) => {
ForeignStaticItem(Static { type_: ty.clean(cx), mutability, expr: None })
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 47289eb..957faec 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -13,6 +13,7 @@
use rustc_ast::util::comments::beautify_doc_string;
use rustc_ast::{self as ast, AttrStyle};
use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel};
+use rustc_const_eval::const_eval::is_unstable_const_fn;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::thin_vec::ThinVec;
use rustc_hir as hir;
@@ -29,6 +30,7 @@
use rustc_span::{self, FileName, Loc};
use rustc_target::abi::VariantIdx;
use rustc_target::spec::abi::Abi;
+use rustc_typeck::check::intrinsic::intrinsic_operation_unsafety;
use crate::clean::cfg::Cfg;
use crate::clean::external_path;
@@ -641,6 +643,48 @@ impl Item {
_ => false,
}
}
+
+ /// Returns a `FnHeader` if `self` is a function item, otherwise returns `None`.
+ crate fn fn_header(&self, tcx: TyCtxt<'_>) -> Option<hir::FnHeader> {
+ fn build_fn_header(
+ def_id: DefId,
+ tcx: TyCtxt<'_>,
+ asyncness: hir::IsAsync,
+ ) -> hir::FnHeader {
+ let sig = tcx.fn_sig(def_id);
+ let constness =
+ if tcx.is_const_fn(def_id) && is_unstable_const_fn(tcx, def_id).is_none() {
+ hir::Constness::Const
+ } else {
+ hir::Constness::NotConst
+ };
+ hir::FnHeader { unsafety: sig.unsafety(), abi: sig.abi(), constness, asyncness }
+ }
+ let header = match *self.kind {
+ ItemKind::ForeignFunctionItem(_) => {
+ let abi = tcx.fn_sig(self.def_id.as_def_id().unwrap()).abi();
+ hir::FnHeader {
+ unsafety: if abi == Abi::RustIntrinsic {
+ intrinsic_operation_unsafety(self.name.unwrap())
+ } else {
+ hir::Unsafety::Unsafe
+ },
+ abi,
+ constness: hir::Constness::NotConst,
+ asyncness: hir::IsAsync::NotAsync,
+ }
+ }
+ ItemKind::FunctionItem(_) | ItemKind::MethodItem(_, _) => {
+ let def_id = self.def_id.as_def_id().unwrap();
+ build_fn_header(def_id, tcx, tcx.asyncness(def_id))
+ }
+ ItemKind::TyMethodItem(_) => {
+ build_fn_header(self.def_id.as_def_id().unwrap(), tcx, hir::IsAsync::NotAsync)
+ }
+ _ => return None,
+ };
+ Some(header)
+ }
}
#[derive(Clone, Debug)]
@@ -1253,7 +1297,6 @@ impl GenericParamDef {
crate struct Function {
crate decl: FnDecl,
crate generics: Generics,
- crate header: hir::FnHeader,
}
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 3666767..93b33b0 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -48,7 +48,6 @@
use rustc_ast_pretty::pprust;
use rustc_attr::{ConstStability, Deprecation, StabilityLevel};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_hir as hir;
use rustc_hir::def::CtorKind;
use rustc_hir::def_id::DefId;
use rustc_hir::Mutability;
@@ -806,7 +805,6 @@ fn assoc_type(
fn assoc_method(
w: &mut Buffer,
meth: &clean::Item,
- header: hir::FnHeader,
g: &clean::Generics,
d: &clean::FnDecl,
link: AssocItemLink<'_>,
@@ -814,6 +812,7 @@ fn assoc_method(
cx: &Context<'_>,
render_mode: RenderMode,
) {
+ let header = meth.fn_header(cx.tcx()).expect("Trying to get header from a non-function item");
let name = meth.name.as_ref().unwrap();
let href = match link {
AssocItemLink::Anchor(Some(ref id)) => Some(format!("#{}", id)),
@@ -972,10 +971,10 @@ fn render_assoc_item(
match *item.kind {
clean::StrippedItem(..) => {}
clean::TyMethodItem(ref m) => {
- assoc_method(w, item, m.header, &m.generics, &m.decl, link, parent, cx, render_mode)
+ assoc_method(w, item, &m.generics, &m.decl, link, parent, cx, render_mode)
}
clean::MethodItem(ref m, _) => {
- assoc_method(w, item, m.header, &m.generics, &m.decl, link, parent, cx, render_mode)
+ assoc_method(w, item, &m.generics, &m.decl, link, parent, cx, render_mode)
}
clean::AssocConstItem(ref ty, _) => {
assoc_const(w, item, ty, link, if parent == ItemType::Trait { " " } else { "" }, cx)
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index e6c7745..6c9a5a9 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -365,8 +365,9 @@ fn cmp(
}
let unsafety_flag = match *myitem.kind {
- clean::FunctionItem(ref func) | clean::ForeignFunctionItem(ref func)
- if func.header.unsafety == hir::Unsafety::Unsafe =>
+ clean::FunctionItem(_) | clean::ForeignFunctionItem(_)
+ if myitem.fn_header(cx.tcx()).unwrap().unsafety
+ == hir::Unsafety::Unsafe =>
{
"<a title=\"unsafe function\" href=\"#\"><sup>âš </sup></a>"
}
@@ -376,17 +377,26 @@ fn cmp(
let stab = myitem.stability_class(cx.tcx());
let add = if stab.is_some() { " " } else { "" };
+ let visibility_emoji = match myitem.visibility {
+ clean::Visibility::Restricted(_) => {
+ "<span title=\"Restricted Visibility\"> 🔒</span> "
+ }
+ _ => "",
+ };
+
let doc_value = myitem.doc_value().unwrap_or_default();
w.write_str(ITEM_TABLE_ROW_OPEN);
write!(
w,
"<div class=\"item-left {stab}{add}module-item\">\
- <a class=\"{class}\" href=\"{href}\" title=\"{title}\">{name}</a>\
- {unsafety_flag}\
- {stab_tags}\
+ <a class=\"{class}\" href=\"{href}\" title=\"{title}\">{name}</a>\
+ {visibility_emoji}\
+ {unsafety_flag}\
+ {stab_tags}\
</div>\
<div class=\"item-right docblock-short\">{docs}</div>",
name = myitem.name.unwrap(),
+ visibility_emoji = visibility_emoji,
stab_tags = extra_info_tags(myitem, item, cx.tcx()),
docs = MarkdownSummaryLine(&doc_value, &myitem.links(cx)).into_string(),
class = myitem.type_(),
@@ -453,16 +463,17 @@ fn tag_html(class: &str, title: &str, contents: &str) -> String {
}
fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::Function) {
- let vis = it.visibility.print_with_space(it.def_id, cx).to_string();
- let constness = print_constness_with_space(&f.header.constness, it.const_stability(cx.tcx()));
- let asyncness = f.header.asyncness.print_with_space();
- let unsafety = f.header.unsafety.print_with_space();
- let abi = print_abi_with_space(f.header.abi).to_string();
+ let header = it.fn_header(cx.tcx()).expect("printing a function which isn't a function");
+ let constness = print_constness_with_space(&header.constness, it.const_stability(cx.tcx()));
+ let unsafety = header.unsafety.print_with_space().to_string();
+ let abi = print_abi_with_space(header.abi).to_string();
+ let asyncness = header.asyncness.print_with_space();
+ let visibility = it.visibility.print_with_space(it.def_id, cx).to_string();
let name = it.name.unwrap();
let generics_len = format!("{:#}", f.generics.print(cx)).len();
let header_len = "fn ".len()
- + vis.len()
+ + visibility.len()
+ constness.len()
+ asyncness.len()
+ unsafety.len()
@@ -478,7 +489,7 @@ fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::
w,
"{vis}{constness}{asyncness}{unsafety}{abi}fn \
{name}{generics}{decl}{notable_traits}{where_clause}",
- vis = vis,
+ vis = visibility,
constness = constness,
asyncness = asyncness,
unsafety = unsafety,
@@ -486,7 +497,7 @@ fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::
name = name,
generics = f.generics.print(cx),
where_clause = print_where_clause(&f.generics, cx, 0, true),
- decl = f.decl.full_print(header_len, 0, f.header.asyncness, cx),
+ decl = f.decl.full_print(header_len, 0, header.asyncness, cx),
notable_traits = notable_traits_decl(&f.decl, cx),
);
});
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index 7cf5d02..bc63820 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -199,6 +199,8 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
use clean::ItemKind::*;
let name = item.name;
let is_crate = item.is_crate();
+ let header = item.fn_header(tcx);
+
match *item.kind {
ModuleItem(m) => ItemEnum::Module(Module { is_crate, items: ids(m.items) }),
ImportItem(i) => ItemEnum::Import(i.into_tcx(tcx)),
@@ -207,12 +209,12 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
StructFieldItem(f) => ItemEnum::StructField(f.into_tcx(tcx)),
EnumItem(e) => ItemEnum::Enum(e.into_tcx(tcx)),
VariantItem(v) => ItemEnum::Variant(v.into_tcx(tcx)),
- FunctionItem(f) => ItemEnum::Function(f.into_tcx(tcx)),
- ForeignFunctionItem(f) => ItemEnum::Function(f.into_tcx(tcx)),
+ FunctionItem(f) => ItemEnum::Function(from_function(f, header.unwrap(), tcx)),
+ ForeignFunctionItem(f) => ItemEnum::Function(from_function(f, header.unwrap(), tcx)),
TraitItem(t) => ItemEnum::Trait(t.into_tcx(tcx)),
TraitAliasItem(t) => ItemEnum::TraitAlias(t.into_tcx(tcx)),
- MethodItem(m, _) => ItemEnum::Method(from_function_method(m, true, tcx)),
- TyMethodItem(m) => ItemEnum::Method(from_function_method(m, false, tcx)),
+ MethodItem(m, _) => ItemEnum::Method(from_function_method(m, true, header.unwrap(), tcx)),
+ TyMethodItem(m) => ItemEnum::Method(from_function_method(m, false, header.unwrap(), tcx)),
ImplItem(i) => ItemEnum::Impl(i.into_tcx(tcx)),
StaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)),
ForeignStaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)),
@@ -300,17 +302,6 @@ fn convert_abi(a: RustcAbi) -> Abi {
}
}
-impl FromWithTcx<clean::Function> for Function {
- fn from_tcx(function: clean::Function, tcx: TyCtxt<'_>) -> Self {
- let clean::Function { decl, generics, header } = function;
- Function {
- decl: decl.into_tcx(tcx),
- generics: generics.into_tcx(tcx),
- header: from_fn_header(&header),
- }
- }
-}
-
impl FromWithTcx<clean::Generics> for Generics {
fn from_tcx(generics: clean::Generics, tcx: TyCtxt<'_>) -> Self {
Generics {
@@ -555,12 +546,26 @@ fn from_tcx(impl_: clean::Impl, tcx: TyCtxt<'_>) -> Self {
}
}
+crate fn from_function(
+ function: clean::Function,
+ header: rustc_hir::FnHeader,
+ tcx: TyCtxt<'_>,
+) -> Function {
+ let clean::Function { decl, generics } = function;
+ Function {
+ decl: decl.into_tcx(tcx),
+ generics: generics.into_tcx(tcx),
+ header: from_fn_header(&header),
+ }
+}
+
crate fn from_function_method(
function: clean::Function,
has_body: bool,
+ header: rustc_hir::FnHeader,
tcx: TyCtxt<'_>,
) -> Method {
- let clean::Function { header, decl, generics } = function;
+ let clean::Function { decl, generics } = function;
Method {
decl: decl.into_tcx(tcx),
generics: generics.into_tcx(tcx),
diff --git a/src/test/run-make-fulldeps/libtest-json/Makefile b/src/test/run-make-fulldeps/libtest-json/Makefile
index f61a1aa..67b5fc2 100644
--- a/src/test/run-make-fulldeps/libtest-json/Makefile
+++ b/src/test/run-make-fulldeps/libtest-json/Makefile
@@ -5,7 +5,7 @@
OUTPUT_FILE_DEFAULT := $(TMPDIR)/libtest-json-output-default.json
OUTPUT_FILE_STDOUT_SUCCESS := $(TMPDIR)/libtest-json-output-stdout-success.json
-all:
+all: f.rs validate_json.py output-default.json output-stdout-success.json
$(RUSTC) --test f.rs
RUST_BACKTRACE=0 $(call RUN,f) -Z unstable-options --test-threads=1 --format=json > $(OUTPUT_FILE_DEFAULT) || true
RUST_BACKTRACE=0 $(call RUN,f) -Z unstable-options --test-threads=1 --format=json --show-output > $(OUTPUT_FILE_STDOUT_SUCCESS) || true
diff --git a/src/test/run-make-fulldeps/libtest-json/f.rs b/src/test/run-make-fulldeps/libtest-json/f.rs
index 95ff36b..edfe250 100644
--- a/src/test/run-make-fulldeps/libtest-json/f.rs
+++ b/src/test/run-make-fulldeps/libtest-json/f.rs
@@ -16,7 +16,7 @@ fn c() {
}
#[test]
-#[ignore]
+#[ignore = "msg"]
fn d() {
assert!(false);
}
diff --git a/src/test/run-make-fulldeps/libtest-json/output-default.json b/src/test/run-make-fulldeps/libtest-json/output-default.json
index e2c778a..63342ab 100644
--- a/src/test/run-make-fulldeps/libtest-json/output-default.json
+++ b/src/test/run-make-fulldeps/libtest-json/output-default.json
@@ -6,5 +6,5 @@
{ "type": "test", "event": "started", "name": "c" }
{ "type": "test", "name": "c", "event": "ok" }
{ "type": "test", "event": "started", "name": "d" }
-{ "type": "test", "name": "d", "event": "ignored" }
+{ "type": "test", "name": "d", "event": "ignored", "message": "msg" }
{ "type": "suite", "event": "failed", "passed": 2, "failed": 1, "ignored": 1, "measured": 0, "filtered_out": 0, "exec_time": $TIME }
diff --git a/src/test/run-make-fulldeps/libtest-json/output-stdout-success.json b/src/test/run-make-fulldeps/libtest-json/output-stdout-success.json
index 68eb00c..8f19114 100644
--- a/src/test/run-make-fulldeps/libtest-json/output-stdout-success.json
+++ b/src/test/run-make-fulldeps/libtest-json/output-stdout-success.json
@@ -6,5 +6,5 @@
{ "type": "test", "event": "started", "name": "c" }
{ "type": "test", "name": "c", "event": "ok", "stdout": "thread 'main' panicked at 'assertion failed: false', f.rs:15:5\n" }
{ "type": "test", "event": "started", "name": "d" }
-{ "type": "test", "name": "d", "event": "ignored" }
+{ "type": "test", "name": "d", "event": "ignored", "message": "msg" }
{ "type": "suite", "event": "failed", "passed": 2, "failed": 1, "ignored": 1, "measured": 0, "filtered_out": 0, "exec_time": $TIME }
diff --git a/src/test/rustdoc/reexport-dep-foreign-fn.rs b/src/test/rustdoc/reexport-dep-foreign-fn.rs
new file mode 100644
index 0000000..6e1dc45
--- /dev/null
+++ b/src/test/rustdoc/reexport-dep-foreign-fn.rs
@@ -0,0 +1,12 @@
+// aux-build:all-item-types.rs
+
+// This test is to ensure there is no problem on handling foreign functions
+// coming from a dependency.
+
+#![crate_name = "foo"]
+
+extern crate all_item_types;
+
+// @has 'foo/fn.foo_ffn.html'
+// @has - '//*[@class="docblock item-decl"]//code' 'pub unsafe extern "C" fn foo_ffn()'
+pub use all_item_types::foo_ffn;
diff --git a/src/test/rustdoc/visibility.rs b/src/test/rustdoc/visibility.rs
index cd284da..c573e1b 100644
--- a/src/test/rustdoc/visibility.rs
+++ b/src/test/rustdoc/visibility.rs
@@ -4,42 +4,68 @@
#![crate_name = "foo"]
+// @!has 'foo/index.html' '//a[@href="struct.FooPublic.html"]/..' 'FooPublic 🔒'
// @has 'foo/struct.FooPublic.html' '//pre' 'pub struct FooPublic'
pub struct FooPublic;
+// @has 'foo/index.html' '//a[@href="struct.FooJustCrate.html"]/..' 'FooJustCrate 🔒'
// @has 'foo/struct.FooJustCrate.html' '//pre' 'pub(crate) struct FooJustCrate'
crate struct FooJustCrate;
+// @has 'foo/index.html' '//a[@href="struct.FooPubCrate.html"]/..' 'FooPubCrate 🔒'
// @has 'foo/struct.FooPubCrate.html' '//pre' 'pub(crate) struct FooPubCrate'
pub(crate) struct FooPubCrate;
+// @has 'foo/index.html' '//a[@href="struct.FooSelf.html"]/..' 'FooSelf 🔒'
// @has 'foo/struct.FooSelf.html' '//pre' 'pub(crate) struct FooSelf'
pub(self) struct FooSelf;
+// @has 'foo/index.html' '//a[@href="struct.FooInSelf.html"]/..' 'FooInSelf 🔒'
// @has 'foo/struct.FooInSelf.html' '//pre' 'pub(crate) struct FooInSelf'
pub(in self) struct FooInSelf;
+// @has 'foo/index.html' '//a[@href="struct.FooPriv.html"]/..' 'FooPriv 🔒'
// @has 'foo/struct.FooPriv.html' '//pre' 'pub(crate) struct FooPriv'
struct FooPriv;
+// @!has 'foo/index.html' '//a[@href="pub_mod/index.html"]/..' 'pub_mod 🔒'
+pub mod pub_mod {}
+
+// @has 'foo/index.html' '//a[@href="pub_crate_mod/index.html"]/..' 'pub_crate_mod 🔒'
+pub(crate) mod pub_crate_mod {}
+
+// @has 'foo/index.html' '//a[@href="a/index.html"]/..' 'a 🔒'
mod a {
+ // @has 'foo/a/index.html' '//a[@href="struct.FooASuper.html"]/..' 'FooASuper 🔒'
// @has 'foo/a/struct.FooASuper.html' '//pre' 'pub(crate) struct FooASuper'
pub(super) struct FooASuper;
+ // @has 'foo/a/index.html' '//a[@href="struct.FooAInSuper.html"]/..' 'FooAInSuper 🔒'
// @has 'foo/a/struct.FooAInSuper.html' '//pre' 'pub(crate) struct FooAInSuper'
pub(in super) struct FooAInSuper;
+ // @has 'foo/a/index.html' '//a[@href="struct.FooAInA.html"]/..' 'FooAInA 🔒'
// @has 'foo/a/struct.FooAInA.html' '//pre' 'struct FooAInA'
// @!has 'foo/a/struct.FooAInA.html' '//pre' 'pub'
pub(in a) struct FooAInA;
+ // @has 'foo/a/index.html' '//a[@href="struct.FooAPriv.html"]/..' 'FooAPriv 🔒'
// @has 'foo/a/struct.FooAPriv.html' '//pre' 'struct FooAPriv'
// @!has 'foo/a/struct.FooAPriv.html' '//pre' 'pub'
struct FooAPriv;
+ // @has 'foo/a/index.html' '//a[@href="b/index.html"]/..' 'b 🔒'
mod b {
+ // @has 'foo/a/b/index.html' '//a[@href="struct.FooBSuper.html"]/..' 'FooBSuper 🔒'
// @has 'foo/a/b/struct.FooBSuper.html' '//pre' 'pub(super) struct FooBSuper'
pub(super) struct FooBSuper;
+ // @has 'foo/a/b/index.html' '//a[@href="struct.FooBInSuperSuper.html"]/..' 'FooBInSuperSuper 🔒'
// @has 'foo/a/b/struct.FooBInSuperSuper.html' '//pre' 'pub(crate) struct FooBInSuperSuper'
pub(in super::super) struct FooBInSuperSuper;
+ // @has 'foo/a/b/index.html' '//a[@href="struct.FooBInAB.html"]/..' 'FooBInAB 🔒'
// @has 'foo/a/b/struct.FooBInAB.html' '//pre' 'struct FooBInAB'
// @!has 'foo/a/b/struct.FooBInAB.html' '//pre' 'pub'
pub(in a::b) struct FooBInAB;
+ // @has 'foo/a/b/index.html' '//a[@href="struct.FooBPriv.html"]/..' 'FooBPriv 🔒'
// @has 'foo/a/b/struct.FooBPriv.html' '//pre' 'struct FooBPriv'
// @!has 'foo/a/b/struct.FooBPriv.html' '//pre' 'pub'
struct FooBPriv;
+
+ // @!has 'foo/a/b/index.html' '//a[@href="struct.FooBPub.html"]/..' 'FooBPub 🔒'
+ // @has 'foo/a/b/struct.FooBPub.html' '//pre' 'pub struct FooBPub'
+ pub struct FooBPub;
}
}
@@ -53,6 +79,8 @@ mod b {
//
// @has 'foo/trait.PubTrait.html' '//pre' 'fn function();'
// @!has 'foo/trait.PubTrait.html' '//pre' 'pub fn function();'
+//
+// @!has 'foo/index.html' '//a[@href="trait.PubTrait.html"]/..' 'PubTrait 🔒'
pub trait PubTrait {
type Type;
@@ -60,6 +88,9 @@ pub trait PubTrait {
fn function();
}
+// @has 'foo/index.html' '//a[@href="trait.PrivTrait.html"]/..' 'PrivTrait 🔒'
+trait PrivTrait {}
+
// @has 'foo/struct.FooPublic.html' '//h4[@class="code-header"]' 'type Type'
// @!has 'foo/struct.FooPublic.html' '//h4[@class="code-header"]' 'pub type Type'
//
diff --git a/src/test/ui/auxiliary/empty-struct.rs b/src/test/ui/auxiliary/empty-struct.rs
deleted file mode 100644
index 3fb40f6..0000000
--- a/src/test/ui/auxiliary/empty-struct.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-pub struct XEmpty1 {}
-pub struct XEmpty2;
-pub struct XEmpty6();
-
-pub enum XE {
- XEmpty3 {},
- XEmpty4,
- XEmpty5(),
-}
diff --git a/src/test/ui/auxiliary/stability-cfg2.rs b/src/test/ui/auxiliary/stability-cfg2.rs
deleted file mode 100644
index c995038..0000000
--- a/src/test/ui/auxiliary/stability-cfg2.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-// compile-flags:--cfg foo
-
-#![cfg_attr(foo, unstable(feature = "unstable_test_feature", issue = "none"))]
-#![cfg_attr(not(foo), stable(feature = "test_feature", since = "1.0.0"))]
-#![feature(staged_api)]
diff --git a/src/test/ui/auxiliary/weak-lang-items.rs b/src/test/ui/auxiliary/weak-lang-items.rs
deleted file mode 100644
index 7a698cf..0000000
--- a/src/test/ui/auxiliary/weak-lang-items.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-// no-prefer-dynamic
-
-// This aux-file will require the eh_personality function to be codegen'd, but
-// it hasn't been defined just yet. Make sure we don't explode.
-
-#![no_std]
-#![crate_type = "rlib"]
-
-struct A;
-
-impl core::ops::Drop for A {
- fn drop(&mut self) {}
-}
-
-pub fn foo() {
- let _a = A;
- panic!("wut");
-}
-
-mod std {
- pub use core::{option, fmt};
-}
diff --git a/src/test/ui/box/issue-95036.rs b/src/test/ui/box/issue-95036.rs
new file mode 100644
index 0000000..c2d4275
--- /dev/null
+++ b/src/test/ui/box/issue-95036.rs
@@ -0,0 +1,22 @@
+// compile-flags: -O
+// build-pass
+
+#![feature(allocator_api, bench_black_box)]
+
+#[inline(never)]
+pub fn by_ref(node: &mut Box<[u8; 1], &std::alloc::Global>) {
+ node[0] = 9u8;
+}
+
+pub fn main() {
+ let mut node = Box::new_in([5u8], &std::alloc::Global);
+ node[0] = 7u8;
+
+ std::hint::black_box(node);
+
+ let mut node = Box::new_in([5u8], &std::alloc::Global);
+
+ by_ref(&mut node);
+
+ std::hint::black_box(node);
+}
diff --git a/src/test/ui/chalkify/closure.stderr b/src/test/ui/chalkify/closure.stderr
index d5a48a7..515e0cf 100644
--- a/src/test/ui/chalkify/closure.stderr
+++ b/src/test/ui/chalkify/closure.stderr
@@ -12,6 +12,10 @@
|
LL | a = 1;
| ^
+help: consider mutably borrowing `b`
+ |
+LL | let mut c = &mut b;
+ | ++++
error: aborting due to previous error
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr
index 066c000..83d282a 100644
--- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr
@@ -11,6 +11,10 @@
|
LL | if let MultiVariant::Point(ref mut x, _) = point {
| ^^^^^
+help: consider mutably borrowing `c`
+ |
+LL | let a = &mut c;
+ | ++++
error: aborting due to previous error
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr
index 2a6e008..46323b7 100644
--- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr
@@ -11,6 +11,10 @@
|
LL | let SingleVariant::Point(ref mut x, _) = point;
| ^^^^^
+help: consider mutably borrowing `c`
+ |
+LL | let b = &mut c;
+ | ++++
error: aborting due to previous error
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr
index d7fc51c..25029cc 100644
--- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr
@@ -11,6 +11,10 @@
|
LL | x.y.a += 1;
| ^^^^^
+help: consider mutably borrowing `hello`
+ |
+LL | let b = &mut hello;
+ | ++++
error: aborting due to previous error
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr
index 63e2d30..06ef7ba 100644
--- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr
@@ -11,6 +11,10 @@
|
LL | x.0 += 1;
| ^^^
+help: consider mutably borrowing `hello`
+ |
+LL | let b = &mut hello;
+ | ++++
error: aborting due to previous error
diff --git a/src/test/ui/cross-crate/auxiliary/anon_trait_static_method_lib.rs b/src/test/ui/cross-crate/auxiliary/anon_trait_static_method_lib.rs
deleted file mode 100644
index dceec7e..0000000
--- a/src/test/ui/cross-crate/auxiliary/anon_trait_static_method_lib.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-pub struct Foo {
- pub x: isize
-}
-
-impl Foo {
- pub fn new() -> Foo {
- Foo { x: 3 }
- }
-}
diff --git a/src/test/ui/cross-crate/auxiliary/newtype_struct_xc.rs b/src/test/ui/cross-crate/auxiliary/newtype_struct_xc.rs
deleted file mode 100644
index 9d1e074..0000000
--- a/src/test/ui/cross-crate/auxiliary/newtype_struct_xc.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-#![crate_type="lib"]
-
-pub struct Au(pub isize);
diff --git a/src/test/ui/cross-crate/auxiliary/xcrate_unit_struct.rs b/src/test/ui/cross-crate/auxiliary/xcrate_unit_struct.rs
deleted file mode 100644
index 69ed498..0000000
--- a/src/test/ui/cross-crate/auxiliary/xcrate_unit_struct.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-#![crate_type = "lib"]
-
-// used by the rpass test
-
-#[derive(Copy, Clone)]
-pub struct Struct;
-
-#[derive(Copy, Clone)]
-pub enum Unit {
- UnitVariant,
- Argument(Struct)
-}
-
-#[derive(Copy, Clone)]
-pub struct TupleStruct(pub usize, pub &'static str);
-
-// used by the cfail test
-
-#[derive(Copy, Clone)]
-pub struct StructWithFields {
- foo: isize,
-}
-
-#[derive(Copy, Clone)]
-pub enum EnumWithVariants {
- EnumVariant,
- EnumVariantArg(isize)
-}
diff --git a/src/test/ui/did_you_mean/compatible-variants-in-pat.rs b/src/test/ui/did_you_mean/compatible-variants-in-pat.rs
new file mode 100644
index 0000000..09e12da
--- /dev/null
+++ b/src/test/ui/did_you_mean/compatible-variants-in-pat.rs
@@ -0,0 +1,41 @@
+enum Foo {
+ Bar(Bar),
+}
+struct Bar {
+ x: i32,
+}
+
+fn a(f: Foo) {
+ match f {
+ Bar { x } => {
+ //~^ ERROR mismatched types
+ //~| HELP try wrapping
+ }
+ }
+}
+
+struct S;
+
+fn b(s: Option<S>) {
+ match s {
+ S => {
+ //~^ ERROR mismatched types
+ //~| HELP try wrapping
+ //~| HELP introduce a new binding instead
+ }
+ _ => {}
+ }
+}
+
+fn c(s: Result<S, S>) {
+ match s {
+ S => {
+ //~^ ERROR mismatched types
+ //~| HELP try wrapping
+ //~| HELP introduce a new binding instead
+ }
+ _ => {}
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/did_you_mean/compatible-variants-in-pat.stderr b/src/test/ui/did_you_mean/compatible-variants-in-pat.stderr
new file mode 100644
index 0000000..a4c77e0
--- /dev/null
+++ b/src/test/ui/did_you_mean/compatible-variants-in-pat.stderr
@@ -0,0 +1,68 @@
+error[E0308]: mismatched types
+ --> $DIR/compatible-variants-in-pat.rs:10:9
+ |
+LL | match f {
+ | - this expression has type `Foo`
+LL | Bar { x } => {
+ | ^^^^^^^^^ expected enum `Foo`, found struct `Bar`
+ |
+help: try wrapping the pattern in `Foo::Bar`
+ |
+LL | Foo::Bar(Bar { x }) => {
+ | +++++++++ +
+
+error[E0308]: mismatched types
+ --> $DIR/compatible-variants-in-pat.rs:21:9
+ |
+LL | struct S;
+ | --------- unit struct defined here
+...
+LL | match s {
+ | - this expression has type `Option<S>`
+LL | S => {
+ | ^
+ | |
+ | expected enum `Option`, found struct `S`
+ | `S` is interpreted as a unit struct, not a new binding
+ |
+ = note: expected enum `Option<S>`
+ found struct `S`
+help: try wrapping the pattern in `Some`
+ |
+LL | Some(S) => {
+ | +++++ +
+help: introduce a new binding instead
+ |
+LL | other_s => {
+ | ~~~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/compatible-variants-in-pat.rs:32:9
+ |
+LL | struct S;
+ | --------- unit struct defined here
+...
+LL | match s {
+ | - this expression has type `Result<S, S>`
+LL | S => {
+ | ^
+ | |
+ | expected enum `Result`, found struct `S`
+ | `S` is interpreted as a unit struct, not a new binding
+ |
+ = note: expected enum `Result<S, S>`
+ found struct `S`
+help: try wrapping the pattern in a variant of `Result`
+ |
+LL | Ok(S) => {
+ | +++ +
+LL | Err(S) => {
+ | ++++ +
+help: introduce a new binding instead
+ |
+LL | other_s => {
+ | ~~~~~~~
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/did_you_mean/compatible-variants.rs b/src/test/ui/did_you_mean/compatible-variants.rs
index b078064..5d7c611 100644
--- a/src/test/ui/did_you_mean/compatible-variants.rs
+++ b/src/test/ui/did_you_mean/compatible-variants.rs
@@ -64,3 +64,27 @@ fn main() {
//~^ ERROR mismatched types
//~| HELP try wrapping
}
+
+enum A {
+ B { b: B},
+}
+
+struct A2(B);
+
+enum B {
+ Fst,
+ Snd,
+}
+
+fn foo() {
+ // We don't want to suggest `A::B(B::Fst)` here.
+ let a: A = B::Fst;
+ //~^ ERROR mismatched types
+}
+
+fn bar() {
+ // But we _do_ want to suggest `A2(B::Fst)` here!
+ let a: A2 = B::Fst;
+ //~^ ERROR mismatched types
+ //~| HELP try wrapping
+}
diff --git a/src/test/ui/did_you_mean/compatible-variants.stderr b/src/test/ui/did_you_mean/compatible-variants.stderr
index 51c1bf9..a8cb5d6 100644
--- a/src/test/ui/did_you_mean/compatible-variants.stderr
+++ b/src/test/ui/did_you_mean/compatible-variants.stderr
@@ -190,6 +190,27 @@
LL | let _ = Foo { bar: Some(bar) };
| ++++++++++ +
-error: aborting due to 11 previous errors
+error[E0308]: mismatched types
+ --> $DIR/compatible-variants.rs:81:16
+ |
+LL | let a: A = B::Fst;
+ | - ^^^^^^ expected enum `A`, found enum `B`
+ | |
+ | expected due to this
+
+error[E0308]: mismatched types
+ --> $DIR/compatible-variants.rs:87:17
+ |
+LL | let a: A2 = B::Fst;
+ | -- ^^^^^^ expected struct `A2`, found enum `B`
+ | |
+ | expected due to this
+ |
+help: try wrapping the expression in `A2`
+ |
+LL | let a: A2 = A2(B::Fst);
+ | +++ +
+
+error: aborting due to 13 previous errors
For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-37026.rs b/src/test/ui/empty/issue-37026.rs
similarity index 100%
rename from src/test/ui/issues/issue-37026.rs
rename to src/test/ui/empty/issue-37026.rs
diff --git a/src/test/ui/issues/issue-37026.stderr b/src/test/ui/empty/issue-37026.stderr
similarity index 100%
rename from src/test/ui/issues/issue-37026.stderr
rename to src/test/ui/empty/issue-37026.stderr
diff --git a/src/test/ui/no-link.rs b/src/test/ui/empty/no-link.rs
similarity index 100%
rename from src/test/ui/no-link.rs
rename to src/test/ui/empty/no-link.rs
diff --git a/src/test/ui/generics/issue-95208-ignore-qself.fixed b/src/test/ui/generics/issue-95208-ignore-qself.fixed
new file mode 100644
index 0000000..608b4a2
--- /dev/null
+++ b/src/test/ui/generics/issue-95208-ignore-qself.fixed
@@ -0,0 +1,11 @@
+// run-rustfix
+
+#[allow(unused)]
+struct Struct<T>(T);
+
+impl<T: Iterator> Struct<T> where <T as std:: iter::Iterator>::Item: std::fmt::Display {
+//~^ ERROR expected `:` followed by trait or lifetime
+//~| HELP use single colon
+}
+
+fn main() {}
diff --git a/src/test/ui/generics/issue-95208-ignore-qself.rs b/src/test/ui/generics/issue-95208-ignore-qself.rs
new file mode 100644
index 0000000..da7efd5
--- /dev/null
+++ b/src/test/ui/generics/issue-95208-ignore-qself.rs
@@ -0,0 +1,11 @@
+// run-rustfix
+
+#[allow(unused)]
+struct Struct<T>(T);
+
+impl<T: Iterator> Struct<T> where <T as std:: iter::Iterator>::Item:: std::fmt::Display {
+//~^ ERROR expected `:` followed by trait or lifetime
+//~| HELP use single colon
+}
+
+fn main() {}
diff --git a/src/test/ui/generics/issue-95208-ignore-qself.stderr b/src/test/ui/generics/issue-95208-ignore-qself.stderr
new file mode 100644
index 0000000..acbc130
--- /dev/null
+++ b/src/test/ui/generics/issue-95208-ignore-qself.stderr
@@ -0,0 +1,10 @@
+error: expected `:` followed by trait or lifetime
+ --> $DIR/issue-95208-ignore-qself.rs:6:88
+ |
+LL | impl<T: Iterator> Struct<T> where <T as std:: iter::Iterator>::Item:: std::fmt::Display {
+ | --- ^
+ | |
+ | help: use single colon: `:`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/generics/issue-95208.fixed b/src/test/ui/generics/issue-95208.fixed
new file mode 100644
index 0000000..a0b1e88
--- /dev/null
+++ b/src/test/ui/generics/issue-95208.fixed
@@ -0,0 +1,11 @@
+// run-rustfix
+
+#[allow(unused)]
+struct Struct<T>(T);
+
+impl<T> Struct<T> where T: std::fmt::Display {
+//~^ ERROR expected `:` followed by trait or lifetime
+//~| HELP use single colon
+}
+
+fn main() {}
diff --git a/src/test/ui/generics/issue-95208.rs b/src/test/ui/generics/issue-95208.rs
new file mode 100644
index 0000000..0e30834
--- /dev/null
+++ b/src/test/ui/generics/issue-95208.rs
@@ -0,0 +1,11 @@
+// run-rustfix
+
+#[allow(unused)]
+struct Struct<T>(T);
+
+impl<T> Struct<T> where T:: std::fmt::Display {
+//~^ ERROR expected `:` followed by trait or lifetime
+//~| HELP use single colon
+}
+
+fn main() {}
diff --git a/src/test/ui/generics/issue-95208.stderr b/src/test/ui/generics/issue-95208.stderr
new file mode 100644
index 0000000..5595276
--- /dev/null
+++ b/src/test/ui/generics/issue-95208.stderr
@@ -0,0 +1,10 @@
+error: expected `:` followed by trait or lifetime
+ --> $DIR/issue-95208.rs:6:46
+ |
+LL | impl<T> Struct<T> where T:: std::fmt::Display {
+ | --- ^
+ | |
+ | help: use single colon: `:`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/auxiliary/empty-struct.rs b/src/test/ui/issues/auxiliary/empty-struct.rs
deleted file mode 100644
index 3fb40f6..0000000
--- a/src/test/ui/issues/auxiliary/empty-struct.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-pub struct XEmpty1 {}
-pub struct XEmpty2;
-pub struct XEmpty6();
-
-pub enum XE {
- XEmpty3 {},
- XEmpty4,
- XEmpty5(),
-}
diff --git a/src/test/ui/issues/issue-12552.stderr b/src/test/ui/issues/issue-12552.stderr
index 3d8852c..4b027eb 100644
--- a/src/test/ui/issues/issue-12552.stderr
+++ b/src/test/ui/issues/issue-12552.stderr
@@ -8,6 +8,10 @@
|
= note: expected enum `Result<_, {integer}>`
found enum `Option<_>`
+help: try wrapping the pattern in `Ok`
+ |
+LL | Ok(Some(k)) => match k {
+ | +++ +
error[E0308]: mismatched types
--> $DIR/issue-12552.rs:9:5
@@ -20,6 +24,10 @@
|
= note: expected enum `Result<_, {integer}>`
found enum `Option<_>`
+help: try wrapping the pattern in `Ok`
+ |
+LL | Ok(None) => ()
+ | +++ +
error: aborting due to 2 previous errors
diff --git a/src/test/ui/issues/issue-3680.stderr b/src/test/ui/issues/issue-3680.stderr
index e8fafa7..29ba44f 100644
--- a/src/test/ui/issues/issue-3680.stderr
+++ b/src/test/ui/issues/issue-3680.stderr
@@ -8,6 +8,10 @@
|
= note: expected enum `Option<_>`
found enum `Result<_, _>`
+help: try wrapping the pattern in `Some`
+ |
+LL | Some(Err(_)) => ()
+ | +++++ +
error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-51244.rs b/src/test/ui/issues/issue-51244.rs
deleted file mode 100644
index d634b8b..0000000
--- a/src/test/ui/issues/issue-51244.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-fn main() {
- let ref my_ref @ _ = 0;
- *my_ref = 0; //~ ERROR cannot assign to `*my_ref`, which is behind a `&` reference [E0594]
-}
diff --git a/src/test/ui/issues/issue-51244.stderr b/src/test/ui/issues/issue-51244.stderr
deleted file mode 100644
index 19f0223..0000000
--- a/src/test/ui/issues/issue-51244.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0594]: cannot assign to `*my_ref`, which is behind a `&` reference
- --> $DIR/issue-51244.rs:3:5
- |
-LL | let ref my_ref @ _ = 0;
- | -------------- help: consider changing this to be a mutable reference: `ref mut my_ref @ _`
-LL | *my_ref = 0;
- | ^^^^^^^^^^^ `my_ref` is a `&` reference, so the data it refers to cannot be written
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/issues/issue-5358-1.stderr b/src/test/ui/issues/issue-5358-1.stderr
index d1bc279..9d5b8d9 100644
--- a/src/test/ui/issues/issue-5358-1.stderr
+++ b/src/test/ui/issues/issue-5358-1.stderr
@@ -8,6 +8,10 @@
|
= note: expected struct `S`
found enum `Either<_, _>`
+help: try wrapping the pattern in `S`
+ |
+LL | S(Either::Right(_)) => {}
+ | ++ +
help: you might have meant to use field `0` whose type is `Either<usize, usize>`
|
LL | match S(Either::Left(5)).0 {
diff --git a/src/test/ui/macros/issue-95267.rs b/src/test/ui/macros/issue-95267.rs
new file mode 100644
index 0000000..4d59c7e
--- /dev/null
+++ b/src/test/ui/macros/issue-95267.rs
@@ -0,0 +1,13 @@
+// check-pass
+
+// This is a valid macro. Commit 4 in #95159 broke things such that it failed
+// with a "missing tokens in macro arguments" error, as reported in #95267.
+macro_rules! f {
+ (
+ /// ab
+ ) => {};
+}
+
+fn main() {
+ f!();
+}
diff --git a/src/test/ui/moves/borrow-closures-instead-of-move.rs b/src/test/ui/moves/borrow-closures-instead-of-move.rs
new file mode 100644
index 0000000..51771ce
--- /dev/null
+++ b/src/test/ui/moves/borrow-closures-instead-of-move.rs
@@ -0,0 +1,36 @@
+fn takes_fn(f: impl Fn()) {
+ loop {
+ takes_fnonce(f);
+ //~^ ERROR use of moved value
+ //~| HELP consider borrowing
+ }
+}
+
+fn takes_fn_mut(m: impl FnMut()) {
+ if maybe() {
+ takes_fnonce(m);
+ //~^ HELP consider mutably borrowing
+ }
+ takes_fnonce(m);
+ //~^ ERROR use of moved value
+}
+
+fn has_closure() {
+ let mut x = 0;
+ let mut closure = || {
+ x += 1;
+ };
+ takes_fnonce(closure);
+ //~^ HELP consider mutably borrowing
+ closure();
+ //~^ ERROR borrow of moved value
+}
+
+fn maybe() -> bool {
+ false
+}
+
+// Could also be Fn[Mut], here it doesn't matter
+fn takes_fnonce(_: impl FnOnce()) {}
+
+fn main() {}
diff --git a/src/test/ui/moves/borrow-closures-instead-of-move.stderr b/src/test/ui/moves/borrow-closures-instead-of-move.stderr
new file mode 100644
index 0000000..3146b69
--- /dev/null
+++ b/src/test/ui/moves/borrow-closures-instead-of-move.stderr
@@ -0,0 +1,53 @@
+error[E0382]: use of moved value: `f`
+ --> $DIR/borrow-closures-instead-of-move.rs:3:22
+ |
+LL | fn takes_fn(f: impl Fn()) {
+ | - move occurs because `f` has type `impl Fn()`, which does not implement the `Copy` trait
+LL | loop {
+LL | takes_fnonce(f);
+ | ^ value moved here, in previous iteration of loop
+ |
+help: consider borrowing `f`
+ |
+LL | takes_fnonce(&f);
+ | +
+
+error[E0382]: use of moved value: `m`
+ --> $DIR/borrow-closures-instead-of-move.rs:14:18
+ |
+LL | fn takes_fn_mut(m: impl FnMut()) {
+ | - move occurs because `m` has type `impl FnMut()`, which does not implement the `Copy` trait
+LL | if maybe() {
+LL | takes_fnonce(m);
+ | - value moved here
+...
+LL | takes_fnonce(m);
+ | ^ value used here after move
+ |
+help: consider mutably borrowing `m`
+ |
+LL | takes_fnonce(&mut m);
+ | ++++
+
+error[E0382]: borrow of moved value: `closure`
+ --> $DIR/borrow-closures-instead-of-move.rs:25:5
+ |
+LL | takes_fnonce(closure);
+ | ------- value moved here
+LL |
+LL | closure();
+ | ^^^^^^^ value borrowed here after move
+ |
+note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `x` out of its environment
+ --> $DIR/borrow-closures-instead-of-move.rs:21:9
+ |
+LL | x += 1;
+ | ^
+help: consider mutably borrowing `closure`
+ |
+LL | takes_fnonce(&mut closure);
+ | ++++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr b/src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr
index 2adaf57..4759b45 100644
--- a/src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr
+++ b/src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr
@@ -17,10 +17,10 @@
LL | f(&mut r, false)
| ^ value borrowed here after move
|
-help: consider further restricting this bound
+help: consider mutably borrowing `f`
|
-LL | fn conspirator<F>(mut f: F) where F: FnMut(&mut R, bool) + Copy {
- | ++++++
+LL | let mut r = R {c: Box::new(&mut f)};
+ | ++++
error: aborting due to 2 previous errors
diff --git a/src/test/ui/not-copy-closure.stderr b/src/test/ui/not-copy-closure.stderr
index 10bf570..93e011c 100644
--- a/src/test/ui/not-copy-closure.stderr
+++ b/src/test/ui/not-copy-closure.stderr
@@ -11,6 +11,10 @@
|
LL | a += 1;
| ^
+help: consider mutably borrowing `hello`
+ |
+LL | let b = &mut hello;
+ | ++++
error: aborting due to previous error
diff --git a/src/test/ui/weak-lang-item.rs b/src/test/ui/panic-handler/weak-lang-item-2.rs
similarity index 100%
rename from src/test/ui/weak-lang-item.rs
rename to src/test/ui/panic-handler/weak-lang-item-2.rs
diff --git a/src/test/ui/regions/regions-enum-not-wf.rs b/src/test/ui/regions/regions-enum-not-wf.rs
deleted file mode 100644
index 8b491ee..0000000
--- a/src/test/ui/regions/regions-enum-not-wf.rs
+++ /dev/null
@@ -1,39 +0,0 @@
-// Various examples of structs whose fields are not well-formed.
-
-#![allow(dead_code)]
-
-trait Dummy<'a> {
- type Out;
-}
-impl<'a, T> Dummy<'a> for T
-where
- T: 'a,
-{
- type Out = ();
-}
-type RequireOutlives<'a, T> = <T as Dummy<'a>>::Out;
-
-enum Ref1<'a, T> {
- Ref1Variant1(RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough
-}
-
-enum Ref2<'a, T> {
- Ref2Variant1,
- Ref2Variant2(isize, RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough
-}
-
-enum RefOk<'a, T: 'a> {
- RefOkVariant1(&'a T),
-}
-
-// This is now well formed. RFC 2093
-enum RefIndirect<'a, T> {
- RefIndirectVariant1(isize, RefOk<'a, T>),
-}
-
-enum RefDouble<'a, 'b, T> {
- RefDoubleVariant1(&'a RequireOutlives<'b, T>),
- //~^ the parameter type `T` may not live long enough [E0309]
-}
-
-fn main() {}
diff --git a/src/test/ui/regions/regions-enum-not-wf.stderr b/src/test/ui/regions/regions-enum-not-wf.stderr
deleted file mode 100644
index 553a3e7..0000000
--- a/src/test/ui/regions/regions-enum-not-wf.stderr
+++ /dev/null
@@ -1,28 +0,0 @@
-error[E0309]: the parameter type `T` may not live long enough
- --> $DIR/regions-enum-not-wf.rs:17:18
- |
-LL | enum Ref1<'a, T> {
- | - help: consider adding an explicit lifetime bound...: `T: 'a`
-LL | Ref1Variant1(RequireOutlives<'a, T>),
- | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
-
-error[E0309]: the parameter type `T` may not live long enough
- --> $DIR/regions-enum-not-wf.rs:22:25
- |
-LL | enum Ref2<'a, T> {
- | - help: consider adding an explicit lifetime bound...: `T: 'a`
-LL | Ref2Variant1,
-LL | Ref2Variant2(isize, RequireOutlives<'a, T>),
- | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
-
-error[E0309]: the parameter type `T` may not live long enough
- --> $DIR/regions-enum-not-wf.rs:35:23
- |
-LL | enum RefDouble<'a, 'b, T> {
- | - help: consider adding an explicit lifetime bound...: `T: 'b`
-LL | RefDoubleVariant1(&'a RequireOutlives<'b, T>),
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
index dd090a3..34f0592 100644
--- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
+++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
@@ -62,7 +62,7 @@
|
= note: only supported directly in conditions of `if` and `while` expressions
= note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
--> $DIR/disallowed-positions.rs:47:13
|
LL | if true || let 0 = 0 {}
@@ -76,7 +76,7 @@
|
= note: only supported directly in conditions of `if` and `while` expressions
= note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
--> $DIR/disallowed-positions.rs:48:14
|
LL | if (true || let 0 = 0) {}
@@ -90,7 +90,7 @@
|
= note: only supported directly in conditions of `if` and `while` expressions
= note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
--> $DIR/disallowed-positions.rs:49:22
|
LL | if true && (true || let 0 = 0) {}
@@ -104,7 +104,7 @@
|
= note: only supported directly in conditions of `if` and `while` expressions
= note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
--> $DIR/disallowed-positions.rs:50:13
|
LL | if true || (true && let 0 = 0) {}
@@ -244,7 +244,7 @@
|
= note: only supported directly in conditions of `if` and `while` expressions
= note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
--> $DIR/disallowed-positions.rs:111:16
|
LL | while true || let 0 = 0 {}
@@ -258,7 +258,7 @@
|
= note: only supported directly in conditions of `if` and `while` expressions
= note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
--> $DIR/disallowed-positions.rs:112:17
|
LL | while (true || let 0 = 0) {}
@@ -272,7 +272,7 @@
|
= note: only supported directly in conditions of `if` and `while` expressions
= note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
--> $DIR/disallowed-positions.rs:113:25
|
LL | while true && (true || let 0 = 0) {}
@@ -286,7 +286,7 @@
|
= note: only supported directly in conditions of `if` and `while` expressions
= note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
--> $DIR/disallowed-positions.rs:114:16
|
LL | while true || (true && let 0 = 0) {}
@@ -426,7 +426,7 @@
|
= note: only supported directly in conditions of `if` and `while` expressions
= note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
--> $DIR/disallowed-positions.rs:184:10
|
LL | true || let 0 = 0;
@@ -440,7 +440,7 @@
|
= note: only supported directly in conditions of `if` and `while` expressions
= note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
--> $DIR/disallowed-positions.rs:185:11
|
LL | (true || let 0 = 0);
@@ -454,7 +454,7 @@
|
= note: only supported directly in conditions of `if` and `while` expressions
= note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
--> $DIR/disallowed-positions.rs:186:19
|
LL | true && (true || let 0 = 0);
diff --git a/src/test/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-exitcode.rs b/src/test/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-exitcode.rs
index 9c2270b..6d4c156 100644
--- a/src/test/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-exitcode.rs
+++ b/src/test/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-exitcode.rs
@@ -1,5 +1,4 @@
// run-pass
-#![feature(process_exitcode_placeholder)]
use std::process::ExitCode;
diff --git a/src/test/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-impl-termination.rs b/src/test/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-impl-termination.rs
index 79cfba0..c06a135 100644
--- a/src/test/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-impl-termination.rs
+++ b/src/test/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-impl-termination.rs
@@ -1,4 +1,3 @@
// run-pass
-#![feature(termination_trait_lib)]
fn main() -> impl std::process::Termination { }
diff --git a/src/test/ui/span/E0057.rs b/src/test/ui/span/E0057.rs
deleted file mode 100644
index 83f941f..0000000
--- a/src/test/ui/span/E0057.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-fn main() {
- let f = |x| x * 3;
- let a = f(); //~ ERROR E0057
- let b = f(4);
- let c = f(2, 3); //~ ERROR E0057
-}
diff --git a/src/test/ui/span/E0057.stderr b/src/test/ui/span/E0057.stderr
deleted file mode 100644
index 31579e2..0000000
--- a/src/test/ui/span/E0057.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0057]: this function takes 1 argument but 0 arguments were supplied
- --> $DIR/E0057.rs:3:13
- |
-LL | let a = f();
- | ^-- supplied 0 arguments
- | |
- | expected 1 argument
-
-error[E0057]: this function takes 1 argument but 2 arguments were supplied
- --> $DIR/E0057.rs:5:13
- |
-LL | let c = f(2, 3);
- | ^ - - supplied 2 arguments
- | |
- | expected 1 argument
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0057`.
diff --git a/src/test/ui/cross-crate/cross-crate-newtype-struct-pat.rs b/src/test/ui/structs-enums/cross-crate-newtype-struct-pat.rs
similarity index 100%
rename from src/test/ui/cross-crate/cross-crate-newtype-struct-pat.rs
rename to src/test/ui/structs-enums/cross-crate-newtype-struct-pat.rs
diff --git a/src/test/ui/suggestions/suggest-private-fields.rs b/src/test/ui/structs/suggest-private-fields.rs
similarity index 100%
rename from src/test/ui/suggestions/suggest-private-fields.rs
rename to src/test/ui/structs/suggest-private-fields.rs
diff --git a/src/test/ui/suggestions/suggest-private-fields.stderr b/src/test/ui/structs/suggest-private-fields.stderr
similarity index 100%
rename from src/test/ui/suggestions/suggest-private-fields.stderr
rename to src/test/ui/structs/suggest-private-fields.stderr
diff --git a/src/test/ui/suggestions/auxiliary/struct_field_privacy.rs b/src/test/ui/suggestions/auxiliary/struct_field_privacy.rs
deleted file mode 100644
index 9765af1..0000000
--- a/src/test/ui/suggestions/auxiliary/struct_field_privacy.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-pub struct A {
- a: isize,
- pub b: isize,
-}
-
-pub struct B {
- pub a: isize,
- b: isize,
-}
diff --git a/src/test/ui/suggestions/derive-clone-for-eq.fixed b/src/test/ui/suggestions/derive-clone-for-eq.fixed
new file mode 100644
index 0000000..f07784d
--- /dev/null
+++ b/src/test/ui/suggestions/derive-clone-for-eq.fixed
@@ -0,0 +1,18 @@
+// run-rustfix
+// https://github.com/rust-lang/rust/issues/79076
+
+use std::cmp::PartialEq;
+
+#[derive(Clone, Eq)] //~ ERROR [E0277]
+pub struct Struct<T: std::clone::Clone>(T);
+
+impl<T: Clone, U> PartialEq<U> for Struct<T>
+where
+ U: Into<Struct<T>> + Clone
+{
+ fn eq(&self, _other: &U) -> bool {
+ todo!()
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/derive-clone-for-eq.rs b/src/test/ui/suggestions/derive-clone-for-eq.rs
new file mode 100644
index 0000000..15c0d46
--- /dev/null
+++ b/src/test/ui/suggestions/derive-clone-for-eq.rs
@@ -0,0 +1,18 @@
+// run-rustfix
+// https://github.com/rust-lang/rust/issues/79076
+
+use std::cmp::PartialEq;
+
+#[derive(Clone, Eq)] //~ ERROR [E0277]
+pub struct Struct<T>(T);
+
+impl<T: Clone, U> PartialEq<U> for Struct<T>
+where
+ U: Into<Struct<T>> + Clone
+{
+ fn eq(&self, _other: &U) -> bool {
+ todo!()
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/derive-clone-for-eq.stderr b/src/test/ui/suggestions/derive-clone-for-eq.stderr
new file mode 100644
index 0000000..55a23c0
--- /dev/null
+++ b/src/test/ui/suggestions/derive-clone-for-eq.stderr
@@ -0,0 +1,25 @@
+error[E0277]: the trait bound `T: Clone` is not satisfied
+ --> $DIR/derive-clone-for-eq.rs:6:17
+ |
+LL | #[derive(Clone, Eq)]
+ | ^^ the trait `Clone` is not implemented for `T`
+ |
+note: required because of the requirements on the impl of `PartialEq` for `Struct<T>`
+ --> $DIR/derive-clone-for-eq.rs:9:19
+ |
+LL | impl<T: Clone, U> PartialEq<U> for Struct<T>
+ | ^^^^^^^^^^^^ ^^^^^^^^^
+note: required by a bound in `Eq`
+ --> $SRC_DIR/core/src/cmp.rs:LL:COL
+ |
+LL | pub trait Eq: PartialEq<Self> {
+ | ^^^^^^^^^^^^^^^ required by this bound in `Eq`
+ = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+ |
+LL | pub struct Struct<T: std::clone::Clone>(T);
+ | +++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suggestions/suggest-mut-method-for-loop-hashmap.fixed b/src/test/ui/suggestions/suggest-mut-method-for-loop-hashmap.fixed
new file mode 100644
index 0000000..b69bad9
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-mut-method-for-loop-hashmap.fixed
@@ -0,0 +1,21 @@
+// run-rustfix
+// https://github.com/rust-lang/rust/issues/82081
+
+use std::collections::HashMap;
+
+struct Test {
+ v: u32,
+}
+
+fn main() {
+ let mut map = HashMap::new();
+ map.insert("a", Test { v: 0 });
+
+ for (_k, mut v) in map.iter_mut() {
+ //~^ HELP use mutable method
+ //~| NOTE this iterator yields `&` references
+ v.v += 1;
+ //~^ ERROR cannot assign to `v.v`
+ //~| NOTE `v` is a `&` reference
+ }
+}
diff --git a/src/test/ui/suggestions/suggest-mut-method-for-loop-hashmap.rs b/src/test/ui/suggestions/suggest-mut-method-for-loop-hashmap.rs
new file mode 100644
index 0000000..9284410
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-mut-method-for-loop-hashmap.rs
@@ -0,0 +1,21 @@
+// run-rustfix
+// https://github.com/rust-lang/rust/issues/82081
+
+use std::collections::HashMap;
+
+struct Test {
+ v: u32,
+}
+
+fn main() {
+ let mut map = HashMap::new();
+ map.insert("a", Test { v: 0 });
+
+ for (_k, mut v) in map.iter() {
+ //~^ HELP use mutable method
+ //~| NOTE this iterator yields `&` references
+ v.v += 1;
+ //~^ ERROR cannot assign to `v.v`
+ //~| NOTE `v` is a `&` reference
+ }
+}
diff --git a/src/test/ui/suggestions/suggest-mut-method-for-loop-hashmap.stderr b/src/test/ui/suggestions/suggest-mut-method-for-loop-hashmap.stderr
new file mode 100644
index 0000000..74433da
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-mut-method-for-loop-hashmap.stderr
@@ -0,0 +1,15 @@
+error[E0594]: cannot assign to `v.v`, which is behind a `&` reference
+ --> $DIR/suggest-mut-method-for-loop-hashmap.rs:17:9
+ |
+LL | for (_k, mut v) in map.iter() {
+ | ----------
+ | | |
+ | | help: use mutable method: `iter_mut()`
+ | this iterator yields `&` references
+...
+LL | v.v += 1;
+ | ^^^^^^^^ `v` is a `&` reference, so the data it refers to cannot be written
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/test-attrs/test-type.rs b/src/test/ui/test-attrs/test-type.rs
index 3f0fa81..f99e476 100644
--- a/src/test/ui/test-attrs/test-type.rs
+++ b/src/test/ui/test-attrs/test-type.rs
@@ -5,7 +5,6 @@
// ignore-emscripten no threads support
// run-pass
-
#[test]
fn test_ok() {
let _a = true;
@@ -18,9 +17,9 @@ fn test_panic() {
}
#[test]
-#[ignore]
+#[ignore = "msg"]
fn test_no_run() {
- loop{
+ loop {
println!("Hello, world");
}
}
diff --git a/src/test/ui/test-attrs/test-type.run.stdout b/src/test/ui/test-attrs/test-type.run.stdout
index be2fd8a..143c13a 100644
--- a/src/test/ui/test-attrs/test-type.run.stdout
+++ b/src/test/ui/test-attrs/test-type.run.stdout
@@ -1,6 +1,6 @@
running 3 tests
-test test_no_run ... ignored
+test test_no_run ... ignored, msg
test test_ok ... ok
test test_panic - should panic ... ok
diff --git a/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs b/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs
index c66009f..471a6b8 100644
--- a/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs
+++ b/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs
@@ -16,4 +16,8 @@ fn foo<T: Bar>(_: T) where <T as Bar>::Baz: String { //~ ERROR expected trait, f
fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: String { //~ ERROR expected trait, found
}
+fn issue_95327() where <u8 as Unresolved>::Assoc: String {}
+//~^ ERROR expected trait, found struct
+//~| ERROR use of undeclared type `Unresolved`
+
fn main() {}
diff --git a/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr b/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr
index 38b2e5a..9ca446a 100644
--- a/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr
+++ b/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr
@@ -1,3 +1,9 @@
+error[E0433]: failed to resolve: use of undeclared type `Unresolved`
+ --> $DIR/assoc_type_bound_with_struct.rs:19:31
+ |
+LL | fn issue_95327() where <u8 as Unresolved>::Assoc: String {}
+ | ^^^^^^^^^^ use of undeclared type `Unresolved`
+
error[E0404]: expected trait, found struct `String`
--> $DIR/assoc_type_bound_with_struct.rs:5:46
|
@@ -78,6 +84,18 @@
LL | fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: ToString {
| ~~~~~~~~
-error: aborting due to 4 previous errors
+error[E0404]: expected trait, found struct `String`
+ --> $DIR/assoc_type_bound_with_struct.rs:19:51
+ |
+LL | fn issue_95327() where <u8 as Unresolved>::Assoc: String {}
+ | ^^^^^^ help: a trait with a similar name exists: `ToString`
+ |
+ ::: $SRC_DIR/alloc/src/string.rs:LL:COL
+ |
+LL | pub trait ToString {
+ | ------------------ similarly named trait `ToString` defined here
-For more information about this error, try `rustc --explain E0404`.
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0404, E0433.
+For more information about an error, try `rustc --explain E0404`.
diff --git a/src/test/ui/cross-crate/xcrate-unit-struct.rs b/src/test/ui/xcrate/xcrate-unit-struct-2.rs
similarity index 100%
rename from src/test/ui/cross-crate/xcrate-unit-struct.rs
rename to src/test/ui/xcrate/xcrate-unit-struct-2.rs
diff --git a/src/tools/miri b/src/tools/miri
index 346f8f2..c1bbf07 160000
--- a/src/tools/miri
+++ b/src/tools/miri
@@ -1 +1 @@
-Subproject commit 346f8f2219562dae3fce5a35cc7eed4df8353b6c
+Subproject commit c1bbf078f368b1a16951730148fe15127df249ef
diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer
index b594f9c..bc08b8e 160000
--- a/src/tools/rust-analyzer
+++ b/src/tools/rust-analyzer
@@ -1 +1 @@
-Subproject commit b594f9c441cf12319d10c14ba6a511d5c9db1b87
+Subproject commit bc08b8eff3f8e4da7c448d7b7f6461938c817a60