Auto merge of #86180 - cjgillot:defmv, r=petrochenkov
Hash DefId in rustc_span.
This is mostly just moving code around. Changes are simplifications of unneeded callbacks from rustc_span to rustc_middle.
r? `@petrochenkov`
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index aa9d97b..3636263 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -259,6 +259,11 @@
- name: x86_64-gnu
os: ubuntu-latest-xl
env: {}
+ - name: x86_64-gnu-stable
+ env:
+ IMAGE: x86_64-gnu
+ RUST_CI_OVERRIDE_RELEASE_CHANNEL: stable
+ os: ubuntu-latest-xl
- name: x86_64-gnu-aux
os: ubuntu-latest-xl
env: {}
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index b3bac1d..93d7a59 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -623,12 +623,13 @@
PatKind::Ident(_, _, Some(p)) => p.walk(it),
// Walk into each field of struct.
- PatKind::Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk(it)),
+ PatKind::Struct(_, _, fields, _) => fields.iter().for_each(|field| field.pat.walk(it)),
// Sequence of patterns.
- PatKind::TupleStruct(_, s) | PatKind::Tuple(s) | PatKind::Slice(s) | PatKind::Or(s) => {
- s.iter().for_each(|p| p.walk(it))
- }
+ PatKind::TupleStruct(_, _, s)
+ | PatKind::Tuple(s)
+ | PatKind::Slice(s)
+ | PatKind::Or(s) => s.iter().for_each(|p| p.walk(it)),
// Trivial wrappers over inner patterns.
PatKind::Box(s) | PatKind::Ref(s, _) | PatKind::Paren(s) => s.walk(it),
@@ -701,10 +702,10 @@
/// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`).
/// The `bool` is `true` in the presence of a `..`.
- Struct(Path, Vec<PatField>, /* recovered */ bool),
+ Struct(Option<QSelf>, Path, Vec<PatField>, /* recovered */ bool),
/// A tuple struct/variant pattern (`Variant(x, y, .., z)`).
- TupleStruct(Path, Vec<P<Pat>>),
+ TupleStruct(Option<QSelf>, Path, Vec<P<Pat>>),
/// An or-pattern `A | B | C`.
/// Invariant: `pats.len() >= 2`.
@@ -1247,6 +1248,7 @@
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct StructExpr {
+ pub qself: Option<QSelf>,
pub path: Path,
pub fields: Vec<ExprField>,
pub rest: StructRest,
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 071d41e..0b6099f 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -1139,7 +1139,8 @@
visit_opt(sub, |sub| vis.visit_pat(sub));
}
PatKind::Lit(e) => vis.visit_expr(e),
- PatKind::TupleStruct(path, elems) => {
+ PatKind::TupleStruct(qself, path, elems) => {
+ vis.visit_qself(qself);
vis.visit_path(path);
visit_vec(elems, |elem| vis.visit_pat(elem));
}
@@ -1147,7 +1148,8 @@
vis.visit_qself(qself);
vis.visit_path(path);
}
- PatKind::Struct(path, fields, _etc) => {
+ PatKind::Struct(qself, path, fields, _etc) => {
+ vis.visit_qself(qself);
vis.visit_path(path);
fields.flat_map_in_place(|field| vis.flat_map_pat_field(field));
}
@@ -1333,7 +1335,8 @@
}
ExprKind::MacCall(mac) => vis.visit_mac_call(mac),
ExprKind::Struct(se) => {
- let StructExpr { path, fields, rest } = se.deref_mut();
+ let StructExpr { qself, path, fields, rest } = se.deref_mut();
+ vis.visit_qself(qself);
vis.visit_path(path);
fields.flat_map_in_place(|field| vis.flat_map_expr_field(field));
match rest {
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index f1a99bc..1ebfcf3 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -497,7 +497,10 @@
pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) {
match pattern.kind {
- PatKind::TupleStruct(ref path, ref elems) => {
+ PatKind::TupleStruct(ref opt_qself, ref path, ref elems) => {
+ if let Some(ref qself) = *opt_qself {
+ visitor.visit_ty(&qself.ty);
+ }
visitor.visit_path(path, pattern.id);
walk_list!(visitor, visit_pat, elems);
}
@@ -507,7 +510,10 @@
}
visitor.visit_path(path, pattern.id)
}
- PatKind::Struct(ref path, ref fields, _) => {
+ PatKind::Struct(ref opt_qself, ref path, ref fields, _) => {
+ if let Some(ref qself) = *opt_qself {
+ visitor.visit_ty(&qself.ty);
+ }
visitor.visit_path(path, pattern.id);
walk_list!(visitor, visit_pat_field, fields);
}
@@ -740,6 +746,9 @@
visitor.visit_anon_const(count)
}
ExprKind::Struct(ref se) => {
+ if let Some(ref qself) = se.qself {
+ visitor.visit_ty(&qself.ty);
+ }
visitor.visit_path(&se.path, expression.id);
walk_list!(visitor, visit_expr_field, &se.fields);
match &se.rest {
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 866f218..b9dcd08 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -237,7 +237,7 @@
hir::ExprKind::Struct(
self.arena.alloc(self.lower_qpath(
e.id,
- &None,
+ &se.qself,
&se.path,
ParamMode::Optional,
ImplTraitContext::disallowed(),
@@ -1041,10 +1041,12 @@
/// It is not a complete check, but just tries to reject most paths early
/// if they are not tuple structs.
/// Type checking will take care of the full validation later.
- fn extract_tuple_struct_path<'a>(&mut self, expr: &'a Expr) -> Option<&'a Path> {
- // For tuple struct destructuring, it must be a non-qualified path (like in patterns).
- if let ExprKind::Path(None, path) = &expr.kind {
- // Does the path resolves to something disallowed in a tuple struct/variant pattern?
+ fn extract_tuple_struct_path<'a>(
+ &mut self,
+ expr: &'a Expr,
+ ) -> Option<(&'a Option<QSelf>, &'a Path)> {
+ if let ExprKind::Path(qself, path) = &expr.kind {
+ // Does the path resolve to something disallowed in a tuple struct/variant pattern?
if let Some(partial_res) = self.resolver.get_partial_res(expr.id) {
if partial_res.unresolved_segments() == 0
&& !partial_res.base_res().expected_in_tuple_struct_pat()
@@ -1052,7 +1054,7 @@
return None;
}
}
- return Some(path);
+ return Some((qself, path));
}
None
}
@@ -1088,7 +1090,7 @@
}
// Tuple structs.
ExprKind::Call(callee, args) => {
- if let Some(path) = self.extract_tuple_struct_path(callee) {
+ if let Some((qself, path)) = self.extract_tuple_struct_path(callee) {
let (pats, rest) = self.destructure_sequence(
args,
"tuple struct or variant",
@@ -1097,7 +1099,7 @@
);
let qpath = self.lower_qpath(
callee.id,
- &None,
+ qself,
path,
ParamMode::Optional,
ImplTraitContext::disallowed(),
@@ -1122,7 +1124,7 @@
}));
let qpath = self.lower_qpath(
lhs.id,
- &None,
+ &se.qself,
&se.path,
ParamMode::Optional,
ImplTraitContext::disallowed(),
diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs
index 2451409..66e6235 100644
--- a/compiler/rustc_ast_lowering/src/pat.rs
+++ b/compiler/rustc_ast_lowering/src/pat.rs
@@ -21,10 +21,10 @@
break self.lower_pat_ident(pattern, binding_mode, ident, lower_sub);
}
PatKind::Lit(ref e) => break hir::PatKind::Lit(self.lower_expr(e)),
- PatKind::TupleStruct(ref path, ref pats) => {
+ PatKind::TupleStruct(ref qself, ref path, ref pats) => {
let qpath = self.lower_qpath(
pattern.id,
- &None,
+ qself,
path,
ParamMode::Optional,
ImplTraitContext::disallowed(),
@@ -47,10 +47,10 @@
);
break hir::PatKind::Path(qpath);
}
- PatKind::Struct(ref path, ref fields, etc) => {
+ PatKind::Struct(ref qself, ref path, ref fields, etc) => {
let qpath = self.lower_qpath(
pattern.id,
- &None,
+ qself,
path,
ParamMode::Optional,
ImplTraitContext::disallowed(),
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index ba2da76..30aa51a 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -938,8 +938,11 @@
}
GenericParamKind::Type { default: None } => (),
GenericParamKind::Lifetime => (),
- // FIXME(const_generics_defaults)
- GenericParamKind::Const { ty: _, kw_span: _, default: _ } => (),
+ GenericParamKind::Const { ty: _, kw_span: _, default: Some(default) } => {
+ ordered_params += " = ";
+ ordered_params += &pprust::expr_to_string(&*default.value);
+ }
+ GenericParamKind::Const { ty: _, kw_span: _, default: None } => (),
}
first = false;
}
@@ -959,7 +962,7 @@
span,
&format!(
"reorder the parameters: lifetimes, {}",
- if sess.features_untracked().const_generics {
+ if sess.features_untracked().unordered_const_ty_params() {
"then consts and types"
} else {
"then types, then consts"
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 664e138..3f98944 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -705,6 +705,7 @@
"async closures are unstable",
"to use an async block, remove the `||`: `async {`"
);
+ gate_all!(more_qualified_paths, "usage of qualified paths in this context is experimental");
gate_all!(generators, "yield syntax is experimental");
gate_all!(raw_ref_op, "raw address of syntax is experimental");
gate_all!(const_trait_bound_opt_out, "`?const` on trait bounds is experimental");
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index b7bb896..93facd2 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -1713,11 +1713,16 @@
fn print_expr_struct(
&mut self,
+ qself: &Option<ast::QSelf>,
path: &ast::Path,
fields: &[ast::ExprField],
rest: &ast::StructRest,
) {
- self.print_path(path, true, 0);
+ if let Some(qself) = qself {
+ self.print_qpath(path, qself, true);
+ } else {
+ self.print_path(path, true, 0);
+ }
self.s.word("{");
self.commasep_cmnt(
Consistent,
@@ -1874,7 +1879,7 @@
self.print_expr_repeat(element, count);
}
ast::ExprKind::Struct(ref se) => {
- self.print_expr_struct(&se.path, &se.fields, &se.rest);
+ self.print_expr_struct(&se.qself, &se.path, &se.fields, &se.rest);
}
ast::ExprKind::Tup(ref exprs) => {
self.print_expr_tup(exprs);
@@ -2340,8 +2345,12 @@
self.print_pat(p);
}
}
- PatKind::TupleStruct(ref path, ref elts) => {
- self.print_path(path, true, 0);
+ PatKind::TupleStruct(ref qself, ref path, ref elts) => {
+ if let Some(qself) = qself {
+ self.print_qpath(path, qself, true);
+ } else {
+ self.print_path(path, true, 0);
+ }
self.popen();
self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p));
self.pclose();
@@ -2355,8 +2364,12 @@
PatKind::Path(Some(ref qself), ref path) => {
self.print_qpath(path, qself, false);
}
- PatKind::Struct(ref path, ref fields, etc) => {
- self.print_path(path, true, 0);
+ PatKind::Struct(ref qself, ref path, ref fields, etc) => {
+ if let Some(qself) = qself {
+ self.print_qpath(path, qself, true);
+ } else {
+ self.print_path(path, true, 0);
+ }
self.nbsp();
self.word_space("{");
self.commasep_cmnt(
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index cb56e3f..6c9ec9e 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -5,7 +5,7 @@
use rustc_hir::def_id::CrateNum;
use rustc_middle::middle::cstore::{DllImport, LibSource};
use rustc_middle::middle::dependency_format::Linkage;
-use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, Strip};
+use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip};
use rustc_session::config::{OutputFilenames, OutputType, PrintRequest};
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
use rustc_session::search_paths::PathKind;
@@ -1927,6 +1927,8 @@
out_filename: &Path,
tmpdir: &Path,
) {
+ add_gcc_ld_path(cmd, sess, flavor);
+
add_apple_sdk(cmd, sess, flavor);
add_link_script(cmd, sess, tmpdir, crate_type);
@@ -2528,3 +2530,30 @@
Err(e) => Err(format!("failed to get {} SDK path: {}", sdk_name, e)),
}
}
+
+fn add_gcc_ld_path(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
+ if let Some(ld_impl) = sess.opts.debugging_opts.gcc_ld {
+ if let LinkerFlavor::Gcc = flavor {
+ match ld_impl {
+ LdImpl::Lld => {
+ let tools_path =
+ sess.host_filesearch(PathKind::All).get_tools_search_paths(false);
+ let lld_path = tools_path
+ .into_iter()
+ .map(|p| p.join("gcc-ld"))
+ .find(|p| {
+ p.join(if sess.host.is_like_windows { "ld.exe" } else { "ld" }).exists()
+ })
+ .unwrap_or_else(|| sess.fatal("rust-lld (as ld) not found"));
+ cmd.cmd().arg({
+ let mut arg = OsString::from("-B");
+ arg.push(lld_path);
+ arg
+ });
+ }
+ }
+ } else {
+ sess.fatal("option `-Z gcc-ld` is used even though linker flavor is not gcc");
+ }
+ }
+}
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index b10de56..c89d42e 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -205,7 +205,7 @@
];
const WASM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
- ("simd128", Some(sym::wasm_target_feature)),
+ ("simd128", None),
("atomics", Some(sym::wasm_target_feature)),
("nontrapping-fptoint", Some(sym::wasm_target_feature)),
];
diff --git a/compiler/rustc_data_structures/src/box_region.rs b/compiler/rustc_data_structures/src/box_region.rs
deleted file mode 100644
index eb6f4e8..0000000
--- a/compiler/rustc_data_structures/src/box_region.rs
+++ /dev/null
@@ -1,169 +0,0 @@
-//! This module provides a way to deal with self-referential data.
-//!
-//! The main idea is to allocate such data in a generator frame and then
-//! give access to it by executing user-provided closures inside that generator.
-//! The module provides a safe abstraction for the latter task.
-//!
-//! The interface consists of two exported macros meant to be used together:
-//! * `declare_box_region_type` wraps a generator inside a struct with `access`
-//! method which accepts closures.
-//! * `box_region_allow_access` is a helper which should be called inside
-//! a generator to actually execute those closures.
-
-use std::marker::PhantomData;
-use std::ops::{Generator, GeneratorState};
-use std::pin::Pin;
-
-#[derive(Copy, Clone)]
-pub struct AccessAction(*mut dyn FnMut());
-
-impl AccessAction {
- pub fn get(self) -> *mut dyn FnMut() {
- self.0
- }
-}
-
-#[derive(Copy, Clone)]
-pub enum Action {
- Initial,
- Access(AccessAction),
- Complete,
-}
-
-pub struct PinnedGenerator<I, A, R> {
- generator: Pin<Box<dyn Generator<Action, Yield = YieldType<I, A>, Return = R>>>,
-}
-
-impl<I, A, R> PinnedGenerator<I, A, R> {
- pub fn new<T: Generator<Action, Yield = YieldType<I, A>, Return = R> + 'static>(
- generator: T,
- ) -> (I, Self) {
- let mut result = PinnedGenerator { generator: Box::pin(generator) };
-
- // Run it to the first yield to set it up
- let init = match Pin::new(&mut result.generator).resume(Action::Initial) {
- GeneratorState::Yielded(YieldType::Initial(y)) => y,
- _ => panic!(),
- };
-
- (init, result)
- }
-
- pub unsafe fn access(&mut self, closure: *mut dyn FnMut()) {
- // Call the generator, which in turn will call the closure
- if let GeneratorState::Complete(_) =
- Pin::new(&mut self.generator).resume(Action::Access(AccessAction(closure)))
- {
- panic!()
- }
- }
-
- pub fn complete(&mut self) -> R {
- // Tell the generator we want it to complete, consuming it and yielding a result
- let result = Pin::new(&mut self.generator).resume(Action::Complete);
- if let GeneratorState::Complete(r) = result { r } else { panic!() }
- }
-}
-
-#[derive(PartialEq)]
-pub struct Marker<T>(PhantomData<T>);
-
-impl<T> Marker<T> {
- pub unsafe fn new() -> Self {
- Marker(PhantomData)
- }
-}
-
-pub enum YieldType<I, A> {
- Initial(I),
- Accessor(Marker<A>),
-}
-
-#[macro_export]
-#[allow_internal_unstable(fn_traits)]
-macro_rules! declare_box_region_type {
- (impl $v:vis
- $name: ident,
- $yield_type:ty,
- for($($lifetimes:tt)*),
- ($($args:ty),*) -> ($reti:ty, $retc:ty)
- ) => {
- $v struct $name($crate::box_region::PinnedGenerator<
- $reti,
- for<$($lifetimes)*> fn(($($args,)*)),
- $retc
- >);
-
- impl $name {
- fn new<T: ::std::ops::Generator<$crate::box_region::Action, Yield = $yield_type, Return = $retc> + 'static>(
- generator: T
- ) -> ($reti, Self) {
- let (initial, pinned) = $crate::box_region::PinnedGenerator::new(generator);
- (initial, $name(pinned))
- }
-
- $v fn access<F: for<$($lifetimes)*> FnOnce($($args,)*) -> R, R>(&mut self, f: F) -> R {
- // Turn the FnOnce closure into *mut dyn FnMut()
- // so we can pass it in to the generator
- let mut r = None;
- let mut f = Some(f);
- let mut_f: &mut dyn for<$($lifetimes)*> FnMut(($($args,)*)) =
- &mut |args| {
- let f = f.take().unwrap();
- r = Some(FnOnce::call_once(f, args));
- };
- let mut_f = mut_f as *mut dyn for<$($lifetimes)*> FnMut(($($args,)*));
-
- // Get the generator to call our closure
- unsafe {
- self.0.access(::std::mem::transmute(mut_f));
- }
-
- // Unwrap the result
- r.unwrap()
- }
-
- $v fn complete(mut self) -> $retc {
- self.0.complete()
- }
-
- fn initial_yield(value: $reti) -> $yield_type {
- $crate::box_region::YieldType::Initial(value)
- }
- }
- };
-
- ($v:vis $name: ident, for($($lifetimes:tt)*), ($($args:ty),*) -> ($reti:ty, $retc:ty)) => {
- declare_box_region_type!(
- impl $v $name,
- $crate::box_region::YieldType<$reti, for<$($lifetimes)*> fn(($($args,)*))>,
- for($($lifetimes)*),
- ($($args),*) -> ($reti, $retc)
- );
- };
-}
-
-#[macro_export]
-#[allow_internal_unstable(fn_traits)]
-macro_rules! box_region_allow_access {
- (for($($lifetimes:tt)*), ($($args:ty),*), ($($exprs:expr),*), $action:ident) => {
- loop {
- match $action {
- $crate::box_region::Action::Access(accessor) => {
- let accessor: &mut dyn for<$($lifetimes)*> FnMut($($args),*) = unsafe {
- ::std::mem::transmute(accessor.get())
- };
- (*accessor)(($($exprs),*));
- unsafe {
- let marker = $crate::box_region::Marker::<
- for<$($lifetimes)*> fn(($($args,)*))
- >::new();
- $action = yield $crate::box_region::YieldType::Accessor(marker);
- };
- }
- $crate::box_region::Action::Complete => break,
- $crate::box_region::Action::Initial => panic!("unexpected box_region action: Initial"),
- }
- }
- }
-}
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index bbfe225..16151e9 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -10,7 +10,6 @@
#![feature(array_windows)]
#![feature(control_flow_enum)]
#![feature(in_band_lifetimes)]
-#![feature(generator_trait)]
#![feature(min_specialization)]
#![feature(auto_traits)]
#![feature(nll)]
@@ -63,7 +62,6 @@
pub mod base_n;
pub mod binary_search_util;
-pub mod box_region;
pub mod captures;
pub mod flock;
pub mod functor;
diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs
index cb8b939..ef5b97a 100644
--- a/compiler/rustc_expand/src/build.rs
+++ b/compiler/rustc_expand/src/build.rs
@@ -275,7 +275,12 @@
) -> P<ast::Expr> {
self.expr(
span,
- ast::ExprKind::Struct(P(ast::StructExpr { path, fields, rest: ast::StructRest::None })),
+ ast::ExprKind::Struct(P(ast::StructExpr {
+ qself: None,
+ path,
+ fields,
+ rest: ast::StructRest::None,
+ })),
)
}
pub fn expr_struct_ident(
@@ -405,7 +410,7 @@
path: ast::Path,
subpats: Vec<P<ast::Pat>>,
) -> P<ast::Pat> {
- self.pat(span, PatKind::TupleStruct(path, subpats))
+ self.pat(span, PatKind::TupleStruct(None, path, subpats))
}
pub fn pat_struct(
&self,
@@ -413,7 +418,7 @@
path: ast::Path,
field_pats: Vec<ast::PatField>,
) -> P<ast::Pat> {
- self.pat(span, PatKind::Struct(path, field_pats, false))
+ self.pat(span, PatKind::Struct(None, path, field_pats, false))
}
pub fn pat_tuple(&self, span: Span, pats: Vec<P<ast::Pat>>) -> P<ast::Pat> {
self.pat(span, PatKind::Tuple(pats))
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 0359f50..56a320c 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -663,6 +663,9 @@
/// Allows unnamed fields of struct and union type
(active, unnamed_fields, "1.53.0", Some(49804), None),
+ /// Allows qualified paths in struct expressions, struct patterns and tuple struct patterns.
+ (active, more_qualified_paths, "1.54.0", Some(80080), None),
+
// -------------------------------------------------------------------------
// feature-group-end: actual feature gates
// -------------------------------------------------------------------------
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index fb762d2..e3a79fe 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -64,6 +64,7 @@
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{Item, ItemKind, Node};
+use rustc_middle::dep_graph::DepContext;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::{
self,
@@ -1965,7 +1966,33 @@
struct_span_err!(self.tcx.sess, span, E0580, "{}", failure_str)
}
FailureCode::Error0308(failure_str) => {
- struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str)
+ let mut err = struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str);
+ if let ValuePairs::Types(ty::error::ExpectedFound { expected, found }) =
+ trace.values
+ {
+ // If a tuple of length one was expected and the found expression has
+ // parentheses around it, perhaps the user meant to write `(expr,)` to
+ // build a tuple (issue #86100)
+ match (expected.kind(), found.kind()) {
+ (ty::Tuple(_), ty::Tuple(_)) => {}
+ (ty::Tuple(_), _) if expected.tuple_fields().count() == 1 => {
+ if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) {
+ if let Some(code) =
+ code.strip_prefix('(').and_then(|s| s.strip_suffix(')'))
+ {
+ err.span_suggestion(
+ span,
+ "use a trailing comma to create a tuple with one element",
+ format!("({},)", code),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ }
+ }
+ _ => {}
+ }
+ }
+ err
}
FailureCode::Error0644(failure_str) => {
struct_span_err!(self.tcx.sess, span, E0644, "{}", failure_str)
diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs
index b5af2bf..c7424b9 100644
--- a/compiler/rustc_interface/src/lib.rs
+++ b/compiler/rustc_interface/src/lib.rs
@@ -2,8 +2,6 @@
#![feature(box_patterns)]
#![feature(internal_output_capture)]
#![feature(nll)]
-#![feature(generator_trait)]
-#![feature(generators)]
#![feature(once_cell)]
#![recursion_limit = "256"]
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index cfe65c5..9e3e96d 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -6,10 +6,10 @@
use rustc_ast::{self as ast, visit};
use rustc_codegen_ssa::back::link::emit_metadata;
use rustc_codegen_ssa::traits::CodegenBackend;
+use rustc_data_structures::parallel;
use rustc_data_structures::steal::Steal;
use rustc_data_structures::sync::{par_iter, Lrc, OnceCell, ParallelIterator, WorkerLocal};
use rustc_data_structures::temp_dir::MaybeTempDir;
-use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel};
use rustc_errors::{ErrorReported, PResult};
use rustc_expand::base::ExtCtxt;
use rustc_hir::def_id::LOCAL_CRATE;
@@ -47,7 +47,9 @@
use std::ffi::OsString;
use std::io::{self, BufWriter, Write};
use std::lazy::SyncLazy;
+use std::marker::PhantomPinned;
use std::path::PathBuf;
+use std::pin::Pin;
use std::rc::Rc;
use std::{env, fs, iter};
@@ -85,11 +87,83 @@
counter.count
}
-declare_box_region_type!(
- pub BoxedResolver,
- for(),
- (&mut Resolver<'_>) -> (Result<ast::Crate>, ResolverOutputs)
-);
+pub use boxed_resolver::BoxedResolver;
+mod boxed_resolver {
+ use super::*;
+
+ pub struct BoxedResolver(Pin<Box<BoxedResolverInner>>);
+
+ struct BoxedResolverInner {
+ session: Lrc<Session>,
+ resolver_arenas: Option<ResolverArenas<'static>>,
+ resolver: Option<Resolver<'static>>,
+ _pin: PhantomPinned,
+ }
+
+ // Note: Drop order is important to prevent dangling references. Resolver must be dropped first,
+ // then resolver_arenas and finally session.
+ impl Drop for BoxedResolverInner {
+ fn drop(&mut self) {
+ self.resolver.take();
+ self.resolver_arenas.take();
+ }
+ }
+
+ impl BoxedResolver {
+ pub(super) fn new<F>(session: Lrc<Session>, make_resolver: F) -> Result<(ast::Crate, Self)>
+ where
+ F: for<'a> FnOnce(
+ &'a Session,
+ &'a ResolverArenas<'a>,
+ ) -> Result<(ast::Crate, Resolver<'a>)>,
+ {
+ let mut boxed_resolver = Box::new(BoxedResolverInner {
+ session,
+ resolver_arenas: Some(Resolver::arenas()),
+ resolver: None,
+ _pin: PhantomPinned,
+ });
+ // SAFETY: `make_resolver` takes a resolver arena with an arbitrary lifetime and
+ // returns a resolver with the same lifetime as the arena. We ensure that the arena
+ // outlives the resolver in the drop impl and elsewhere so these transmutes are sound.
+ unsafe {
+ let (crate_, resolver) = make_resolver(
+ std::mem::transmute::<&Session, &Session>(&boxed_resolver.session),
+ std::mem::transmute::<&ResolverArenas<'_>, &ResolverArenas<'_>>(
+ boxed_resolver.resolver_arenas.as_ref().unwrap(),
+ ),
+ )?;
+ boxed_resolver.resolver = Some(resolver);
+ Ok((crate_, BoxedResolver(Pin::new_unchecked(boxed_resolver))))
+ }
+ }
+
+ pub fn access<F: for<'a> FnOnce(&mut Resolver<'a>) -> R, R>(&mut self, f: F) -> R {
+ // SAFETY: The resolver doesn't need to be pinned.
+ let mut resolver = unsafe {
+ self.0.as_mut().map_unchecked_mut(|boxed_resolver| &mut boxed_resolver.resolver)
+ };
+ f((&mut *resolver).as_mut().unwrap())
+ }
+
+ pub fn to_resolver_outputs(resolver: Rc<RefCell<BoxedResolver>>) -> ResolverOutputs {
+ match Rc::try_unwrap(resolver) {
+ Ok(resolver) => {
+ let mut resolver = resolver.into_inner();
+ // SAFETY: The resolver doesn't need to be pinned.
+ let mut resolver = unsafe {
+ resolver
+ .0
+ .as_mut()
+ .map_unchecked_mut(|boxed_resolver| &mut boxed_resolver.resolver)
+ };
+ resolver.take().unwrap().into_outputs()
+ }
+ Err(resolver) => resolver.borrow_mut().access(|resolver| resolver.clone_outputs()),
+ }
+ }
+ }
+}
/// Runs the "early phases" of the compiler: initial `cfg` processing, loading compiler plugins,
/// syntax expansion, secondary `cfg` expansion, synthesis of a test
@@ -111,41 +185,16 @@
// its contents but the results of name resolution on those contents. Hopefully we'll push
// this back at some point.
let crate_name = crate_name.to_string();
- let (result, resolver) = BoxedResolver::new(static move |mut action| {
- let _ = action;
- let sess = &*sess;
- let resolver_arenas = Resolver::arenas();
- let res = configure_and_expand_inner(
+ BoxedResolver::new(sess, move |sess, resolver_arenas| {
+ configure_and_expand_inner(
sess,
&lint_store,
krate,
&crate_name,
&resolver_arenas,
- &*metadata_loader,
- );
- let mut resolver = match res {
- Err(v) => {
- yield BoxedResolver::initial_yield(Err(v));
- panic!()
- }
- Ok((krate, resolver)) => {
- action = yield BoxedResolver::initial_yield(Ok(krate));
- resolver
- }
- };
- box_region_allow_access!(for(), (&mut Resolver<'_>), (&mut resolver), action);
- resolver.into_outputs()
- });
- result.map(|k| (k, resolver))
-}
-
-impl BoxedResolver {
- pub fn to_resolver_outputs(resolver: Rc<RefCell<BoxedResolver>>) -> ResolverOutputs {
- match Rc::try_unwrap(resolver) {
- Ok(resolver) => resolver.into_inner().complete(),
- Err(resolver) => resolver.borrow_mut().access(|resolver| resolver.clone_outputs()),
- }
- }
+ metadata_loader,
+ )
+ })
}
pub fn register_plugins<'a>(
@@ -231,11 +280,11 @@
fn configure_and_expand_inner<'a>(
sess: &'a Session,
- lint_store: &'a LintStore,
+ lint_store: &LintStore,
mut krate: ast::Crate,
crate_name: &str,
resolver_arenas: &'a ResolverArenas<'a>,
- metadata_loader: &'a MetadataLoaderDyn,
+ metadata_loader: Box<MetadataLoaderDyn>,
) -> Result<(ast::Crate, Resolver<'a>)> {
tracing::trace!("configure_and_expand_inner");
pre_expansion_lint(sess, lint_store, &krate, crate_name);
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 67946df..44c2a55 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -858,10 +858,10 @@
// The other cases do not contain sub-patterns.
| Wild | Rest | Lit(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) => {},
// These are list-like patterns; parens can always be removed.
- TupleStruct(_, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps {
+ TupleStruct(_, _, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps {
self.check_unused_parens_pat(cx, p, false, false);
},
- Struct(_, fps, _) => for f in fps {
+ Struct(_, _, fps, _) => for f in fps {
self.check_unused_parens_pat(cx, &f.pat, false, false);
},
// Avoid linting on `i @ (p0 | .. | pn)` and `box (p0 | .. | pn)`, #64106.
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index e9ae22f..d73cfe3 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -54,7 +54,7 @@
pub struct CrateLoader<'a> {
// Immutable configuration.
sess: &'a Session,
- metadata_loader: &'a MetadataLoaderDyn,
+ metadata_loader: Box<MetadataLoaderDyn>,
local_crate_name: Symbol,
// Mutable output.
cstore: CStore,
@@ -219,7 +219,7 @@
impl<'a> CrateLoader<'a> {
pub fn new(
sess: &'a Session,
- metadata_loader: &'a MetadataLoaderDyn,
+ metadata_loader: Box<MetadataLoaderDyn>,
local_crate_name: &str,
) -> Self {
let local_crate_stable_id =
@@ -544,7 +544,7 @@
info!("falling back to a load");
let mut locator = CrateLocator::new(
self.sess,
- self.metadata_loader,
+ &*self.metadata_loader,
name,
hash,
host_hash,
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index 982c8a3..bfb4c0c 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -54,7 +54,7 @@
/// ADTs with no type arguments.
pub fn is_simple_text(&self) -> bool {
match self.kind() {
- Adt(_, substs) => substs.types().next().is_none(),
+ Adt(_, substs) => substs.non_erasable_generics().next().is_none(),
Ref(_, ty, _) => ty.is_simple_text(),
_ => self.is_simple_ty(),
}
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index 872d12c..3f426b1 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -112,7 +112,7 @@
///////////////////////////////////////////////////////////////////////////
// Relate impls
-fn relate_type_and_mut<'tcx, R: TypeRelation<'tcx>>(
+pub fn relate_type_and_mut<'tcx, R: TypeRelation<'tcx>>(
relation: &mut R,
a: ty::TypeAndMut<'tcx>,
b: ty::TypeAndMut<'tcx>,
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs
index d2b1566..bf5f2c0 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs
@@ -902,9 +902,13 @@
{
let lt_name = &src[1..ws_pos];
let ty = &src[ws_pos..];
- return (assignment_rhs_span, format!("&{} mut {}", lt_name, ty));
+ if !ty.trim_start().starts_with("mut") {
+ return (assignment_rhs_span, format!("&{} mut {}", lt_name, ty));
+ }
} else if let Some(stripped) = src.strip_prefix('&') {
- return (assignment_rhs_span, format!("&mut {}", stripped));
+ if !stripped.trim_start().starts_with("mut") {
+ return (assignment_rhs_span, format!("&mut {}", stripped));
+ }
}
}
}
diff --git a/compiler/rustc_mir/src/interpret/intrinsics.rs b/compiler/rustc_mir/src/interpret/intrinsics.rs
index 99622fb..4e4166d 100644
--- a/compiler/rustc_mir/src/interpret/intrinsics.rs
+++ b/compiler/rustc_mir/src/interpret/intrinsics.rs
@@ -56,8 +56,12 @@
let alloc = type_name::alloc_type_name(tcx, tp_ty);
ConstValue::Slice { data: alloc, start: 0, end: alloc.len() }
}
- sym::needs_drop => ConstValue::from_bool(tp_ty.needs_drop(tcx, param_env)),
+ sym::needs_drop => {
+ ensure_monomorphic_enough(tcx, tp_ty)?;
+ ConstValue::from_bool(tp_ty.needs_drop(tcx, param_env))
+ }
sym::min_align_of | sym::pref_align_of => {
+ // Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough.
let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(e)))?;
let n = match name {
sym::pref_align_of => layout.align.pref.bytes(),
@@ -71,6 +75,7 @@
ConstValue::from_u64(tcx.type_id_hash(tp_ty))
}
sym::variant_count => match tp_ty.kind() {
+ // Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough.
ty::Adt(ref adt, _) => ConstValue::from_machine_usize(adt.variants.len() as u64, &tcx),
ty::Projection(_)
| ty::Opaque(_, _)
diff --git a/compiler/rustc_mir/src/interpret/traits.rs b/compiler/rustc_mir/src/interpret/traits.rs
index 11f8d38..d0c04b5 100644
--- a/compiler/rustc_mir/src/interpret/traits.rs
+++ b/compiler/rustc_mir/src/interpret/traits.rs
@@ -158,6 +158,8 @@
let size = u64::try_from(self.force_bits(size, pointer_size)?).unwrap();
let align = vtable.read_ptr_sized(pointer_size * 2)?.check_init()?;
let align = u64::try_from(self.force_bits(align, pointer_size)?).unwrap();
+ let align = Align::from_bytes(align)
+ .map_err(|e| err_ub_format!("invalid vtable: alignment {}", e))?;
if size >= self.tcx.data_layout.obj_size_bound() {
throw_ub_format!(
@@ -165,6 +167,6 @@
size is bigger than largest supported object"
);
}
- Ok((Size::from_bytes(size), Align::from_bytes(align).unwrap()))
+ Ok((Size::from_bytes(size), align))
}
}
diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs
index ee6ff4d..8b05038 100644
--- a/compiler/rustc_parse/src/parser/attr.rs
+++ b/compiler/rustc_parse/src/parser/attr.rs
@@ -32,7 +32,6 @@
let mut just_parsed_doc_comment = false;
let start_pos = self.token_cursor.num_next_calls;
loop {
- debug!("parse_outer_attributes: self.token={:?}", self.token);
let attr = if self.check(&token::Pound) {
let inner_error_reason = if just_parsed_doc_comment {
"an inner attribute is not permitted following an outer doc comment"
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 72fdc78..b37caae 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -366,7 +366,7 @@
let mut snapshot = self.clone();
let path =
Path { segments: vec![], span: self.prev_token.span.shrink_to_lo(), tokens: None };
- let struct_expr = snapshot.parse_struct_expr(path, AttrVec::new(), false);
+ let struct_expr = snapshot.parse_struct_expr(None, path, AttrVec::new(), false);
let block_tail = self.parse_block_tail(lo, s, AttemptLocalParseRecovery::No);
return Some(match (struct_expr, block_tail) {
(Ok(expr), Err(mut err)) => {
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index a764cf6..c8789ab 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1108,9 +1108,6 @@
self.parse_closure_expr(attrs)
} else if self.check(&token::OpenDelim(token::Bracket)) {
self.parse_array_or_repeat_expr(attrs)
- } else if self.eat_lt() {
- let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
- Ok(self.mk_expr(lo.to(path.span), ExprKind::Path(Some(qself), path), attrs))
} else if self.check_path() {
self.parse_path_start_expr(attrs)
} else if self.check_keyword(kw::Move) || self.check_keyword(kw::Static) {
@@ -1262,12 +1259,20 @@
}
fn parse_path_start_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
- let path = self.parse_path(PathStyle::Expr)?;
+ let (qself, path) = if self.eat_lt() {
+ let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
+ (Some(qself), path)
+ } else {
+ (None, self.parse_path(PathStyle::Expr)?)
+ };
let lo = path.span;
// `!`, as an operator, is prefix, so we know this isn't that.
let (hi, kind) = if self.eat(&token::Not) {
// MACRO INVOCATION expression
+ if qself.is_some() {
+ self.struct_span_err(path.span, "macros cannot use qualified paths").emit();
+ }
let mac = MacCall {
path,
args: self.parse_mac_args()?,
@@ -1275,13 +1280,16 @@
};
(self.prev_token.span, ExprKind::MacCall(mac))
} else if self.check(&token::OpenDelim(token::Brace)) {
- if let Some(expr) = self.maybe_parse_struct_expr(&path, &attrs) {
+ if let Some(expr) = self.maybe_parse_struct_expr(qself.as_ref(), &path, &attrs) {
+ if qself.is_some() {
+ self.sess.gated_spans.gate(sym::more_qualified_paths, path.span);
+ }
return expr;
} else {
- (path.span, ExprKind::Path(None, path))
+ (path.span, ExprKind::Path(qself, path))
}
} else {
- (path.span, ExprKind::Path(None, path))
+ (path.span, ExprKind::Path(qself, path))
};
let expr = self.mk_expr(lo.to(hi), kind, attrs);
@@ -2247,6 +2255,7 @@
fn maybe_parse_struct_expr(
&mut self,
+ qself: Option<&ast::QSelf>,
path: &ast::Path,
attrs: &AttrVec,
) -> Option<PResult<'a, P<Expr>>> {
@@ -2255,7 +2264,7 @@
if let Err(err) = self.expect(&token::OpenDelim(token::Brace)) {
return Some(Err(err));
}
- let expr = self.parse_struct_expr(path.clone(), attrs.clone(), true);
+ let expr = self.parse_struct_expr(qself.cloned(), path.clone(), attrs.clone(), true);
if let (Ok(expr), false) = (&expr, struct_allowed) {
// This is a struct literal, but we don't can't accept them here.
self.error_struct_lit_not_allowed_here(path.span, expr.span);
@@ -2278,6 +2287,7 @@
/// Precondition: already parsed the '{'.
pub(super) fn parse_struct_expr(
&mut self,
+ qself: Option<ast::QSelf>,
pth: ast::Path,
attrs: AttrVec,
recover: bool,
@@ -2375,7 +2385,7 @@
let expr = if recover_async {
ExprKind::Err
} else {
- ExprKind::Struct(P(ast::StructExpr { path: pth, fields, rest: base }))
+ ExprKind::Struct(P(ast::StructExpr { qself, path: pth, fields, rest: base }))
};
Ok(self.mk_expr(span, expr, attrs))
}
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index 0abefbd..4181222 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -859,7 +859,8 @@
/// Parse a struct ("record") pattern (e.g. `Foo { ... }` or `Foo::Bar { ... }`).
fn parse_pat_struct(&mut self, qself: Option<QSelf>, path: Path) -> PResult<'a, PatKind> {
if qself.is_some() {
- return self.error_qpath_before_pat(&path, "{");
+ // Feature gate the use of qualified paths in patterns
+ self.sess.gated_spans.gate(sym::more_qualified_paths, path.span);
}
self.bump();
let (fields, etc) = self.parse_pat_fields().unwrap_or_else(|mut e| {
@@ -869,27 +870,17 @@
(vec![], true)
});
self.bump();
- Ok(PatKind::Struct(path, fields, etc))
+ Ok(PatKind::Struct(qself, path, fields, etc))
}
/// Parse tuple struct or tuple variant pattern (e.g. `Foo(...)` or `Foo::Bar(...)`).
fn parse_pat_tuple_struct(&mut self, qself: Option<QSelf>, path: Path) -> PResult<'a, PatKind> {
- if qself.is_some() {
- return self.error_qpath_before_pat(&path, "(");
- }
let (fields, _) =
self.parse_paren_comma_seq(|p| p.parse_pat_allow_top_alt(None, RecoverComma::No))?;
- Ok(PatKind::TupleStruct(path, fields))
- }
-
- /// Error when there's a qualified path, e.g. `<Foo as Bar>::Baz`
- /// as the path of e.g., a tuple or record struct pattern.
- fn error_qpath_before_pat(&mut self, path: &Path, token: &str) -> PResult<'a, PatKind> {
- let msg = &format!("unexpected `{}` after qualified path", token);
- let mut err = self.struct_span_err(self.token.span, msg);
- err.span_label(self.token.span, msg);
- err.span_label(path.span, "the qualified path");
- Err(err)
+ if qself.is_some() {
+ self.sess.gated_spans.gate(sym::more_qualified_paths, path.span);
+ }
+ Ok(PatKind::TupleStruct(qself, path, fields))
}
/// Parses the fields of a struct-like pattern.
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 4f0dcfe..9ef3f61 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -117,7 +117,7 @@
}
let expr = if this.eat(&token::OpenDelim(token::Brace)) {
- this.parse_struct_expr(path, AttrVec::new(), true)?
+ this.parse_struct_expr(None, path, AttrVec::new(), true)?
} else {
let hi = this.prev_token.span;
this.mk_expr(lo.to(hi), ExprKind::Path(None, path), AttrVec::new())
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 408d9b2..a21d819 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -1613,10 +1613,10 @@
self.r.record_partial_res(pat.id, PartialRes::new(res));
self.r.record_pat_span(pat.id, pat.span);
}
- PatKind::TupleStruct(ref path, ref sub_patterns) => {
+ PatKind::TupleStruct(ref qself, ref path, ref sub_patterns) => {
self.smart_resolve_path(
pat.id,
- None,
+ qself.as_ref(),
path,
PathSource::TupleStruct(
pat.span,
@@ -1627,8 +1627,8 @@
PatKind::Path(ref qself, ref path) => {
self.smart_resolve_path(pat.id, qself.as_ref(), path, PathSource::Pat);
}
- PatKind::Struct(ref path, ..) => {
- self.smart_resolve_path(pat.id, None, path, PathSource::Struct);
+ PatKind::Struct(ref qself, ref path, ..) => {
+ self.smart_resolve_path(pat.id, qself.as_ref(), path, PathSource::Struct);
}
PatKind::Or(ref ps) => {
// Add a new set of bindings to the stack. `Or` here records that when a
@@ -2288,7 +2288,7 @@
}
ExprKind::Struct(ref se) => {
- self.smart_resolve_path(expr.id, None, &se.path, PathSource::Struct);
+ self.smart_resolve_path(expr.id, se.qself.as_ref(), &se.path, PathSource::Struct);
visit::walk_expr(self, expr);
}
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index fd9b897..6d5531d 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -1198,7 +1198,7 @@
session: &'a Session,
krate: &Crate,
crate_name: &str,
- metadata_loader: &'a MetadataLoaderDyn,
+ metadata_loader: Box<MetadataLoaderDyn>,
arenas: &'a ResolverArenas<'a>,
) -> Resolver<'a> {
let root_local_def_id = LocalDefId { local_def_index: CRATE_DEF_INDEX };
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 5752258..2b547f8 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -2417,6 +2417,7 @@
/// we have an opt-in scheme here, so one is hopefully forced to think about
/// how the hash should be calculated when adding a new command-line argument.
crate mod dep_tracking {
+ use super::LdImpl;
use super::{
CFGuard, CrateType, DebugInfo, ErrorOutputType, InstrumentCoverage, LinkerPluginLto,
LtoCli, OptLevel, OutputTypes, Passes, SourceFileHashAlgorithm, SwitchWithOptPath,
@@ -2497,6 +2498,7 @@
SymbolManglingVersion,
SourceFileHashAlgorithm,
TrimmedDefPaths,
+ Option<LdImpl>,
);
impl<T1, T2> DepTrackingHash for (T1, T2)
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 58a53b3..1946bfd 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -370,6 +370,7 @@
pub const parse_wasi_exec_model: &str = "either `command` or `reactor`";
pub const parse_split_debuginfo: &str =
"one of supported split-debuginfo modes (`off`, `packed`, or `unpacked`)";
+ pub const parse_gcc_ld: &str = "one of: no value, `lld`";
}
mod parse {
@@ -864,6 +865,15 @@
}
true
}
+
+ crate fn parse_gcc_ld(slot: &mut Option<LdImpl>, v: Option<&str>) -> bool {
+ match v {
+ None => *slot = None,
+ Some("lld") => *slot = Some(LdImpl::Lld),
+ _ => return false,
+ }
+ true
+ }
}
options! {
@@ -1067,6 +1077,7 @@
"set the optimization fuel quota for a crate"),
function_sections: Option<bool> = (None, parse_opt_bool, [TRACKED],
"whether each function should go in its own section"),
+ gcc_ld: Option<LdImpl> = (None, parse_gcc_ld, [TRACKED], "implementation of ld used by cc"),
graphviz_dark_mode: bool = (false, parse_bool, [UNTRACKED],
"use dark-themed colors in graphviz output (default: no)"),
graphviz_font: String = ("Courier, monospace".to_string(), parse_string, [UNTRACKED],
@@ -1321,3 +1332,8 @@
Command,
Reactor,
}
+
+#[derive(Clone, Copy, Hash)]
+pub enum LdImpl {
+ Lld,
+}
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 0dadd41..1d45cd1 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -407,7 +407,7 @@
}
fn span_to_string(&self, sp: Span, prefer_local: bool) -> String {
- if self.files.borrow().source_files.is_empty() && sp.is_dummy() {
+ if self.files.borrow().source_files.is_empty() || sp.is_dummy() {
return "no-location".to_string();
}
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 31b425f..fb37c5e 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -756,6 +756,7 @@
modifiers,
module,
module_path,
+ more_qualified_paths,
more_struct_aliases,
movbe_target_feature,
move_ref_pattern,
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index eb91af8..13b4244 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -1209,7 +1209,7 @@
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "from_for_ptrs", since = "1.6.0")]
impl<T> From<T> for Box<T> {
- /// Converts a generic type `T` into a `Box<T>`
+ /// Converts a `T` into a `Box<T>`
///
/// The conversion allocates on the heap and moves `t`
/// from the stack into it.
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 2da3d6a..80d0890 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -1,6 +1,5 @@
//! impl char {}
-use crate::intrinsics::likely;
use crate::slice;
use crate::str::from_utf8_unchecked_mut;
use crate::unicode::printable::is_printable;
@@ -332,21 +331,16 @@
#[inline]
pub fn to_digit(self, radix: u32) -> Option<u32> {
assert!(radix <= 36, "to_digit: radix is too high (maximum 36)");
- // the code is split up here to improve execution speed for cases where
- // the `radix` is constant and 10 or smaller
- let val = if likely(radix <= 10) {
- // If not a digit, a number greater than radix will be created.
- (self as u32).wrapping_sub('0' as u32)
- } else {
- match self {
- '0'..='9' => self as u32 - '0' as u32,
- 'a'..='z' => self as u32 - 'a' as u32 + 10,
- 'A'..='Z' => self as u32 - 'A' as u32 + 10,
- _ => return None,
+ // If not a digit, a number greater than radix will be created.
+ let mut digit = (self as u32).wrapping_sub('0' as u32);
+ if radix > 10 {
+ if digit < 10 {
+ return Some(digit);
}
- };
-
- if val < radix { Some(val) } else { None }
+ // Force the 6th bit to be set to ensure ascii is lower case.
+ digit = (self as u32 | 0b10_0000).wrapping_sub('a' as u32).saturating_add(10);
+ }
+ (digit < radix).then_some(digit)
}
/// Returns an iterator that yields the hexadecimal Unicode escape of a
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index d4e4c5b..949ef27 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -65,6 +65,7 @@
#![feature(allow_internal_unstable)]
#![feature(arbitrary_self_types)]
#![feature(asm)]
+#![feature(bool_to_option)]
#![feature(cfg_target_has_atomic)]
#![feature(const_heap)]
#![feature(const_alloc_layout)]
@@ -165,6 +166,7 @@
#![feature(no_niche)] // rust-lang/rust#68303
#![feature(no_coverage)] // rust-lang/rust#84605
#![feature(int_error_matching)]
+#![cfg_attr(bootstrap, feature(target_feature_11))]
#![deny(unsafe_op_in_unsafe_fn)]
#![deny(or_patterns_back_compat)]
diff --git a/library/core/tests/char.rs b/library/core/tests/char.rs
index c16f540..51eca1e 100644
--- a/library/core/tests/char.rs
+++ b/library/core/tests/char.rs
@@ -67,10 +67,20 @@
assert_eq!('A'.to_digit(16), Some(10));
assert_eq!('b'.to_digit(16), Some(11));
assert_eq!('B'.to_digit(16), Some(11));
+ assert_eq!('A'.to_digit(36), Some(10));
assert_eq!('z'.to_digit(36), Some(35));
assert_eq!('Z'.to_digit(36), Some(35));
- assert_eq!(' '.to_digit(10), None);
+ assert_eq!('['.to_digit(36), None);
+ assert_eq!('`'.to_digit(36), None);
+ assert_eq!('{'.to_digit(36), None);
assert_eq!('$'.to_digit(36), None);
+ assert_eq!('@'.to_digit(16), None);
+ assert_eq!('G'.to_digit(16), None);
+ assert_eq!('g'.to_digit(16), None);
+ assert_eq!(' '.to_digit(10), None);
+ assert_eq!('/'.to_digit(10), None);
+ assert_eq!(':'.to_digit(10), None);
+ assert_eq!(':'.to_digit(11), None);
}
#[test]
diff --git a/library/stdarch b/library/stdarch
index 37d6e18..1e05dff 160000
--- a/library/stdarch
+++ b/library/stdarch
@@ -1 +1 @@
-Subproject commit 37d6e1886369ea0176356286dc7fbd42ee5aa79c
+Subproject commit 1e05dffbeeb80ba61bf59cc63b222d538d7825ed
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index ed311e2..112a6ea 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -1108,6 +1108,13 @@
let src_exe = exe("lld", target_compiler.host);
let dst_exe = exe("rust-lld", target_compiler.host);
builder.copy(&lld_install.join("bin").join(&src_exe), &libdir_bin.join(&dst_exe));
+ // for `-Z gcc-ld=lld`
+ let gcc_ld_dir = libdir_bin.join("gcc-ld");
+ t!(fs::create_dir(&gcc_ld_dir));
+ builder.copy(
+ &lld_install.join("bin").join(&src_exe),
+ &gcc_ld_dir.join(exe("ld", target_compiler.host)),
+ );
}
// Similarly, copy `llvm-dwp` into libdir for Split DWARF. Only copy it when the LLVM
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index aee3c83..71ed0af 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -402,6 +402,10 @@
if builder.config.lld_enabled {
let exe = exe("rust-lld", compiler.host);
builder.copy(&src_dir.join(&exe), &dst_dir.join(&exe));
+ // for `-Z gcc-ld=lld`
+ let gcc_lld_dir = dst_dir.join("gcc-ld");
+ t!(fs::create_dir(&gcc_lld_dir));
+ builder.copy(&src_dir.join(&exe), &gcc_lld_dir.join(&exe));
}
// Copy over llvm-dwp if it's there
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 430510b..fe4666e 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1503,6 +1503,8 @@
cmd.env("BOOTSTRAP_CARGO", &builder.initial_cargo);
+ cmd.arg("--channel").arg(&builder.config.channel);
+
builder.ci_env.force_coloring_in_ci(&mut cmd);
builder.info(&format!(
diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh
index c2ff62e..3a47076 100755
--- a/src/ci/docker/run.sh
+++ b/src/ci/docker/run.sh
@@ -235,6 +235,7 @@
--env TOOLSTATE_REPO_ACCESS_TOKEN \
--env TOOLSTATE_REPO \
--env TOOLSTATE_PUBLISH \
+ --env RUST_CI_OVERRIDE_RELEASE_CHANNEL \
--env CI_JOB_NAME="${CI_JOB_NAME-$IMAGE}" \
--init \
--rm \
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index 343091c..e704071 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -407,6 +407,17 @@
- name: x86_64-gnu
<<: *job-linux-xl
+ # This job ensures commits landing on nightly still pass the full
+ # test suite on the stable channel. There are some UI tests that
+ # depend on the channel being built (for example if they include the
+ # channel name on the output), and this builder prevents landing
+ # changes that would result in broken builds after a promotion.
+ - name: x86_64-gnu-stable
+ env:
+ IMAGE: x86_64-gnu
+ RUST_CI_OVERRIDE_RELEASE_CHANNEL: stable
+ <<: *job-linux-xl
+
- name: x86_64-gnu-aux
<<: *job-linux-xl
diff --git a/src/ci/run.sh b/src/ci/run.sh
index 35f80a9..c5e225c 100755
--- a/src/ci/run.sh
+++ b/src/ci/run.sh
@@ -65,7 +65,11 @@
# Always set the release channel for bootstrap; this is normally not important (i.e., only dist
# builds would seem to matter) but in practice bootstrap wants to know whether we're targeting
# master, beta, or stable with a build to determine whether to run some checks (notably toolstate).
-export RUST_RELEASE_CHANNEL="$(cat "${ci_dir}/channel")"
+if [[ -z "${RUST_CI_OVERRIDE_RELEASE_CHANNEL+x}" ]]; then
+ export RUST_RELEASE_CHANNEL="$(cat "${ci_dir}/channel")"
+else
+ export RUST_RELEASE_CHANNEL="${RUST_CI_OVERRIDE_RELEASE_CHANNEL}"
+fi
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --release-channel=$RUST_RELEASE_CHANNEL"
if [ "$DEPLOY$DEPLOY_ALT" = "1" ]; then
diff --git a/src/doc/unstable-book/src/language-features/more-qualified-paths.md b/src/doc/unstable-book/src/language-features/more-qualified-paths.md
new file mode 100644
index 0000000..857af57
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/more-qualified-paths.md
@@ -0,0 +1,29 @@
+# `more_qualified_paths`
+
+The `more_qualified_paths` feature can be used in order to enable the
+use of qualified paths in patterns.
+
+## Example
+
+```rust
+#![feature(more_qualified_paths)]
+
+fn main() {
+ // destructure through a qualified path
+ let <Foo as A>::Assoc { br } = StructStruct { br: 2 };
+}
+
+struct StructStruct {
+ br: i8,
+}
+
+struct Foo;
+
+trait A {
+ type Assoc;
+}
+
+impl A for Foo {
+ type Assoc = StructStruct;
+}
+```
diff --git "a/src/test/mir-opt/generator_storage_dead_unwind.main-\173closure\0430\175.StateTransform.before.mir" "b/src/test/mir-opt/generator_storage_dead_unwind.main-\173closure\0430\175.StateTransform.before.mir"
index 42b95b5..296a459 100644
--- "a/src/test/mir-opt/generator_storage_dead_unwind.main-\173closure\0430\175.StateTransform.before.mir"
+++ "b/src/test/mir-opt/generator_storage_dead_unwind.main-\173closure\0430\175.StateTransform.before.mir"
@@ -85,13 +85,13 @@
bb8 (cleanup): {
StorageDead(_10); // scope 2 at $DIR/generator-storage-dead-unwind.rs:27:15: 27:16
StorageDead(_9); // scope 2 at $DIR/generator-storage-dead-unwind.rs:27:16: 27:17
- goto -> bb10; // scope 2 at $DIR/generator-storage-dead-unwind.rs:1:1: 1:1
+ goto -> bb10; // scope 2 at no-location
}
bb9 (cleanup): {
StorageDead(_8); // scope 2 at $DIR/generator-storage-dead-unwind.rs:26:15: 26:16
StorageDead(_7); // scope 2 at $DIR/generator-storage-dead-unwind.rs:26:16: 26:17
- goto -> bb10; // scope 2 at $DIR/generator-storage-dead-unwind.rs:1:1: 1:1
+ goto -> bb10; // scope 2 at no-location
}
bb10 (cleanup): {
diff --git a/src/test/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir b/src/test/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir
index 99c7ac8..db88f77 100644
--- a/src/test/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir
+++ b/src/test/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir
@@ -43,7 +43,7 @@
_6 = const 1_i32; // scope 0 at $DIR/loop_test.rs:14:17: 14:18
FakeRead(ForLet(None), _6); // scope 0 at $DIR/loop_test.rs:14:13: 14:14
StorageDead(_6); // scope 0 at $DIR/loop_test.rs:16:5: 16:6
- goto -> bb3; // scope 0 at $DIR/loop_test.rs:1:1: 1:1
+ goto -> bb3; // scope 0 at no-location
}
bb5 (cleanup): {
diff --git a/src/test/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/src/test/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff
index 3395cbf..feb2503 100644
--- a/src/test/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff
+++ b/src/test/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff
@@ -94,8 +94,8 @@
_0 = const 3_i32; // scope 0 at $DIR/match-arm-scopes.rs:15:59: 15:60
StorageDead(_10); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
StorageDead(_9); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
-- goto -> bb23; // scope 0 at $DIR/match-arm-scopes.rs:1:1: 1:1
-+ goto -> bb20; // scope 0 at $DIR/match-arm-scopes.rs:1:1: 1:1
+- goto -> bb23; // scope 0 at no-location
++ goto -> bb20; // scope 0 at no-location
}
- bb10: {
@@ -150,8 +150,8 @@
_0 = const 3_i32; // scope 0 at $DIR/match-arm-scopes.rs:15:59: 15:60
StorageDead(_13); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
StorageDead(_12); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
-- goto -> bb23; // scope 0 at $DIR/match-arm-scopes.rs:1:1: 1:1
-+ goto -> bb20; // scope 0 at $DIR/match-arm-scopes.rs:1:1: 1:1
+- goto -> bb23; // scope 0 at no-location
++ goto -> bb20; // scope 0 at no-location
}
- bb15: {
diff --git a/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir b/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir
index b91aae0..bf9c2d1 100644
--- a/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir
+++ b/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir
@@ -40,7 +40,7 @@
bb4: {
StorageDead(_4); // scope 0 at $DIR/while-storage.rs:13:9: 13:10
- goto -> bb6; // scope 0 at $DIR/while-storage.rs:1:1: 1:1
+ goto -> bb6; // scope 0 at no-location
}
bb5: {
diff --git a/src/test/run-make/issue-71519/Makefile b/src/test/run-make/issue-71519/Makefile
new file mode 100644
index 0000000..636665e
--- /dev/null
+++ b/src/test/run-make/issue-71519/Makefile
@@ -0,0 +1,6 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# needs-rust-lld
+all:
+ RUSTC_LOG=rustc_codegen_ssa::back::link=info $(RUSTC) -Z gcc-ld=lld -C link-args=-Wl,-v main.rs 2> $(TMPDIR)/output.txt
+ $(CGREP) -e "^LLD [0-9]+\.[0-9]+\.[0-9]+" < $(TMPDIR)/output.txt
diff --git a/src/test/run-make/issue-71519/main.rs b/src/test/run-make/issue-71519/main.rs
new file mode 100644
index 0000000..f8d09e8
--- /dev/null
+++ b/src/test/run-make/issue-71519/main.rs
@@ -0,0 +1,4 @@
+// test linking using cc with rust-lld injected into search path as ld
+// see rust-lang/rust#71519 for more info
+
+fn main() {}
diff --git a/src/test/rustdoc-ui/wasm-safe.rs b/src/test/rustdoc-ui/wasm-safe.rs
index 80b15ac..ba97134 100644
--- a/src/test/rustdoc-ui/wasm-safe.rs
+++ b/src/test/rustdoc-ui/wasm-safe.rs
@@ -1,7 +1,5 @@
// check-pass
-#![feature(wasm_target_feature)]
-
#[cfg(any(target_arch = "wasm32", doc))]
#[target_feature(enable = "simd128")]
pub fn foo() {}
diff --git a/src/test/rustdoc/intra-doc/field.rs b/src/test/rustdoc/intra-doc/field.rs
index c67c40a..0011434 100644
--- a/src/test/rustdoc/intra-doc/field.rs
+++ b/src/test/rustdoc/intra-doc/field.rs
@@ -1,4 +1,4 @@
-// @has field/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/ops/range/struct.Range.html#structfield.start"]' 'start'
-// @has field/index.html '//a[@href="https://doc.rust-lang.org/nightly/std/io/error/enum.ErrorKind.html#variant.NotFound"]' 'not_found'
+// @has field/index.html '//a[@href="{{channel}}/core/ops/range/struct.Range.html#structfield.start"]' 'start'
+// @has field/index.html '//a[@href="{{channel}}/std/io/error/enum.ErrorKind.html#variant.NotFound"]' 'not_found'
//! [start][std::ops::Range::start]
//! [not_found][std::io::ErrorKind::NotFound]
diff --git a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs
index ac2d29c..091c834 100644
--- a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs
+++ b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs
@@ -19,45 +19,35 @@
#![feature(rustc_private)]
+extern crate rustc_ast;
extern crate rustc_ast_pretty;
extern crate rustc_data_structures;
-extern crate rustc_ast;
extern crate rustc_parse;
extern crate rustc_session;
extern crate rustc_span;
+use rustc_ast::mut_visit::{self, visit_clobber, MutVisitor};
+use rustc_ast::ptr::P;
+use rustc_ast::*;
use rustc_ast_pretty::pprust;
use rustc_data_structures::thin_vec::ThinVec;
use rustc_parse::new_parser_from_source_str;
use rustc_session::parse::ParseSess;
-use rustc_span::source_map::{Spanned, DUMMY_SP, FileName};
use rustc_span::source_map::FilePathMapping;
+use rustc_span::source_map::{FileName, Spanned, DUMMY_SP};
use rustc_span::symbol::Ident;
-use rustc_ast::*;
-use rustc_ast::mut_visit::{self, MutVisitor, visit_clobber};
-use rustc_ast::ptr::P;
fn parse_expr(ps: &ParseSess, src: &str) -> Option<P<Expr>> {
let src_as_string = src.to_string();
- let mut p = new_parser_from_source_str(
- ps,
- FileName::Custom(src_as_string.clone()),
- src_as_string,
- );
+ let mut p =
+ new_parser_from_source_str(ps, FileName::Custom(src_as_string.clone()), src_as_string);
p.parse_expr().map_err(|mut e| e.cancel()).ok()
}
-
// Helper functions for building exprs
fn expr(kind: ExprKind) -> P<Expr> {
- P(Expr {
- id: DUMMY_NODE_ID,
- kind,
- span: DUMMY_SP,
- attrs: ThinVec::new(),
- tokens: None
- })
+ P(Expr { id: DUMMY_NODE_ID, kind, span: DUMMY_SP, attrs: ThinVec::new(), tokens: None })
}
fn make_x() -> P<Expr> {
@@ -83,11 +73,13 @@
1 => iter_exprs(depth - 1, &mut |e| g(ExprKind::Call(e, vec![]))),
2 => {
let seg = PathSegment::from_ident(Ident::from_str("x"));
- iter_exprs(depth - 1, &mut |e| g(ExprKind::MethodCall(
- seg.clone(), vec![e, make_x()], DUMMY_SP)));
- iter_exprs(depth - 1, &mut |e| g(ExprKind::MethodCall(
- seg.clone(), vec![make_x(), e], DUMMY_SP)));
- },
+ iter_exprs(depth - 1, &mut |e| {
+ g(ExprKind::MethodCall(seg.clone(), vec![e, make_x()], DUMMY_SP))
+ });
+ iter_exprs(depth - 1, &mut |e| {
+ g(ExprKind::MethodCall(seg.clone(), vec![make_x(), e], DUMMY_SP))
+ });
+ }
3..=8 => {
let op = Spanned {
span: DUMMY_SP,
@@ -99,14 +91,14 @@
7 => BinOpKind::Or,
8 => BinOpKind::Lt,
_ => unreachable!(),
- }
+ },
};
iter_exprs(depth - 1, &mut |e| g(ExprKind::Binary(op, e, make_x())));
iter_exprs(depth - 1, &mut |e| g(ExprKind::Binary(op, make_x(), e)));
- },
+ }
9 => {
iter_exprs(depth - 1, &mut |e| g(ExprKind::Unary(UnOp::Deref, e)));
- },
+ }
10 => {
let block = P(Block {
stmts: Vec::new(),
@@ -116,67 +108,66 @@
tokens: None,
});
iter_exprs(depth - 1, &mut |e| g(ExprKind::If(e, block.clone(), None)));
- },
+ }
11 => {
- let decl = P(FnDecl {
- inputs: vec![],
- output: FnRetTy::Default(DUMMY_SP),
+ let decl = P(FnDecl { inputs: vec![], output: FnRetTy::Default(DUMMY_SP) });
+ iter_exprs(depth - 1, &mut |e| {
+ g(ExprKind::Closure(
+ CaptureBy::Value,
+ Async::No,
+ Movability::Movable,
+ decl.clone(),
+ e,
+ DUMMY_SP,
+ ))
});
- iter_exprs(depth - 1, &mut |e| g(
- ExprKind::Closure(CaptureBy::Value,
- Async::No,
- Movability::Movable,
- decl.clone(),
- e,
- DUMMY_SP)));
- },
+ }
12 => {
iter_exprs(depth - 1, &mut |e| g(ExprKind::Assign(e, make_x(), DUMMY_SP)));
iter_exprs(depth - 1, &mut |e| g(ExprKind::Assign(make_x(), e, DUMMY_SP)));
- },
+ }
13 => {
iter_exprs(depth - 1, &mut |e| g(ExprKind::Field(e, Ident::from_str("f"))));
- },
+ }
14 => {
- iter_exprs(depth - 1, &mut |e| g(ExprKind::Range(
- Some(e), Some(make_x()), RangeLimits::HalfOpen)));
- iter_exprs(depth - 1, &mut |e| g(ExprKind::Range(
- Some(make_x()), Some(e), RangeLimits::HalfOpen)));
- },
+ iter_exprs(depth - 1, &mut |e| {
+ g(ExprKind::Range(Some(e), Some(make_x()), RangeLimits::HalfOpen))
+ });
+ iter_exprs(depth - 1, &mut |e| {
+ g(ExprKind::Range(Some(make_x()), Some(e), RangeLimits::HalfOpen))
+ });
+ }
15 => {
- iter_exprs(
- depth - 1,
- &mut |e| g(ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, e)),
- );
- },
+ iter_exprs(depth - 1, &mut |e| {
+ g(ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, e))
+ });
+ }
16 => {
g(ExprKind::Ret(None));
iter_exprs(depth - 1, &mut |e| g(ExprKind::Ret(Some(e))));
- },
+ }
17 => {
let path = Path::from_ident(Ident::from_str("S"));
g(ExprKind::Struct(P(StructExpr {
- path, fields: vec![], rest: StructRest::Base(make_x())
+ qself: None,
+ path,
+ fields: vec![],
+ rest: StructRest::Base(make_x()),
})));
- },
+ }
18 => {
iter_exprs(depth - 1, &mut |e| g(ExprKind::Try(e)));
- },
+ }
19 => {
- let pat = P(Pat {
- id: DUMMY_NODE_ID,
- kind: PatKind::Wild,
- span: DUMMY_SP,
- tokens: None,
- });
+ let pat =
+ P(Pat { id: DUMMY_NODE_ID, kind: PatKind::Wild, span: DUMMY_SP, tokens: None });
iter_exprs(depth - 1, &mut |e| g(ExprKind::Let(pat.clone(), e)))
- },
+ }
_ => panic!("bad counter value in iter_exprs"),
}
}
}
-
// Folders for manipulating the placement of `Paren` nodes. See below for why this is needed.
/// `MutVisitor` that removes all `ExprKind::Paren` nodes.
@@ -192,7 +183,6 @@
}
}
-
/// `MutVisitor` that inserts `ExprKind::Paren` nodes around every `Expr`.
struct AddParens;
@@ -205,7 +195,7 @@
kind: ExprKind::Paren(e),
span: DUMMY_SP,
attrs: ThinVec::new(),
- tokens: None
+ tokens: None,
})
});
}
@@ -238,9 +228,12 @@
RemoveParens.visit_expr(&mut parsed);
AddParens.visit_expr(&mut parsed);
let text2 = pprust::expr_to_string(&parsed);
- assert!(text1 == text2,
- "exprs are not equal:\n e = {:?}\n parsed = {:?}",
- text1, text2);
+ assert!(
+ text1 == text2,
+ "exprs are not equal:\n e = {:?}\n parsed = {:?}",
+ text1,
+ text2
+ );
}
});
}
diff --git a/src/test/ui-fulldeps/session-derive-errors.rs b/src/test/ui-fulldeps/session-derive-errors.rs
index 7967b32..140aaad 100644
--- a/src/test/ui-fulldeps/session-derive-errors.rs
+++ b/src/test/ui-fulldeps/session-derive-errors.rs
@@ -1,6 +1,12 @@
// check-fail
// Tests error conditions for specifying diagnostics using #[derive(SessionDiagnostic)]
+// The proc_macro2 crate handles spans differently when on beta/stable release rather than nightly,
+// changing the output of this test. Since SessionDiagnostic is strictly internal to the compiler
+// the test is just ignored on stable and beta:
+// ignore-beta
+// ignore-stable
+
#![feature(rustc_private)]
#![crate_type = "lib"]
diff --git a/src/test/ui-fulldeps/session-derive-errors.stderr b/src/test/ui-fulldeps/session-derive-errors.stderr
index c6c3765..2f1debe 100644
--- a/src/test/ui-fulldeps/session-derive-errors.stderr
+++ b/src/test/ui-fulldeps/session-derive-errors.stderr
@@ -1,5 +1,5 @@
error: `#[derive(SessionDiagnostic)]` can only be used on structs
- --> $DIR/session-derive-errors.rs:28:1
+ --> $DIR/session-derive-errors.rs:34:1
|
LL | / #[error = "E0123"]
LL | |
@@ -10,31 +10,31 @@
| |_^
error: `#[label = ...]` is not a valid SessionDiagnostic struct attribute
- --> $DIR/session-derive-errors.rs:37:1
+ --> $DIR/session-derive-errors.rs:43:1
|
LL | #[label = "This is in the wrong place"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: `#[suggestion = ...]` is not a valid SessionDiagnostic field attribute
- --> $DIR/session-derive-errors.rs:44:5
+ --> $DIR/session-derive-errors.rs:50:5
|
LL | #[suggestion = "this is the wrong kind of attribute"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: `error` specified multiple times
- --> $DIR/session-derive-errors.rs:52:11
+ --> $DIR/session-derive-errors.rs:58:11
|
LL | #[error = "E0456"]
| ^^^^^^^
error: `lint` specified when `error` was already specified
- --> $DIR/session-derive-errors.rs:58:10
+ --> $DIR/session-derive-errors.rs:64:10
|
LL | #[lint = "some_useful_lint"]
| ^^^^^^^^^^^^^^^^^^
error: `code` not specified
- --> $DIR/session-derive-errors.rs:67:1
+ --> $DIR/session-derive-errors.rs:73:1
|
LL | struct ErrorCodeNotProvided {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -42,19 +42,19 @@
= help: use the [code = "..."] attribute to set this diagnostic's error code
error: the `#[message = "..."]` attribute can only be applied to fields of type Span
- --> $DIR/session-derive-errors.rs:95:5
+ --> $DIR/session-derive-errors.rs:101:5
|
LL | #[message = "this message is applied to a String field"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: `name` doesn't refer to a field on this type
- --> $DIR/session-derive-errors.rs:102:1
+ --> $DIR/session-derive-errors.rs:108:1
|
LL | #[message = "This error has a field, and references {name}"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: invalid format string: expected `'}'` but string was terminated
- --> $DIR/session-derive-errors.rs:110:1
+ --> $DIR/session-derive-errors.rs:116:1
|
LL | #[error = "E0123"]
| - because of this opening brace
@@ -65,7 +65,7 @@
= note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
error: invalid format string: unmatched `}` found
- --> $DIR/session-derive-errors.rs:119:1
+ --> $DIR/session-derive-errors.rs:125:1
|
LL | #[message = "This is missing an opening brace: name}"]
| ^ unmatched `}` in format string
@@ -74,25 +74,25 @@
= note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
error: The `#[label = ...]` attribute can only be applied to fields of type Span
- --> $DIR/session-derive-errors.rs:138:5
+ --> $DIR/session-derive-errors.rs:144:5
|
LL | #[label = "See here"]
| ^^^^^^^^^^^^^^^^^^^^^
error: `nonsense` is not a valid key for `#[suggestion(...)]`
- --> $DIR/session-derive-errors.rs:163:18
+ --> $DIR/session-derive-errors.rs:169:18
|
LL | #[suggestion(nonsense = "This is nonsense")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: `msg` is not a valid key for `#[suggestion(...)]`
- --> $DIR/session-derive-errors.rs:171:18
+ --> $DIR/session-derive-errors.rs:177:18
|
LL | #[suggestion(msg = "This is a suggestion")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing suggestion message
- --> $DIR/session-derive-errors.rs:179:7
+ --> $DIR/session-derive-errors.rs:185:7
|
LL | #[suggestion(code = "This is suggested code")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -100,7 +100,7 @@
= help: provide a suggestion message using #[suggestion(message = "...")]
error: wrong field type for suggestion
- --> $DIR/session-derive-errors.rs:194:5
+ --> $DIR/session-derive-errors.rs:200:5
|
LL | / #[suggestion(message = "This is a message", code = "This is suggested code")]
LL | |
@@ -110,7 +110,7 @@
= help: #[suggestion(...)] should be applied to fields of type Span or (Span, Applicability)
error: type of field annotated with `#[suggestion(...)]` contains more than one Span
- --> $DIR/session-derive-errors.rs:209:5
+ --> $DIR/session-derive-errors.rs:215:5
|
LL | / #[suggestion(message = "This is a message", code = "This is suggested code")]
LL | |
@@ -118,7 +118,7 @@
| |___________________________________________^
error: type of field annotated with `#[suggestion(...)]` contains more than one Applicability
- --> $DIR/session-derive-errors.rs:217:5
+ --> $DIR/session-derive-errors.rs:223:5
|
LL | / #[suggestion(message = "This is a message", code = "This is suggested code")]
LL | |
@@ -126,7 +126,7 @@
| |____________________________________________________^
error: invalid annotation list `#[label(...)]`
- --> $DIR/session-derive-errors.rs:225:7
+ --> $DIR/session-derive-errors.rs:231:7
|
LL | #[label("wrong kind of annotation for label")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/associated-types/associated-type-destructuring-assignment.rs b/src/test/ui/associated-types/associated-type-destructuring-assignment.rs
new file mode 100644
index 0000000..fea7c7a
--- /dev/null
+++ b/src/test/ui/associated-types/associated-type-destructuring-assignment.rs
@@ -0,0 +1,11 @@
+// check-pass
+
+#![feature(destructuring_assignment)]
+#![feature(more_qualified_paths)]
+
+enum E { V() }
+
+fn main() {
+ <E>::V() = E::V(); // OK, destructuring assignment
+ <E>::V {} = E::V(); // OK, destructuring assignment
+}
diff --git a/src/test/ui/associated-types/associated-type-macro.rs b/src/test/ui/associated-types/associated-type-macro.rs
new file mode 100644
index 0000000..22b5bca
--- /dev/null
+++ b/src/test/ui/associated-types/associated-type-macro.rs
@@ -0,0 +1,4 @@
+fn main() {
+ #[cfg(FALSE)]
+ <() as module>::mac!(); //~ ERROR macros cannot use qualified paths
+}
diff --git a/src/test/ui/associated-types/associated-type-macro.stderr b/src/test/ui/associated-types/associated-type-macro.stderr
new file mode 100644
index 0000000..6a4cf99
--- /dev/null
+++ b/src/test/ui/associated-types/associated-type-macro.stderr
@@ -0,0 +1,8 @@
+error: macros cannot use qualified paths
+ --> $DIR/associated-type-macro.rs:3:5
+ |
+LL | <() as module>::mac!();
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/associated-types/associated-type-struct-construction.rs b/src/test/ui/associated-types/associated-type-struct-construction.rs
new file mode 100644
index 0000000..f8f8048
--- /dev/null
+++ b/src/test/ui/associated-types/associated-type-struct-construction.rs
@@ -0,0 +1,24 @@
+// Make sure that users can construct structs through associated types
+// in both expressions and patterns
+
+#![feature(more_qualified_paths)]
+
+// check-pass
+fn main() {
+ let <Foo as A>::Assoc { br } = <Foo as A>::Assoc { br: 2 };
+ assert!(br == 2);
+}
+
+struct StructStruct {
+ br: i8,
+}
+
+struct Foo;
+
+trait A {
+ type Assoc;
+}
+
+impl A for Foo {
+ type Assoc = StructStruct;
+}
diff --git a/src/test/ui/associated-types/associated-type-tuple-struct-construction.rs b/src/test/ui/associated-types/associated-type-tuple-struct-construction.rs
new file mode 100644
index 0000000..d5809ec
--- /dev/null
+++ b/src/test/ui/associated-types/associated-type-tuple-struct-construction.rs
@@ -0,0 +1,24 @@
+// Users cannot yet construct structs through associated types
+// in both expressions and patterns
+
+#![feature(more_qualified_paths)]
+
+fn main() {
+ let <Foo as A>::Assoc(n) = <Foo as A>::Assoc(2);
+ //~^ ERROR expected method or associated constant, found associated type
+ //~| ERROR expected method or associated constant, found associated type
+ assert!(n == 2);
+}
+
+struct TupleStruct(i8);
+
+struct Foo;
+
+
+trait A {
+ type Assoc;
+}
+
+impl A for Foo {
+ type Assoc = TupleStruct;
+}
diff --git a/src/test/ui/associated-types/associated-type-tuple-struct-construction.stderr b/src/test/ui/associated-types/associated-type-tuple-struct-construction.stderr
new file mode 100644
index 0000000..bca7dee
--- /dev/null
+++ b/src/test/ui/associated-types/associated-type-tuple-struct-construction.stderr
@@ -0,0 +1,19 @@
+error[E0575]: expected method or associated constant, found associated type `A::Assoc`
+ --> $DIR/associated-type-tuple-struct-construction.rs:7:32
+ |
+LL | let <Foo as A>::Assoc(n) = <Foo as A>::Assoc(2);
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: can't use a type alias as a constructor
+
+error[E0575]: expected method or associated constant, found associated type `A::Assoc`
+ --> $DIR/associated-type-tuple-struct-construction.rs:7:9
+ |
+LL | let <Foo as A>::Assoc(n) = <Foo as A>::Assoc(2);
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: can't use a type alias as a constructor
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0575`.
diff --git a/src/test/ui/borrowck/issue-85765.rs b/src/test/ui/borrowck/issue-85765.rs
new file mode 100644
index 0000000..b82e029
--- /dev/null
+++ b/src/test/ui/borrowck/issue-85765.rs
@@ -0,0 +1,8 @@
+fn main() {
+ let mut test = Vec::new();
+ let rofl: &Vec<Vec<i32>> = &mut test;
+ //~^ HELP consider changing this to be a mutable reference
+ rofl.push(Vec::new());
+ //~^ ERROR cannot borrow `*rofl` as mutable, as it is behind a `&` reference
+ //~| NOTE `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+}
diff --git a/src/test/ui/borrowck/issue-85765.stderr b/src/test/ui/borrowck/issue-85765.stderr
new file mode 100644
index 0000000..863c2e8
--- /dev/null
+++ b/src/test/ui/borrowck/issue-85765.stderr
@@ -0,0 +1,12 @@
+error[E0596]: cannot borrow `*rofl` as mutable, as it is behind a `&` reference
+ --> $DIR/issue-85765.rs:5:5
+ |
+LL | let rofl: &Vec<Vec<i32>> = &mut test;
+ | ---- help: consider changing this to be a mutable reference: `&mut Vec<Vec<i32>>`
+LL |
+LL | rofl.push(Vec::new());
+ | ^^^^ `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr b/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr
index 985e7b6..29d835e 100644
--- a/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr
+++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr
@@ -2,13 +2,13 @@
--> $DIR/intermixed-lifetime.rs:7:28
|
LL | struct Foo<const N: usize, 'a, T = u32>(&'a (), T);
- | -----------------^^---------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const N: usize, T = u32>`
+ | -----------------^^---------- help: reorder the parameters: lifetimes, then consts and types: `<'a, const N: usize, T = u32>`
error: lifetime parameters must be declared prior to type parameters
--> $DIR/intermixed-lifetime.rs:10:37
|
LL | struct Bar<const N: usize, T = u32, 'a>(&'a (), T);
- | --------------------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const N: usize, T = u32>`
+ | --------------------------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, const N: usize, T = u32>`
error: aborting due to 2 previous errors
diff --git a/src/test/ui/const-generics/defaults/mismatch.full.stderr b/src/test/ui/const-generics/defaults/mismatch.full.stderr
index be4f364..4aa8401 100644
--- a/src/test/ui/const-generics/defaults/mismatch.full.stderr
+++ b/src/test/ui/const-generics/defaults/mismatch.full.stderr
@@ -5,9 +5,12 @@
| ------------- ^^ expected struct `Example`, found `()`
| |
| expected due to this
+ |
+ = note: expected struct `Example`
+ found unit type `()`
error[E0308]: mismatched types
- --> $DIR/mismatch.rs:14:34
+ --> $DIR/mismatch.rs:15:34
|
LL | let e: Example2::<u32, 13> = ();
| ------------------- ^^ expected struct `Example2`, found `()`
@@ -18,7 +21,7 @@
found unit type `()`
error[E0308]: mismatched types
- --> $DIR/mismatch.rs:16:34
+ --> $DIR/mismatch.rs:18:34
|
LL | let e: Example3::<13, u32> = ();
| ------------------- ^^ expected struct `Example3`, found `()`
@@ -29,7 +32,7 @@
found unit type `()`
error[E0308]: mismatched types
- --> $DIR/mismatch.rs:18:28
+ --> $DIR/mismatch.rs:21:28
|
LL | let e: Example3::<7> = ();
| ------------- ^^ expected struct `Example3`, found `()`
@@ -40,12 +43,15 @@
found unit type `()`
error[E0308]: mismatched types
- --> $DIR/mismatch.rs:22:28
+ --> $DIR/mismatch.rs:24:28
|
LL | let e: Example4::<7> = ();
| ------------- ^^ expected struct `Example4`, found `()`
| |
| expected due to this
+ |
+ = note: expected struct `Example4<7_usize>`
+ found unit type `()`
error: aborting due to 5 previous errors
diff --git a/src/test/ui/const-generics/defaults/mismatch.min.stderr b/src/test/ui/const-generics/defaults/mismatch.min.stderr
index be4f364..4aa8401 100644
--- a/src/test/ui/const-generics/defaults/mismatch.min.stderr
+++ b/src/test/ui/const-generics/defaults/mismatch.min.stderr
@@ -5,9 +5,12 @@
| ------------- ^^ expected struct `Example`, found `()`
| |
| expected due to this
+ |
+ = note: expected struct `Example`
+ found unit type `()`
error[E0308]: mismatched types
- --> $DIR/mismatch.rs:14:34
+ --> $DIR/mismatch.rs:15:34
|
LL | let e: Example2::<u32, 13> = ();
| ------------------- ^^ expected struct `Example2`, found `()`
@@ -18,7 +21,7 @@
found unit type `()`
error[E0308]: mismatched types
- --> $DIR/mismatch.rs:16:34
+ --> $DIR/mismatch.rs:18:34
|
LL | let e: Example3::<13, u32> = ();
| ------------------- ^^ expected struct `Example3`, found `()`
@@ -29,7 +32,7 @@
found unit type `()`
error[E0308]: mismatched types
- --> $DIR/mismatch.rs:18:28
+ --> $DIR/mismatch.rs:21:28
|
LL | let e: Example3::<7> = ();
| ------------- ^^ expected struct `Example3`, found `()`
@@ -40,12 +43,15 @@
found unit type `()`
error[E0308]: mismatched types
- --> $DIR/mismatch.rs:22:28
+ --> $DIR/mismatch.rs:24:28
|
LL | let e: Example4::<7> = ();
| ------------- ^^ expected struct `Example4`, found `()`
| |
| expected due to this
+ |
+ = note: expected struct `Example4<7_usize>`
+ found unit type `()`
error: aborting due to 5 previous errors
diff --git a/src/test/ui/const-generics/defaults/mismatch.rs b/src/test/ui/const-generics/defaults/mismatch.rs
index 68a640c..9d9a879 100644
--- a/src/test/ui/const-generics/defaults/mismatch.rs
+++ b/src/test/ui/const-generics/defaults/mismatch.rs
@@ -11,14 +11,17 @@
fn main() {
let e: Example::<13> = ();
//~^ Error: mismatched types
+ //~| expected struct `Example`
let e: Example2::<u32, 13> = ();
//~^ Error: mismatched types
+ //~| expected struct `Example2`
let e: Example3::<13, u32> = ();
//~^ Error: mismatched types
+ //~| expected struct `Example3`
let e: Example3::<7> = ();
//~^ Error: mismatched types
- // FIXME(const_generics_defaults): There should be a note for the error below, but it is
- // missing.
+ //~| expected struct `Example3<7_usize>`
let e: Example4::<7> = ();
//~^ Error: mismatched types
+ //~| expected struct `Example4<7_usize>`
}
diff --git a/src/test/ui/const-generics/defaults/param-order-err-pretty-prints-default.rs b/src/test/ui/const-generics/defaults/param-order-err-pretty-prints-default.rs
new file mode 100644
index 0000000..933eacb
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/param-order-err-pretty-prints-default.rs
@@ -0,0 +1,5 @@
+#![feature(const_generics_defaults)]
+struct Foo<const M: usize = 10, 'a>(&'a u32);
+//~^ Error lifetime parameters must be declared prior to const parameters
+
+fn main() {}
diff --git a/src/test/ui/const-generics/defaults/param-order-err-pretty-prints-default.stderr b/src/test/ui/const-generics/defaults/param-order-err-pretty-prints-default.stderr
new file mode 100644
index 0000000..f50653f
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/param-order-err-pretty-prints-default.stderr
@@ -0,0 +1,8 @@
+error: lifetime parameters must be declared prior to const parameters
+ --> $DIR/param-order-err-pretty-prints-default.rs:2:33
+ |
+LL | struct Foo<const M: usize = 10, 'a>(&'a u32);
+ | ----------------------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, const M: usize = 10>`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/min_const_generics/transmute-const-param-static-reference.rs b/src/test/ui/const-generics/min_const_generics/transmute-const-param-static-reference.rs
deleted file mode 100644
index 560795a..0000000
--- a/src/test/ui/const-generics/min_const_generics/transmute-const-param-static-reference.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-struct Const<const P: &'static ()>;
-//~^ ERROR `&'static ()` is forbidden as the type of a const generic parameter
-
-fn main() {
- const A: &'static () = unsafe {
- std::mem::transmute(10 as *const ())
- };
-
- let _ = Const::<{A}>;
-}
diff --git a/src/test/ui/const-generics/min_const_generics/transmute-const-param-static-reference.stderr b/src/test/ui/const-generics/transmute-const-param-static-reference.min.stderr
similarity index 85%
rename from src/test/ui/const-generics/min_const_generics/transmute-const-param-static-reference.stderr
rename to src/test/ui/const-generics/transmute-const-param-static-reference.min.stderr
index d612e0c..f735be9 100644
--- a/src/test/ui/const-generics/min_const_generics/transmute-const-param-static-reference.stderr
+++ b/src/test/ui/const-generics/transmute-const-param-static-reference.min.stderr
@@ -1,5 +1,5 @@
error: `&'static ()` is forbidden as the type of a const generic parameter
- --> $DIR/transmute-const-param-static-reference.rs:1:23
+ --> $DIR/transmute-const-param-static-reference.rs:7:23
|
LL | struct Const<const P: &'static ()>;
| ^^^^^^^^^^^
diff --git a/src/test/ui/const-generics/transmute-const-param-static-reference.rs b/src/test/ui/const-generics/transmute-const-param-static-reference.rs
new file mode 100644
index 0000000..3147d61
--- /dev/null
+++ b/src/test/ui/const-generics/transmute-const-param-static-reference.rs
@@ -0,0 +1,16 @@
+// revisions: full min
+//[full] check-pass
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+
+struct Const<const P: &'static ()>;
+//[min]~^ ERROR `&'static ()` is forbidden as the type of a const generic parameter
+
+fn main() {
+ const A: &'static () = unsafe {
+ std::mem::transmute(10 as *const ())
+ };
+
+ let _ = Const::<{A}>;
+}
diff --git a/src/test/ui/consts/const-eval/ub-incorrect-vtable.rs b/src/test/ui/consts/const-eval/ub-incorrect-vtable.rs
new file mode 100644
index 0000000..0c0e368
--- /dev/null
+++ b/src/test/ui/consts/const-eval/ub-incorrect-vtable.rs
@@ -0,0 +1,21 @@
+// This test contains code with incorrect vtables in a const context:
+// - from issue 86132: a trait object with invalid alignment caused an ICE in const eval, and now
+// triggers an error
+// - a similar test that triggers a previously-untested const UB error: emitted close to the above
+// error, it checks the correctness of the size
+
+trait Trait {}
+
+const INVALID_VTABLE_ALIGNMENT: &dyn Trait =
+ unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
+//~^ ERROR any use of this value will cause an error
+//~| WARNING this was previously accepted by the compiler
+//~| invalid vtable: alignment `1000` is not a power of 2
+
+const INVALID_VTABLE_SIZE: &dyn Trait =
+ unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
+//~^ ERROR any use of this value will cause an error
+//~| WARNING this was previously accepted by the compiler
+//~| invalid vtable: size is bigger than largest supported object
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/ub-incorrect-vtable.stderr b/src/test/ui/consts/const-eval/ub-incorrect-vtable.stderr
new file mode 100644
index 0000000..c937d03
--- /dev/null
+++ b/src/test/ui/consts/const-eval/ub-incorrect-vtable.stderr
@@ -0,0 +1,27 @@
+error: any use of this value will cause an error
+ --> $DIR/ub-incorrect-vtable.rs:10:14
+ |
+LL | / const INVALID_VTABLE_ALIGNMENT: &dyn Trait =
+LL | | unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
+ | |______________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^__-
+ | |
+ | invalid vtable: alignment `1000` is not a power of 2
+ |
+ = note: `#[deny(const_err)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: any use of this value will cause an error
+ --> $DIR/ub-incorrect-vtable.rs:16:14
+ |
+LL | / const INVALID_VTABLE_SIZE: &dyn Trait =
+LL | | unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
+ | |______________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^__-
+ | |
+ | invalid vtable: size is bigger than largest supported object
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/consts/const-needs_drop-monomorphic.rs b/src/test/ui/consts/const-needs_drop-monomorphic.rs
new file mode 100644
index 0000000..9f66e3c
--- /dev/null
+++ b/src/test/ui/consts/const-needs_drop-monomorphic.rs
@@ -0,0 +1,17 @@
+// Check that evaluation of needs_drop<T> fails when T is not monomorphic.
+#![feature(const_generics)]
+#![allow(const_evaluatable_unchecked)]
+#![allow(incomplete_features)]
+
+struct Bool<const B: bool> {}
+impl Bool<true> {
+ fn assert() {}
+}
+fn f<T>() {
+ Bool::<{ std::mem::needs_drop::<T>() }>::assert();
+ //~^ ERROR no function or associated item named `assert` found
+ //~| ERROR constant expression depends on a generic parameter
+}
+fn main() {
+ f::<u32>();
+}
diff --git a/src/test/ui/consts/const-needs_drop-monomorphic.stderr b/src/test/ui/consts/const-needs_drop-monomorphic.stderr
new file mode 100644
index 0000000..0770d06
--- /dev/null
+++ b/src/test/ui/consts/const-needs_drop-monomorphic.stderr
@@ -0,0 +1,20 @@
+error[E0599]: no function or associated item named `assert` found for struct `Bool<{ std::mem::needs_drop::<T>() }>` in the current scope
+ --> $DIR/const-needs_drop-monomorphic.rs:11:46
+ |
+LL | struct Bool<const B: bool> {}
+ | -------------------------- function or associated item `assert` not found for this
+...
+LL | Bool::<{ std::mem::needs_drop::<T>() }>::assert();
+ | ^^^^^^ function or associated item cannot be called on `Bool<{ std::mem::needs_drop::<T>() }>` due to unsatisfied trait bounds
+
+error: constant expression depends on a generic parameter
+ --> $DIR/const-needs_drop-monomorphic.rs:11:5
+ |
+LL | Bool::<{ std::mem::needs_drop::<T>() }>::assert();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this may fail depending on what value the parameter takes
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/feature-gates/feature-gate-more-qualified-paths.rs b/src/test/ui/feature-gates/feature-gate-more-qualified-paths.rs
new file mode 100644
index 0000000..2e05acb
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-more-qualified-paths.rs
@@ -0,0 +1,27 @@
+fn main() {
+ // destructure through a qualified path
+ let <Foo as A>::Assoc { br } = StructStruct { br: 2 };
+ //~^ ERROR usage of qualified paths in this context is experimental
+ let _ = <Foo as A>::Assoc { br: 2 };
+ //~^ ERROR usage of qualified paths in this context is experimental
+ let <E>::V(..) = E::V(0);
+ //~^ ERROR usage of qualified paths in this context is experimental
+}
+
+struct StructStruct {
+ br: i8,
+}
+
+struct Foo;
+
+trait A {
+ type Assoc;
+}
+
+impl A for Foo {
+ type Assoc = StructStruct;
+}
+
+enum E {
+ V(u8)
+}
diff --git a/src/test/ui/feature-gates/feature-gate-more-qualified-paths.stderr b/src/test/ui/feature-gates/feature-gate-more-qualified-paths.stderr
new file mode 100644
index 0000000..b49cc40
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-more-qualified-paths.stderr
@@ -0,0 +1,30 @@
+error[E0658]: usage of qualified paths in this context is experimental
+ --> $DIR/feature-gate-more-qualified-paths.rs:3:9
+ |
+LL | let <Foo as A>::Assoc { br } = StructStruct { br: 2 };
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #80080 <https://github.com/rust-lang/rust/issues/80080> for more information
+ = help: add `#![feature(more_qualified_paths)]` to the crate attributes to enable
+
+error[E0658]: usage of qualified paths in this context is experimental
+ --> $DIR/feature-gate-more-qualified-paths.rs:5:13
+ |
+LL | let _ = <Foo as A>::Assoc { br: 2 };
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #80080 <https://github.com/rust-lang/rust/issues/80080> for more information
+ = help: add `#![feature(more_qualified_paths)]` to the crate attributes to enable
+
+error[E0658]: usage of qualified paths in this context is experimental
+ --> $DIR/feature-gate-more-qualified-paths.rs:7:9
+ |
+LL | let <E>::V(..) = E::V(0);
+ | ^^^^^^
+ |
+ = note: see issue #80080 <https://github.com/rust-lang/rust/issues/80080> for more information
+ = help: add `#![feature(more_qualified_paths)]` to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/parser/brace-after-qualified-path-in-match.rs b/src/test/ui/parser/brace-after-qualified-path-in-match.rs
deleted file mode 100644
index f415208..0000000
--- a/src/test/ui/parser/brace-after-qualified-path-in-match.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-fn main() {
- match 10 {
- <T as Trait>::Type{key: value} => (),
- //~^ ERROR unexpected `{` after qualified path
- _ => (),
- }
-}
diff --git a/src/test/ui/parser/brace-after-qualified-path-in-match.stderr b/src/test/ui/parser/brace-after-qualified-path-in-match.stderr
deleted file mode 100644
index d6fdf35..0000000
--- a/src/test/ui/parser/brace-after-qualified-path-in-match.stderr
+++ /dev/null
@@ -1,10 +0,0 @@
-error: unexpected `{` after qualified path
- --> $DIR/brace-after-qualified-path-in-match.rs:3:27
- |
-LL | <T as Trait>::Type{key: value} => (),
- | ------------------^ unexpected `{` after qualified path
- | |
- | the qualified path
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/parser/paren-after-qualified-path-in-match.rs b/src/test/ui/parser/paren-after-qualified-path-in-match.rs
deleted file mode 100644
index 68b1c2b..0000000
--- a/src/test/ui/parser/paren-after-qualified-path-in-match.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-fn main() {
- match 10 {
- <T as Trait>::Type(2) => (),
- //~^ ERROR unexpected `(` after qualified path
- _ => (),
- }
-}
diff --git a/src/test/ui/parser/paren-after-qualified-path-in-match.stderr b/src/test/ui/parser/paren-after-qualified-path-in-match.stderr
deleted file mode 100644
index af21f91..0000000
--- a/src/test/ui/parser/paren-after-qualified-path-in-match.stderr
+++ /dev/null
@@ -1,10 +0,0 @@
-error: unexpected `(` after qualified path
- --> $DIR/paren-after-qualified-path-in-match.rs:3:27
- |
-LL | <T as Trait>::Type(2) => (),
- | ------------------^ unexpected `(` after qualified path
- | |
- | the qualified path
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/simd/wasm-simd-indirect.rs b/src/test/ui/simd/wasm-simd-indirect.rs
index deac593..88f92fc 100644
--- a/src/test/ui/simd/wasm-simd-indirect.rs
+++ b/src/test/ui/simd/wasm-simd-indirect.rs
@@ -1,7 +1,5 @@
// build-pass
-#![cfg_attr(target_arch = "wasm32", feature(wasm_simd, wasm_target_feature))]
-
#[cfg(target_arch = "wasm32")]
fn main() {
unsafe {
diff --git a/src/test/ui/suggestions/issue-86100-tuple-paren-comma.rs b/src/test/ui/suggestions/issue-86100-tuple-paren-comma.rs
new file mode 100644
index 0000000..fa9d1a8
--- /dev/null
+++ b/src/test/ui/suggestions/issue-86100-tuple-paren-comma.rs
@@ -0,0 +1,25 @@
+// Tests that a suggestion is issued for type mismatch errors when a
+// 1-tuple is expected and a parenthesized expression of non-tuple
+// type is supplied.
+
+fn foo<T>(_t: (T,)) {}
+struct S { _s: (String,) }
+
+fn main() {
+ let _x: (i32,) = (5);
+ //~^ ERROR: mismatched types [E0308]
+ //~| HELP: use a trailing comma to create a tuple with one element
+
+ foo((Some(3)));
+ //~^ ERROR: mismatched types [E0308]
+ //~| HELP: use a trailing comma to create a tuple with one element
+
+ let _s = S { _s: ("abc".to_string()) };
+ //~^ ERROR: mismatched types [E0308]
+ //~| HELP: use a trailing comma to create a tuple with one element
+
+ // Do not issue the suggestion if the found type is already a tuple.
+ let t = (1, 2);
+ let _x: (i32,) = (t);
+ //~^ ERROR: mismatched types [E0308]
+}
diff --git a/src/test/ui/suggestions/issue-86100-tuple-paren-comma.stderr b/src/test/ui/suggestions/issue-86100-tuple-paren-comma.stderr
new file mode 100644
index 0000000..5753796
--- /dev/null
+++ b/src/test/ui/suggestions/issue-86100-tuple-paren-comma.stderr
@@ -0,0 +1,55 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-86100-tuple-paren-comma.rs:9:22
+ |
+LL | let _x: (i32,) = (5);
+ | ------ ^^^ expected tuple, found integer
+ | |
+ | expected due to this
+ |
+ = note: expected tuple `(i32,)`
+ found type `{integer}`
+help: use a trailing comma to create a tuple with one element
+ |
+LL | let _x: (i32,) = (5,);
+ | ^^^^
+
+error[E0308]: mismatched types
+ --> $DIR/issue-86100-tuple-paren-comma.rs:13:9
+ |
+LL | foo((Some(3)));
+ | ^^^^^^^^^ expected tuple, found enum `Option`
+ |
+ = note: expected tuple `(_,)`
+ found enum `Option<{integer}>`
+help: use a trailing comma to create a tuple with one element
+ |
+LL | foo((Some(3),));
+ | ^^^^^^^^^^
+
+error[E0308]: mismatched types
+ --> $DIR/issue-86100-tuple-paren-comma.rs:17:22
+ |
+LL | let _s = S { _s: ("abc".to_string()) };
+ | ^^^^^^^^^^^^^^^^^^^ expected tuple, found struct `String`
+ |
+ = note: expected tuple `(String,)`
+ found struct `String`
+help: use a trailing comma to create a tuple with one element
+ |
+LL | let _s = S { _s: ("abc".to_string(),) };
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+ --> $DIR/issue-86100-tuple-paren-comma.rs:23:22
+ |
+LL | let _x: (i32,) = (t);
+ | ------ ^^^ expected a tuple with 1 element, found one with 2 elements
+ | |
+ | expected due to this
+ |
+ = note: expected tuple `(i32,)`
+ found tuple `({integer}, {integer})`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/tools/clippy/clippy_lints/src/misc_early/unneeded_field_pattern.rs b/src/tools/clippy/clippy_lints/src/misc_early/unneeded_field_pattern.rs
index 329a000..2201cf5 100644
--- a/src/tools/clippy/clippy_lints/src/misc_early/unneeded_field_pattern.rs
+++ b/src/tools/clippy/clippy_lints/src/misc_early/unneeded_field_pattern.rs
@@ -5,7 +5,7 @@
use super::UNNEEDED_FIELD_PATTERN;
pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) {
- if let PatKind::Struct(ref npat, ref pfields, _) = pat.kind {
+ if let PatKind::Struct(_, ref npat, ref pfields, _) = pat.kind {
let mut wilds = 0;
let type_name = npat
.segments
diff --git a/src/tools/clippy/clippy_lints/src/misc_early/unneeded_wildcard_pattern.rs b/src/tools/clippy/clippy_lints/src/misc_early/unneeded_wildcard_pattern.rs
index 4dd032d..df04453 100644
--- a/src/tools/clippy/clippy_lints/src/misc_early/unneeded_wildcard_pattern.rs
+++ b/src/tools/clippy/clippy_lints/src/misc_early/unneeded_wildcard_pattern.rs
@@ -7,7 +7,7 @@
use super::UNNEEDED_WILDCARD_PATTERN;
pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) {
- if let PatKind::TupleStruct(_, ref patterns) | PatKind::Tuple(ref patterns) = pat.kind {
+ if let PatKind::TupleStruct(_, _, ref patterns) | PatKind::Tuple(ref patterns) = pat.kind {
if let Some(rest_index) = patterns.iter().position(|pat| pat.is_rest()) {
if let Some((left_index, left_pat)) = patterns[..rest_index]
.iter()
diff --git a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs
index 5292af5..1a23e6a 100644
--- a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs
+++ b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs
@@ -139,7 +139,7 @@
self.check_ident(ident);
}
},
- PatKind::Struct(_, ref fields, _) => {
+ PatKind::Struct(_, _, ref fields, _) => {
for field in fields {
if !field.is_shorthand {
self.visit_pat(&field.pat);
diff --git a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
index 3e985fa..1b3c457 100644
--- a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
+++ b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
@@ -1,6 +1,6 @@
#![allow(clippy::wildcard_imports, clippy::enum_glob_use)]
-use clippy_utils::ast_utils::{eq_field_pat, eq_id, eq_pat, eq_path};
+use clippy_utils::ast_utils::{eq_field_pat, eq_id, eq_pat, eq_path, eq_maybe_qself};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::{meets_msrv, msrvs, over};
use rustc_ast::mut_visit::*;
@@ -273,16 +273,16 @@
|k| always_pat!(k, Tuple(ps) => ps),
),
// Transform `S(pre, x, post) | ... | S(pre, y, post)` into `S(pre, x | y, post)`.
- TupleStruct(path1, ps1) => extend_with_matching_product(
+ TupleStruct(qself1, path1, ps1) => extend_with_matching_product(
ps1, start, alternatives,
|k, ps1, idx| matches!(
k,
- TupleStruct(path2, ps2) if eq_path(path1, path2) && eq_pre_post(ps1, ps2, idx)
+ TupleStruct(qself2, path2, ps2) if eq_maybe_qself(qself1, qself2) && eq_path(path1, path2) && eq_pre_post(ps1, ps2, idx)
),
- |k| always_pat!(k, TupleStruct(_, ps) => ps),
+ |k| always_pat!(k, TupleStruct(_, _, ps) => ps),
),
// Transform a record pattern `S { fp_0, ..., fp_n }`.
- Struct(path1, fps1, rest1) => extend_with_struct_pat(path1, fps1, *rest1, start, alternatives),
+ Struct(qself1, path1, fps1, rest1) => extend_with_struct_pat(qself1, path1, fps1, *rest1, start, alternatives),
};
alternatives[focus_idx].kind = focus_kind;
@@ -294,6 +294,7 @@
/// So when we fixate on some `ident_k: pat_k`, we try to find `ident_k` in the other pattern
/// and check that all `fp_i` where `i ∈ ((0...n) \ k)` between two patterns are equal.
fn extend_with_struct_pat(
+ qself1: &Option<ast::QSelf>,
path1: &ast::Path,
fps1: &mut Vec<ast::PatField>,
rest1: bool,
@@ -306,8 +307,9 @@
start,
alternatives,
|k| {
- matches!(k, Struct(path2, fps2, rest2)
+ matches!(k, Struct(qself2, path2, fps2, rest2)
if rest1 == *rest2 // If one struct pattern has `..` so must the other.
+ && eq_maybe_qself(qself1, qself2)
&& eq_path(path1, path2)
&& fps1.len() == fps2.len()
&& fps1.iter().enumerate().all(|(idx_1, fp1)| {
@@ -323,7 +325,7 @@
}))
},
// Extract `p2_k`.
- |k| always_pat!(k, Struct(_, mut fps, _) => fps.swap_remove(pos_in_2.take().unwrap()).pat),
+ |k| always_pat!(k, Struct(_, _, mut fps, _) => fps.swap_remove(pos_in_2.take().unwrap()).pat),
);
extend_with_tail_or(&mut fps1[idx].pat, tail_or)
})
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs
index 93e10c8..e6d84bc 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs
@@ -47,9 +47,9 @@
| (Ref(l, Mutability::Mut), Ref(r, Mutability::Mut)) => eq_pat(l, r),
(Tuple(l), Tuple(r)) | (Slice(l), Slice(r)) => over(l, r, |l, r| eq_pat(l, r)),
(Path(lq, lp), Path(rq, rp)) => both(lq, rq, |l, r| eq_qself(l, r)) && eq_path(lp, rp),
- (TupleStruct(lp, lfs), TupleStruct(rp, rfs)) => eq_path(lp, rp) && over(lfs, rfs, |l, r| eq_pat(l, r)),
- (Struct(lp, lfs, lr), Struct(rp, rfs, rr)) => {
- lr == rr && eq_path(lp, rp) && unordered_over(lfs, rfs, |lf, rf| eq_field_pat(lf, rf))
+ (TupleStruct(lqself, lp, lfs), TupleStruct(rqself, rp, rfs)) => eq_maybe_qself(lqself, rqself) && eq_path(lp, rp) && over(lfs, rfs, |l, r| eq_pat(l, r)),
+ (Struct(lqself, lp, lfs, lr), Struct(rqself, rp, rfs, rr)) => {
+ lr == rr && eq_maybe_qself(lqself, rqself) &&eq_path(lp, rp) && unordered_over(lfs, rfs, |lf, rf| eq_field_pat(lf, rf))
},
(Or(ls), Or(rs)) => unordered_over(ls, rs, |l, r| eq_pat(l, r)),
(MacCall(l), MacCall(r)) => eq_mac_call(l, r),
@@ -78,6 +78,14 @@
l.position == r.position && eq_ty(&l.ty, &r.ty)
}
+pub fn eq_maybe_qself(l: &Option<QSelf>, r: &Option<QSelf>) -> bool {
+ match (l, r) {
+ (Some(l), Some(r)) => eq_qself(l, r),
+ (None, None) => true,
+ _ => false
+ }
+}
+
pub fn eq_path(l: &Path, r: &Path) -> bool {
over(&l.segments, &r.segments, |l, r| eq_path_seg(l, r))
}
@@ -170,7 +178,8 @@
(Path(lq, lp), Path(rq, rp)) => both(lq, rq, |l, r| eq_qself(l, r)) && eq_path(lp, rp),
(MacCall(l), MacCall(r)) => eq_mac_call(l, r),
(Struct(lse), Struct(rse)) => {
- eq_path(&lse.path, &rse.path)
+ eq_maybe_qself(&lse.qself, &rse.qself)
+ && eq_path(&lse.path, &rse.path)
&& eq_struct_rest(&lse.rest, &rse.rest)
&& unordered_over(&lse.fields, &rse.fields, |l, r| eq_field(l, r))
},
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 408c0b8..a5b526b 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -346,6 +346,9 @@
/// whether to run `tidy` when a rustdoc test fails
pub has_tidy: bool,
+ /// The current Rust channel
+ pub channel: String,
+
// Configuration for various run-make tests frobbing things like C compilers
// or querying about various LLVM component information.
pub cc: String,
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 19ea215..26c1710 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -50,6 +50,15 @@
let has_msan = util::MSAN_SUPPORTED_TARGETS.contains(&&*config.target);
let has_tsan = util::TSAN_SUPPORTED_TARGETS.contains(&&*config.target);
let has_hwasan = util::HWASAN_SUPPORTED_TARGETS.contains(&&*config.target);
+ // for `-Z gcc-ld=lld`
+ let has_rust_lld = config
+ .compile_lib_path
+ .join("rustlib")
+ .join(&config.target)
+ .join("bin")
+ .join("gcc-ld")
+ .join(if config.host.contains("windows") { "ld.exe" } else { "ld" })
+ .exists();
iter_header(testfile, None, rdr, &mut |ln| {
// we should check if any only-<platform> exists and if it exists
@@ -136,6 +145,10 @@
if config.debugger == Some(Debugger::Lldb) && ignore_lldb(config, ln) {
props.ignore = true;
}
+
+ if !has_rust_lld && config.parse_name_directive(ln, "needs-rust-lld") {
+ props.ignore = true;
+ }
}
if let Some(s) = config.parse_aux_build(ln) {
@@ -879,6 +892,7 @@
name == util::get_arch(&self.target) || // architecture
name == util::get_pointer_width(&self.target) || // pointer width
name == self.stage_id.split('-').next().unwrap() || // stage
+ name == self.channel || // channel
(self.target != self.host && name == "cross-compile") ||
(name == "endian-big" && util::is_big_endian(&self.target)) ||
(self.remote_test_client.is_some() && name == "remote") ||
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index ca7458d..2c607b6 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -55,6 +55,7 @@
"--llvm-components=",
"--android-cross-path=",
"--target=x86_64-unknown-linux-gnu",
+ "--channel=nightly",
];
let args = args.iter().map(ToString::to_string).collect();
crate::parse_config(args)
@@ -235,6 +236,20 @@
}
#[test]
+fn channel() {
+ let mut config = config();
+ config.channel = "beta".into();
+
+ assert!(parse_rs(&config, "// ignore-beta").ignore);
+ assert!(parse_rs(&config, "// only-nightly").ignore);
+ assert!(parse_rs(&config, "// only-stable").ignore);
+
+ assert!(!parse_rs(&config, "// only-beta").ignore);
+ assert!(!parse_rs(&config, "// ignore-nightly").ignore);
+ assert!(!parse_rs(&config, "// ignore-stable").ignore);
+}
+
+#[test]
fn test_extract_version_range() {
use super::{extract_llvm_version, extract_version_range};
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index 08ee8fc..c854663 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -144,7 +144,8 @@
"enable this to generate a Rustfix coverage file, which is saved in \
`./<build_base>/rustfix_missing_coverage.txt`",
)
- .optflag("h", "help", "show this message");
+ .optflag("h", "help", "show this message")
+ .reqopt("", "channel", "current Rust channel", "CHANNEL");
let (argv0, args_) = args.split_first().unwrap();
if args.len() == 1 || args[1] == "-h" || args[1] == "--help" {
@@ -278,6 +279,7 @@
compare_mode: matches.opt_str("compare-mode").map(CompareMode::parse),
rustfix_coverage: matches.opt_present("rustfix-coverage"),
has_tidy,
+ channel: matches.opt_str("channel").unwrap(),
cc: matches.opt_str("cc").unwrap(),
cxx: matches.opt_str("cxx").unwrap(),
diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs
index ced382c..bca9f77 100644
--- a/src/tools/rustfmt/src/expr.rs
+++ b/src/tools/rustfmt/src/expr.rs
@@ -107,7 +107,9 @@
}
ast::ExprKind::Unary(op, ref subexpr) => rewrite_unary_op(context, op, subexpr, shape),
ast::ExprKind::Struct(ref struct_expr) => {
- let ast::StructExpr { fields, path, rest } = &**struct_expr;
+ let ast::StructExpr {
+ fields, path, rest, ..
+ } = &**struct_expr;
rewrite_struct_lit(context, path, fields, rest, &expr.attrs, expr.span, shape)
}
ast::ExprKind::Tup(ref items) => {
diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs
index 6824fc6..fa0ef26 100644
--- a/src/tools/rustfmt/src/patterns.rs
+++ b/src/tools/rustfmt/src/patterns.rs
@@ -45,7 +45,7 @@
| ast::PatKind::Path(..)
| ast::PatKind::Range(..) => false,
ast::PatKind::Tuple(ref subpats) => subpats.len() <= 1,
- ast::PatKind::TupleStruct(ref path, ref subpats) => {
+ ast::PatKind::TupleStruct(_, ref path, ref subpats) => {
path.segments.len() <= 1 && subpats.len() <= 1
}
ast::PatKind::Box(ref p) | ast::PatKind::Ref(ref p, _) | ast::PatKind::Paren(ref p) => {
@@ -226,7 +226,7 @@
PatKind::Path(ref q_self, ref path) => {
rewrite_path(context, PathContext::Expr, q_self.as_ref(), path, shape)
}
- PatKind::TupleStruct(ref path, ref pat_vec) => {
+ PatKind::TupleStruct(_, ref path, ref pat_vec) => {
let path_str = rewrite_path(context, PathContext::Expr, None, path, shape)?;
rewrite_tuple_pat(pat_vec, Some(path_str), self.span, context, shape)
}
@@ -244,7 +244,7 @@
.collect();
Some(format!("[{}]", rw.join(", ")))
}
- PatKind::Struct(ref path, ref fields, ellipsis) => {
+ PatKind::Struct(_, ref path, ref fields, ellipsis) => {
rewrite_struct_pat(path, fields, ellipsis, self.span, context, shape)
}
PatKind::MacCall(ref mac) => {
diff --git a/src/version b/src/version
index b7921ae..094d6ad 100644
--- a/src/version
+++ b/src/version
@@ -1 +1 @@
-1.54.0
+1.55.0