diff --git a/Cargo.lock b/Cargo.lock index 80acf227698e9..cde73166babb7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,9 +26,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.13" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" dependencies = [ "memchr", ] @@ -559,7 +559,7 @@ dependencies = [ "cargo_metadata 0.12.0", "clippy_lints", "clippy_utils", - "compiletest_rs 0.6.0", + "compiletest_rs", "derive-new", "filetime", "if_chain", @@ -581,7 +581,7 @@ version = "0.0.1" dependencies = [ "bytecount", "clap", - "itertools 0.9.0", + "itertools 0.10.1", "opener", "regex", "shell-escape", @@ -595,7 +595,7 @@ dependencies = [ "cargo_metadata 0.12.0", "clippy_utils", "if_chain", - "itertools 0.9.0", + "itertools 0.10.1", "pulldown-cmark 0.8.0", "quine-mc_cluskey", "regex-syntax", @@ -687,29 +687,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "compiletest_rs" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0086d6ad78cf409c3061618cd98e2789d5c9ce598fc9651611cf62eae0a599cb" -dependencies = [ - "diff", - "filetime", - "getopts", - "lazy_static", - "libc", - "log", - "miow", - "regex", - "rustfix 0.5.1", - "serde", - "serde_derive", - "serde_json", - "tempfile", - "tester", - "winapi", -] - [[package]] name = "compiletest_rs" version = "0.7.0" @@ -2272,7 +2249,7 @@ name = "miri" version = "0.1.0" dependencies = [ "colored", - "compiletest_rs 0.7.0", + "compiletest_rs", "env_logger 0.8.1", "getrandom 0.2.0", "hex 0.4.2", @@ -3005,9 +2982,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.4.6" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a26af418b574bd56588335b3a3659a65725d4e636eb1016c2f9e3b38c7cc759" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" dependencies = [ "aho-corasick", "memchr", diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index b92c5fa072786..c27ab810a4c60 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1902,10 +1902,6 @@ pub enum TyKind { Never, /// A tuple (`(A, B, C, D,...)`). Tup(Vec>), - /// An anonymous struct type i.e. `struct { foo: Type }` - AnonymousStruct(Vec, bool), - /// An anonymous union type i.e. `union { bar: Type }` - AnonymousUnion(Vec, bool), /// A path (`module::module::...::Type`), optionally /// "qualified", e.g., ` as SomeTrait>::SomeType`. /// diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 2ec941cbb2466..ba86036577ac5 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -484,9 +484,6 @@ pub fn noop_visit_ty(ty: &mut P, vis: &mut T) { visit_vec(bounds, |bound| vis.visit_param_bound(bound)); } TyKind::MacCall(mac) => vis.visit_mac_call(mac), - TyKind::AnonymousStruct(fields, ..) | TyKind::AnonymousUnion(fields, ..) => { - fields.flat_map_in_place(|field| vis.flat_map_field_def(field)); - } } vis.visit_span(span); visit_lazy_tts(tokens, vis); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index c30f711b39707..b38031042e0f0 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -407,9 +407,6 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) { TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression), TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {} TyKind::MacCall(ref mac) => visitor.visit_mac_call(mac), - TyKind::AnonymousStruct(ref fields, ..) | TyKind::AnonymousUnion(ref fields, ..) => { - walk_list!(visitor, visit_field_def, fields) - } TyKind::Never | TyKind::CVarArgs => {} } } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index b7497c713f3df..a77e3e1997fd6 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -748,10 +748,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - pub(super) fn lower_field_def( - &mut self, - (index, f): (usize, &FieldDef), - ) -> hir::FieldDef<'hir> { + fn lower_field_def(&mut self, (index, f): (usize, &FieldDef)) -> hir::FieldDef<'hir> { let ty = if let TyKind::Path(ref qself, ref path) = f.ty.kind { let t = self.lower_path_ty( &f.ty, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 8d731d7a57895..4cf54b07dbef8 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1301,15 +1301,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let kind = match t.kind { TyKind::Infer => hir::TyKind::Infer, TyKind::Err => hir::TyKind::Err, - // FIXME(unnamed_fields): IMPLEMENTATION IN PROGRESS - TyKind::AnonymousStruct(ref _fields, _recovered) => { - self.sess.struct_span_err(t.span, "anonymous structs are unimplemented").emit(); - hir::TyKind::Err - } - TyKind::AnonymousUnion(ref _fields, _recovered) => { - self.sess.struct_span_err(t.span, "anonymous unions are unimplemented").emit(); - hir::TyKind::Err - } TyKind::Slice(ref ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)), TyKind::Ptr(ref mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)), TyKind::Rptr(ref region, ref mt) => { diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index e9dce953c7388..6723cffc8e684 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -193,11 +193,6 @@ impl<'a> AstValidator<'a> { } } } - TyKind::AnonymousStruct(ref fields, ..) | TyKind::AnonymousUnion(ref fields, ..) => { - self.with_banned_assoc_ty_bound(|this| { - walk_list!(this, visit_struct_field_def, fields) - }); - } _ => visit::walk_ty(self, t), } } @@ -205,7 +200,6 @@ impl<'a> AstValidator<'a> { fn visit_struct_field_def(&mut self, field: &'a FieldDef) { if let Some(ident) = field.ident { if ident.name == kw::Underscore { - self.check_anonymous_field(field); self.visit_vis(&field.vis); self.visit_ident(ident); self.visit_ty_common(&field.ty); @@ -251,66 +245,6 @@ impl<'a> AstValidator<'a> { err.emit(); } - fn check_anonymous_field(&self, field: &FieldDef) { - let FieldDef { ty, .. } = field; - match &ty.kind { - TyKind::AnonymousStruct(..) | TyKind::AnonymousUnion(..) => { - // We already checked for `kw::Underscore` before calling this function, - // so skip the check - } - TyKind::Path(..) => { - // If the anonymous field contains a Path as type, we can't determine - // if the path is a valid struct or union, so skip the check - } - _ => { - let msg = "unnamed fields can only have struct or union types"; - let label = "not a struct or union"; - self.err_handler() - .struct_span_err(field.span, msg) - .span_label(ty.span, label) - .emit(); - } - } - } - - fn deny_anonymous_struct(&self, ty: &Ty) { - match &ty.kind { - TyKind::AnonymousStruct(..) => { - self.err_handler() - .struct_span_err( - ty.span, - "anonymous structs are not allowed outside of unnamed struct or union fields", - ) - .span_label(ty.span, "anonymous struct declared here") - .emit(); - } - TyKind::AnonymousUnion(..) => { - self.err_handler() - .struct_span_err( - ty.span, - "anonymous unions are not allowed outside of unnamed struct or union fields", - ) - .span_label(ty.span, "anonymous union declared here") - .emit(); - } - _ => {} - } - } - - fn deny_anonymous_field(&self, field: &FieldDef) { - if let Some(ident) = field.ident { - if ident.name == kw::Underscore { - self.err_handler() - .struct_span_err( - field.span, - "anonymous fields are not allowed outside of structs or unions", - ) - .span_label(ident.span, "anonymous field declared here") - .emit() - } - } - } - fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option, bool)) { for Param { pat, .. } in &decl.inputs { match pat.kind { @@ -1081,7 +1015,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_ty(&mut self, ty: &'a Ty) { self.visit_ty_common(ty); - self.deny_anonymous_struct(ty); self.walk_ty(ty) } @@ -1096,7 +1029,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } fn visit_field_def(&mut self, s: &'a FieldDef) { - self.deny_anonymous_field(s); visit::walk_field_def(self, s) } diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 1defb65ed8793..30bc4edd7e69c 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -668,7 +668,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) { // involved, so we only emit errors where there are no other parsing errors. gate_all!(destructuring_assignment, "destructuring assignments are unstable"); } - gate_all!(unnamed_fields, "unnamed fields are not yet fully implemented"); // All uses of `gate_all!` below this point were added in #65742, // and subsequently disabled (with the non-early gating readded). diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 3cf04be160c64..c24882086e12d 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -985,14 +985,6 @@ impl<'a> State<'a> { } self.pclose(); } - ast::TyKind::AnonymousStruct(ref fields, ..) => { - self.head("struct"); - self.print_record_struct_body(&fields, ty.span); - } - ast::TyKind::AnonymousUnion(ref fields, ..) => { - self.head("union"); - self.print_record_struct_body(&fields, ty.span); - } ast::TyKind::Paren(ref typ) => { self.popen(); self.print_type(typ); @@ -1413,7 +1405,12 @@ impl<'a> State<'a> { } } - crate fn print_record_struct_body(&mut self, fields: &[ast::FieldDef], span: rustc_span::Span) { + crate fn print_record_struct_body( + &mut self, + fields: &Vec, + span: rustc_span::Span, + ) { + self.nbsp(); self.bopen(); self.hardbreak_if_not_bol(); @@ -1462,7 +1459,6 @@ impl<'a> State<'a> { } ast::VariantData::Struct(ref fields, ..) => { self.print_where_clause(&generics.where_clause); - self.nbsp(); self.print_record_struct_body(fields, span); } } diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 56b93f8346680..c180706c581a6 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -12,7 +12,7 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_session::config::OptLevel; use rustc_session::Session; use rustc_target::spec::abi::Abi; -use rustc_target::spec::{FramePointer, SanitizerSet, StackProbeType}; +use rustc_target::spec::{FramePointer, SanitizerSet, StackProbeType, StackProtector}; use crate::attributes; use crate::llvm::AttributePlace::Function; @@ -161,6 +161,17 @@ fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { } } +fn set_stackprotector(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { + let sspattr = match cx.sess().stack_protector() { + StackProtector::None => return, + StackProtector::All => Attribute::StackProtectReq, + StackProtector::Strong => Attribute::StackProtectStrong, + StackProtector::Basic => Attribute::StackProtect, + }; + + sspattr.apply_llfn(Function, llfn) +} + pub fn apply_target_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { let target_cpu = SmallCStr::new(llvm_util::target_cpu(cx.tcx.sess)); llvm::AddFunctionAttrStringValue( @@ -267,6 +278,7 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty:: set_frame_pointer_type(cx, llfn); set_instrument_function(cx, llfn); set_probestack(cx, llfn); + set_stackprotector(cx, llfn); if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) { Attribute::Cold.apply_llfn(Function, llfn); diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 1da14344b1d26..5756e47590272 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -232,6 +232,29 @@ impl CodegenBackend for LlvmCodegenBackend { } println!(); } + PrintRequest::StackProtectorStrategies => { + println!( + r#"Available stack protector strategies: + all + Generate stack canaries in all functions. + + strong + Generate stack canaries in a function if it either: + - has a local variable of `[T; N]` type, regardless of `T` and `N` + - takes the address of a local variable. + + (Note that a local variable being borrowed is not equivalent to its + address being taken: e.g. some borrows may be removed by optimization, + while by-value argument passing may be implemented with reference to a + local stack variable in the ABI.) + + basic + Generate stack canaries in functions with: + - local variables of `[T; N]` type, where `T` is byte-sized and `N` > 8. + +"# + ); + } req => llvm_util::print(req, sess), } } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 3f2ed02d90df3..3accd9785650d 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -159,6 +159,9 @@ pub enum Attribute { InaccessibleMemOnly = 27, SanitizeHWAddress = 28, WillReturn = 29, + StackProtectReq = 30, + StackProtectStrong = 31, + StackProtect = 32, } /// LLVMIntPredicate diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 53053327d0dab..9edcf1dbb747d 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -736,7 +736,12 @@ impl RustcDefaultCalls { println!("{}", cfg); } } - RelocationModels | CodeModels | TlsModels | TargetCPUs | TargetFeatures => { + RelocationModels + | CodeModels + | TlsModels + | TargetCPUs + | StackProtectorStrategies + | TargetFeatures => { codegen_backend.print(*req, sess); } // Any output here interferes with Cargo's parsing of other printed output diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 366ed715434ed..efa93c186363a 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -638,9 +638,6 @@ declare_features! ( /// Allows specifying the as-needed link modifier (active, native_link_modifiers_as_needed, "1.53.0", Some(81490), None), - /// Allows unnamed fields of struct and union type - (incomplete, 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(86935), None), diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index afab919bc3c2c..4729c9e004261 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -18,7 +18,9 @@ use rustc_span::edition::{Edition, DEFAULT_EDITION}; use rustc_span::symbol::sym; use rustc_span::SourceFileHashAlgorithm; use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy}; -use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, TlsModel}; +use rustc_target::spec::{ + RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel, +}; use std::collections::{BTreeMap, BTreeSet}; use std::iter::FromIterator; @@ -709,8 +711,8 @@ fn test_debugging_options_tracking_hash() { // This list is in alphabetical order. tracked!(allow_features, Some(vec![String::from("lang_items")])); tracked!(always_encode_mir, true); - tracked!(assume_incomplete_release, true); tracked!(asm_comments, true); + tracked!(assume_incomplete_release, true); tracked!(binary_dep_depinfo, true); tracked!(chalk, true); tracked!(codegen_backend, Some("abc".to_string())); @@ -726,8 +728,8 @@ fn test_debugging_options_tracking_hash() { tracked!(human_readable_cgu_names, true); tracked!(inline_in_all_cgus, Some(true)); tracked!(inline_mir, Some(true)); - tracked!(inline_mir_threshold, Some(123)); tracked!(inline_mir_hint_threshold, Some(123)); + tracked!(inline_mir_threshold, Some(123)); tracked!(instrument_coverage, Some(InstrumentCoverage::All)); tracked!(instrument_mcount, true); tracked!(link_only, true); @@ -753,7 +755,6 @@ fn test_debugging_options_tracking_hash() { tracked!(profiler_runtime, "abc".to_string()); tracked!(relax_elf_relocations, Some(true)); tracked!(relro_level, Some(RelroLevel::Full)); - tracked!(simulate_remapped_rust_src_base, Some(PathBuf::from("/rustc/abc"))); tracked!(report_delayed_bugs, true); tracked!(sanitizer, SanitizerSet::ADDRESS); tracked!(sanitizer_memory_track_origins, 2); @@ -761,15 +762,17 @@ fn test_debugging_options_tracking_hash() { tracked!(saturating_float_casts, Some(true)); tracked!(share_generics, Some(true)); tracked!(show_span, Some(String::from("abc"))); + tracked!(simulate_remapped_rust_src_base, Some(PathBuf::from("/rustc/abc"))); tracked!(src_hash_algorithm, Some(SourceFileHashAlgorithm::Sha1)); + tracked!(stack_protector, StackProtector::All); tracked!(symbol_mangling_version, Some(SymbolManglingVersion::V0)); tracked!(teach, true); tracked!(thinlto, Some(true)); tracked!(thir_unsafeck, true); - tracked!(tune_cpu, Some(String::from("abc"))); tracked!(tls_model, Some(TlsModel::GeneralDynamic)); tracked!(trap_unreachable, Some(false)); tracked!(treat_err_as_bug, NonZeroUsize::new(1)); + tracked!(tune_cpu, Some(String::from("abc"))); tracked!(unleash_the_miri_inside_of_you, true); tracked!(use_ctors_section, Some(true)); tracked!(verify_llvm_ir, true); diff --git a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h index 0b1b68d83b7b9..51c835245997e 100644 --- a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h +++ b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h @@ -80,6 +80,9 @@ enum LLVMRustAttribute { InaccessibleMemOnly = 27, SanitizeHWAddress = 28, WillReturn = 29, + StackProtectReq = 30, + StackProtectStrong = 31, + StackProtect = 32, }; typedef struct OpaqueRustString *RustStringRef; diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 9850f395a0f65..b86a9ac8265e2 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -199,6 +199,12 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) { return Attribute::SanitizeHWAddress; case WillReturn: return Attribute::WillReturn; + case StackProtectReq: + return Attribute::StackProtectReq; + case StackProtectStrong: + return Attribute::StackProtectStrong; + case StackProtect: + return Attribute::StackProtect; } report_fatal_error("bad AttributeKind"); } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 10c73fd64bc19..c5b961f12b2ab 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1234,7 +1234,7 @@ impl<'a> Parser<'a> { Ok((class_name, ItemKind::Union(vdata, generics))) } - pub(super) fn parse_record_struct_body( + fn parse_record_struct_body( &mut self, adt_ty: &str, ) -> PResult<'a, (Vec, /* recovered */ bool)> { @@ -1468,28 +1468,22 @@ impl<'a> Parser<'a> { fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> { let (ident, is_raw) = self.ident_or_err()?; if !is_raw && ident.is_reserved() { - if ident.name == kw::Underscore { - self.sess.gated_spans.gate(sym::unnamed_fields, lo); + let err = if self.check_fn_front_matter(false) { + // We use `parse_fn` to get a span for the function + if let Err(mut db) = self.parse_fn(&mut Vec::new(), |_| true, lo) { + db.delay_as_bug(); + } + let mut err = self.struct_span_err( + lo.to(self.prev_token.span), + &format!("functions are not allowed in {} definitions", adt_ty), + ); + err.help("unlike in C++, Java, and C#, functions are declared in `impl` blocks"); + err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information"); + err } else { - let err = if self.check_fn_front_matter(false) { - // We use `parse_fn` to get a span for the function - if let Err(mut db) = self.parse_fn(&mut Vec::new(), |_| true, lo) { - db.delay_as_bug(); - } - let mut err = self.struct_span_err( - lo.to(self.prev_token.span), - &format!("functions are not allowed in {} definitions", adt_ty), - ); - err.help( - "unlike in C++, Java, and C#, functions are declared in `impl` blocks", - ); - err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information"); - err - } else { - self.expected_ident_found() - }; - return Err(err); - } + self.expected_ident_found() + }; + return Err(err); } self.bump(); Ok(ident) diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 299fc916ac97f..98400372c36a6 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -226,19 +226,6 @@ impl<'a> Parser<'a> { } } else if self.eat_keyword(kw::Impl) { self.parse_impl_ty(&mut impl_dyn_multi)? - } else if self.token.is_keyword(kw::Union) - && self.look_ahead(1, |t| t == &token::OpenDelim(token::Brace)) - { - self.bump(); - let (fields, recovered) = self.parse_record_struct_body("union")?; - let span = lo.to(self.prev_token.span); - self.sess.gated_spans.gate(sym::unnamed_fields, span); - TyKind::AnonymousUnion(fields, recovered) - } else if self.eat_keyword(kw::Struct) { - let (fields, recovered) = self.parse_record_struct_body("struct")?; - let span = lo.to(self.prev_token.span); - self.sess.gated_spans.gate(sym::unnamed_fields, span); - TyKind::AnonymousStruct(fields, recovered) } else if self.is_explicit_dyn_type() { self.parse_dyn_ty(&mut impl_dyn_multi)? } else if self.eat_lt() { diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index fdedb7e6a4afe..062c424478c6b 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -512,6 +512,7 @@ pub enum PrintRequest { TlsModels, TargetSpec, NativeStaticLibs, + StackProtectorStrategies, } #[derive(Copy, Clone)] @@ -1067,8 +1068,8 @@ pub fn rustc_short_optgroups() -> Vec { "print", "Compiler information to print on stdout", "[crate-name|file-names|sysroot|target-libdir|cfg|target-list|\ - target-cpus|target-features|relocation-models|\ - code-models|tls-models|target-spec-json|native-static-libs]", + target-cpus|target-features|relocation-models|code-models|\ + tls-models|target-spec-json|native-static-libs|stack-protector-strategies]", ), opt::flagmulti_s("g", "", "Equivalent to -C debuginfo=2"), opt::flagmulti_s("O", "", "Equivalent to -C opt-level=2"), @@ -1484,6 +1485,7 @@ fn collect_print_requests( "code-models" => PrintRequest::CodeModels, "tls-models" => PrintRequest::TlsModels, "native-static-libs" => PrintRequest::NativeStaticLibs, + "stack-protector-strategies" => PrintRequest::StackProtectorStrategies, "target-spec-json" => { if dopts.unstable_options { PrintRequest::TargetSpec @@ -2414,7 +2416,9 @@ crate mod dep_tracking { use rustc_span::edition::Edition; use rustc_span::RealFileName; use rustc_target::spec::{CodeModel, MergeFunctions, PanicStrategy, RelocModel}; - use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, TargetTriple, TlsModel}; + use rustc_target::spec::{ + RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TargetTriple, TlsModel, + }; use std::collections::hash_map::DefaultHasher; use std::collections::BTreeMap; use std::hash::Hash; @@ -2488,6 +2492,7 @@ crate mod dep_tracking { Edition, LinkerPluginLto, SplitDebuginfo, + StackProtector, SwitchWithOptPath, SymbolManglingVersion, SourceFileHashAlgorithm, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 447be84b5a70a..d57b438c6e4b0 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -6,7 +6,9 @@ use crate::search_paths::SearchPath; use crate::utils::NativeLib; use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy, SanitizerSet}; -use rustc_target::spec::{RelocModel, RelroLevel, SplitDebuginfo, TargetTriple, TlsModel}; +use rustc_target::spec::{ + RelocModel, RelroLevel, SplitDebuginfo, StackProtector, TargetTriple, TlsModel, +}; use rustc_feature::UnstableFeatures; use rustc_span::edition::Edition; @@ -381,6 +383,8 @@ mod desc { 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`"; + pub const parse_stack_protector: &str = + "one of (`none` (default), `basic`, `strong`, or `all`)"; } mod parse { @@ -884,6 +888,14 @@ mod parse { } true } + + crate fn parse_stack_protector(slot: &mut StackProtector, v: Option<&str>) -> bool { + match v.and_then(|s| StackProtector::from_str(s).ok()) { + Some(ssp) => *slot = ssp, + _ => return false, + } + true + } } options! { @@ -1275,6 +1287,8 @@ options! { "exclude spans when debug-printing compiler state (default: no)"), src_hash_algorithm: Option = (None, parse_src_file_hash, [TRACKED], "hash algorithm of source files in debug info (`md5`, `sha1`, or `sha256`)"), + stack_protector: StackProtector = (StackProtector::None, parse_stack_protector, [TRACKED], + "control stack smash protection strategy (`rustc --print stack-protector-strategies` for details)"), strip: Strip = (Strip::None, parse_strip, [UNTRACKED], "tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"), split_dwarf_inlining: bool = (true, parse_bool, [UNTRACKED], diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 4471e1e0ae8b4..7eef8aba13c64 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -28,7 +28,9 @@ use rustc_span::source_map::{FileLoader, MultiSpan, RealFileLoader, SourceMap, S use rustc_span::{sym, SourceFileHashAlgorithm, Symbol}; use rustc_target::asm::InlineAsmArch; use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel}; -use rustc_target::spec::{SanitizerSet, SplitDebuginfo, Target, TargetTriple, TlsModel}; +use rustc_target::spec::{ + SanitizerSet, SplitDebuginfo, StackProtector, Target, TargetTriple, TlsModel, +}; use std::cell::{self, RefCell}; use std::env; @@ -747,6 +749,14 @@ impl Session { self.opts.cg.split_debuginfo.unwrap_or(self.target.split_debuginfo) } + pub fn stack_protector(&self) -> StackProtector { + if self.target.options.supports_stack_protector { + self.opts.debugging_opts.stack_protector + } else { + StackProtector::None + } + } + pub fn target_can_use_split_dwarf(&self) -> bool { !self.target.is_like_windows && !self.target.is_like_osx } @@ -1391,6 +1401,15 @@ fn validate_commandline_args_with_session_available(sess: &Session) { disable it using `-C target-feature=-crt-static`", ); } + + if sess.opts.debugging_opts.stack_protector != StackProtector::None { + if !sess.target.options.supports_stack_protector { + sess.warn(&format!( + "`-Z stack-protector={}` is not supported for target {} and will be ignored", + sess.opts.debugging_opts.stack_protector, sess.opts.target_triple + )) + } + } } /// Holds data on the current incremental compilation session, if there is one. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index c816d06045681..b1aea3c9ba00a 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1359,7 +1359,6 @@ symbols! { unix, unlikely, unmarked_api, - unnamed_fields, unpin, unreachable, unreachable_code, diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 273221360b8b5..0194521223ebe 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -705,6 +705,59 @@ impl ToJson for FramePointer { } } +/// Controls use of stack canaries. +#[derive(Clone, Copy, Debug, PartialEq, Hash, Eq)] +pub enum StackProtector { + /// Disable stack canary generation. + None, + + /// On LLVM, mark all generated LLVM functions with the `ssp` attribute (see + /// llvm/docs/LangRef.rst). This triggers stack canary generation in + /// functions which contain an array of a byte-sized type with more than + /// eight elements. + Basic, + + /// On LLVM, mark all generated LLVM functions with the `sspstrong` + /// attribute (see llvm/docs/LangRef.rst). This triggers stack canary + /// generation in functions which either contain an array, or which take + /// the address of a local variable. + Strong, + + /// Generate stack canaries in all functions. + All, +} + +impl StackProtector { + fn as_str(&self) -> &'static str { + match self { + StackProtector::None => "none", + StackProtector::Basic => "basic", + StackProtector::Strong => "strong", + StackProtector::All => "all", + } + } +} + +impl FromStr for StackProtector { + type Err = (); + + fn from_str(s: &str) -> Result { + Ok(match s { + "none" => StackProtector::None, + "basic" => StackProtector::Basic, + "strong" => StackProtector::Strong, + "all" => StackProtector::All, + _ => return Err(()), + }) + } +} + +impl fmt::Display for StackProtector { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self.as_str()) + } +} + macro_rules! supported_targets { ( $(($( $triple:literal, )+ $module:ident ),)+ ) => { $(mod $module;)+ @@ -1339,6 +1392,10 @@ pub struct TargetOptions { /// Minimum number of bits in #[repr(C)] enum. Defaults to 32. pub c_enum_min_bits: u64, + + /// Whether the target supports stack canary checks. `true` by default, + /// since this is most common among tier 1 and tier 2 targets. + pub supports_stack_protector: bool, } impl Default for TargetOptions { @@ -1444,6 +1501,7 @@ impl Default for TargetOptions { supported_sanitizers: SanitizerSet::empty(), default_adjusted_cabi: None, c_enum_min_bits: 32, + supports_stack_protector: true, } } } @@ -2029,6 +2087,7 @@ impl Target { key!(supported_sanitizers, SanitizerSet)?; key!(default_adjusted_cabi, Option)?; key!(c_enum_min_bits, u64); + key!(supports_stack_protector, bool); if base.is_builtin { // This can cause unfortunate ICEs later down the line. @@ -2268,6 +2327,7 @@ impl ToJson for Target { target_option_val!(split_debuginfo); target_option_val!(supported_sanitizers); target_option_val!(c_enum_min_bits); + target_option_val!(supports_stack_protector); if let Some(abi) = self.default_adjusted_cabi { d.insert("default-adjusted-cabi".to_string(), Abi::name(abi).to_json()); diff --git a/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs b/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs index 083262cf3514c..ba32a312910d8 100644 --- a/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs +++ b/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs @@ -44,6 +44,10 @@ pub fn target() -> Target { // produce kernel functions that call other kernel functions. // This behavior is not supported by PTX ISA. merge_functions: MergeFunctions::Disabled, + + // The LLVM backend does not support stack canaries for this target + supports_stack_protector: false, + ..Default::default() }, } diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 2adf6a549e641..e56b631dbaf8d 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -1916,7 +1916,8 @@ impl UnsafeCell { /// ``` #[inline(always)] #[stable(feature = "unsafe_cell_get_mut", since = "1.50.0")] - pub fn get_mut(&mut self) -> &mut T { + #[rustc_const_unstable(feature = "const_unsafecell_get_mut", issue = "88836")] + pub const fn get_mut(&mut self) -> &mut T { &mut self.value } diff --git a/src/test/assembly/stack-protector/stack-protector-heuristics-effect.rs b/src/test/assembly/stack-protector/stack-protector-heuristics-effect.rs new file mode 100644 index 0000000000000..c688006abc329 --- /dev/null +++ b/src/test/assembly/stack-protector/stack-protector-heuristics-effect.rs @@ -0,0 +1,395 @@ +// revisions: all strong basic none missing +// assembly-output: emit-asm +// ignore-windows stack check code uses different function names +// ignore-nvptx stack protector is not supported +// [all] compile-flags: -Z stack-protector=all +// [strong] compile-flags: -Z stack-protector=strong +// [basic] compile-flags: -Z stack-protector=basic +// [none] compile-flags: -Z stack-protector=none +// compile-flags: -C opt-level=2 -Z merge-functions=disabled + +#![crate_type = "lib"] + +#![allow(incomplete_features)] + +#![feature(unsized_locals, unsized_fn_params)] + + +// CHECK-LABEL: emptyfn: +#[no_mangle] +pub fn emptyfn() { + // all: __stack_chk_fail + // strong-NOT: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +// CHECK-LABEL: array_char +#[no_mangle] +pub fn array_char(f: fn(*const char)) { + let a = ['c'; 1]; + let b = ['d'; 3]; + let c = ['e'; 15]; + + f(&a as *const _); + f(&b as *const _); + f(&c as *const _); + + // Any type of local array variable leads to stack protection with the + // "strong" heuristic. The 'basic' heuristic only adds stack protection to + // functions with local array variables of a byte-sized type, however. Since + // 'char' is 4 bytes in Rust, this function is not protected by the 'basic' + // heuristic + // + // (This test *also* takes the address of the local stack variables. We + // cannot know that this isn't what triggers the `strong` heuristic. + // However, the test strategy of passing the address of a stack array to an + // external function is sufficient to trigger the `basic` heuristic (see + // test `array_u8_large()`). Since the `basic` heuristic only checks for the + // presence of stack-local array variables, we can be confident that this + // test also captures this part of the `strong` heuristic specification.) + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +// CHECK-LABEL: array_u8_1 +#[no_mangle] +pub fn array_u8_1(f: fn(*const u8)) { + let a = [0u8; 1]; + f(&a as *const _); + + // The 'strong' heuristic adds stack protection to functions with local + // array variables regardless of their size. + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +// CHECK-LABEL: array_u8_small: +#[no_mangle] +pub fn array_u8_small(f: fn(*const u8)) { + let a = [0u8; 2]; + let b = [0u8; 8]; + f(&a as *const _); + f(&b as *const _); + + // Small arrays do not lead to stack protection by the 'basic' heuristic. + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +// CHECK-LABEL: array_u8_large: +#[no_mangle] +pub fn array_u8_large(f: fn(*const u8)) { + let a = [0u8; 9]; + f(&a as *const _); + + // Since `a` is a byte array with size greater than 8, the basic heuristic + // will also protect this function. + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +#[derive(Copy, Clone)] +pub struct ByteSizedNewtype(u8); + +// CHECK-LABEL: array_bytesizednewtype_9: +#[no_mangle] +pub fn array_bytesizednewtype_9(f: fn(*const ByteSizedNewtype)) { + let a = [ByteSizedNewtype(0); 9]; + f(&a as *const _); + + // Since `a` is a byte array in the LLVM output, the basic heuristic will + // also protect this function. + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +// CHECK-LABEL: local_var_addr_used_indirectly +#[no_mangle] +pub fn local_var_addr_used_indirectly(f: fn(bool)) { + let a = 5; + let a_addr = &a as *const _ as usize; + f(a_addr & 0x10 == 0); + + // This function takes the address of a local variable taken. Although this + // address is never used as a way to refer to stack memory, the `strong` + // heuristic adds stack smash protection. This is also the case in C++: + // ``` + // cat << EOF | clang++ -O2 -fstack-protector-strong -S -x c++ - -o - | grep stack_chk + // #include + // void f(void (*g)(bool)) { + // int32_t x; + // g((reinterpret_cast(&x) & 0x10U) == 0); + // } + // EOF + // ``` + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + + +// CHECK-LABEL: local_string_addr_taken +#[no_mangle] +pub fn local_string_addr_taken(f: fn(&String)) { + let x = String::new(); + f(&x); + + // Taking the address of the local variable `x` leads to stack smash + // protection with the `strong` heuristic, but not with the `basic` + // heuristic. It does not matter that the reference is not mut. + // + // An interesting note is that a similar function in C++ *would* be + // protected by the `basic` heuristic, because `std::string` has a char + // array internally as a small object optimization: + // ``` + // cat < + // void f(void (*g)(const std::string&)) { + // std::string x; + // g(x); + // } + // EOF + // ``` + // + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +pub trait SelfByRef { + fn f(&self) -> i32; +} + +impl SelfByRef for i32 { + fn f(&self) -> i32 { + return self + 1; + } +} + +// CHECK-LABEL: local_var_addr_taken_used_locally_only +#[no_mangle] +pub fn local_var_addr_taken_used_locally_only(factory: fn() -> i32, sink: fn(i32)) { + let x = factory(); + let g = x.f(); + sink(g); + + // Even though the local variable conceptually has its address taken, as + // it's passed by reference to the trait function, the use of the reference + // is easily inlined. There is therefore no stack smash protection even with + // the `strong` heuristic. + + // all: __stack_chk_fail + // strong-NOT: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +pub struct Gigastruct { + does: u64, + not: u64, + have: u64, + array: u64, + members: u64 +} + +// CHECK-LABEL: local_large_var_moved +#[no_mangle] +pub fn local_large_var_moved(f: fn(Gigastruct)) { + let x = Gigastruct { does: 0, not: 1, have: 2, array: 3, members: 4 }; + f(x); + + // Even though the local variable conceptually doesn't have its address + // taken, it's so large that the "move" is implemented with a reference to a + // stack-local variable in the ABI. Consequently, this function *is* + // protected by the `strong` heuristic. This is also the case for + // rvalue-references in C++, regardless of struct size: + // ``` + // cat < + // #include + // void f(void (*g)(uint64_t&&)) { + // uint64_t x; + // g(std::move(x)); + // } + // EOF + // ``` + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +// CHECK-LABEL: local_large_var_cloned +#[no_mangle] +pub fn local_large_var_cloned(f: fn(Gigastruct)) { + f(Gigastruct { does: 0, not: 1, have: 2, array: 3, members: 4 }); + + // A new instance of `Gigastruct` is passed to `f()`, without any apparent + // connection to this stack frame. Still, since instances of `Gigastruct` + // are sufficiently large, it is allocated in the caller stack frame and + // passed as a pointer. As such, this function is *also* protected by the + // `strong` heuristic, just like `local_large_var_moved`. This is also the + // case for pass-by-value of sufficiently large structs in C++: + // ``` + // cat < + // #include + // struct Gigastruct { uint64_t a, b, c, d, e; }; + // void f(void (*g)(Gigastruct)) { + // g(Gigastruct{}); + // } + // EOF + // ``` + + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + + +extern "C" { + // A call to an external `alloca` function is *not* recognized as an + // `alloca(3)` operation. This function is a compiler built-in, as the + // man page explains. Clang translates it to an LLVM `alloca` + // instruction with a count argument, which is also what the LLVM stack + // protector heuristics looks for. The man page for `alloca(3)` details + // a way to avoid using the compiler built-in: pass a -std=c11 + // argument, *and* don't include . Though this leads to an + // external alloca() function being called, it doesn't lead to stack + // protection being included. It even fails with a linker error + // "undefined reference to `alloca'". Example: + // ``` + // cat< + // void * alloca(size_t); + // void f(void (*g)(void*)) { + // void * p = alloca(10); + // g(p); + // } + // int main() { return 0; } + // EOF + // ``` + // The following tests demonstrate that calls to an external `alloca` + // function in Rust also doesn't trigger stack protection. + + fn alloca(size: usize) -> *mut (); +} + +// CHECK-LABEL: alloca_small_compile_time_constant_arg +#[no_mangle] +pub fn alloca_small_compile_time_constant_arg(f: fn(*mut ())) { + f(unsafe { alloca(8) }); + + // all: __stack_chk_fail + // strong-NOT: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +// CHECK-LABEL: alloca_large_compile_time_constant_arg +#[no_mangle] +pub fn alloca_large_compile_time_constant_arg(f: fn(*mut ())) { + f(unsafe { alloca(9) }); + + // all: __stack_chk_fail + // strong-NOT: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + + +// CHECK-LABEL: alloca_dynamic_arg +#[no_mangle] +pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) { + f(unsafe { alloca(n) }); + + // all: __stack_chk_fail + // strong-NOT: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +// The question then is: in what ways can Rust code generate array-`alloca` +// LLVM instructions? This appears to only be generated by +// rustc_codegen_ssa::traits::Builder::array_alloca() through +// rustc_codegen_ssa::mir::operand::OperandValue::store_unsized(). FWICT +// this is support for the "unsized locals" unstable feature: +// https://doc.rust-lang.org/unstable-book/language-features/unsized-locals.html. + + +// CHECK-LABEL: unsized_fn_param +#[no_mangle] +pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) { + let n = if l { 1 } else { 2 }; + f(*Box::<[u8]>::from(&s[0..n])); // slice-copy with Box::from + + // Even though slices are conceptually passed by-value both into this + // function and into `f()`, this is implemented with pass-by-reference + // using a suitably constructed fat-pointer (as if the functions + // accepted &[u8]). This function therefore doesn't need dynamic array + // alloca, and is therefore not protected by the `strong` or `basic` + // heuristics. + + + // all: __stack_chk_fail + // strong-NOT: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +// CHECK-LABEL: unsized_local +#[no_mangle] +pub fn unsized_local(s: &[u8], l: bool, f: fn(&mut [u8])) { + let n = if l { 1 } else { 2 }; + let mut a: [u8] = *Box::<[u8]>::from(&s[0..n]); // slice-copy with Box::from + f(&mut a); + + // This function allocates a slice as a local variable in its stack + // frame. Since the size is not a compile-time constant, an array + // alloca is required, and the function is protected by both the + // `strong` and `basic` heuristic. + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} diff --git a/src/test/assembly/stack-protector/stack-protector-target-support.rs b/src/test/assembly/stack-protector/stack-protector-target-support.rs new file mode 100644 index 0000000000000..5ba46d082e157 --- /dev/null +++ b/src/test/assembly/stack-protector/stack-protector-target-support.rs @@ -0,0 +1,286 @@ +// Test that stack smash protection code is emitted for all tier1 and tier2 +// targets, with the exception of nvptx64-nvidia-cuda +// +// revisions: r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15 r16 r17 r18 r19 r20 r21 r22 r23 +// revisions: r24 r25 r26 r27 r28 r29 r30 r31 r32 r33 r34 r35 r36 r37 r38 r39 r40 r41 r42 r43 r44 +// revisions: r45 r46 r47 r48 r49 r50 r51 r52 r53 r54 r55 r56 r57 r58 r59 r60 r61 r62 r63 r64 r65 +// revisions: r66 r67 r68 r69 r70 r71 r72 r73 r74 r75 r76 r77 r78 r79 r80 r81 r82 r83 r84 +// assembly-output: emit-asm +// [r1] compile-flags: --target aarch64-unknown-linux-gnu +// [r1] needs-llvm-components: aarch64 +// [r2] compile-flags: --target i686-pc-windows-gnu +// [r2] needs-llvm-components: x86 +// [r3] compile-flags: --target i686-pc-windows-msvc +// [r3] needs-llvm-components: x86 +// [r4] compile-flags: --target i686-unknown-linux-gnu +// [r4] needs-llvm-components: x86 +// [r5] compile-flags: --target x86_64-apple-darwin +// [r5] needs-llvm-components: x86 +// [r6] compile-flags: --target x86_64-pc-windows-gnu +// [r6] needs-llvm-components: x86 +// [r7] compile-flags: --target x86_64-pc-windows-msvc +// [r7] needs-llvm-components: x86 +// [r8] compile-flags: --target x86_64-unknown-linux-gnu +// [r8] needs-llvm-components: x86 +// [r9] compile-flags: --target aarch64-apple-darwin +// [r9] needs-llvm-components: aarch64 +// [r10] compile-flags: --target aarch64-apple-ios +// [r10] needs-llvm-components: aarch64 +// [r11] compile-flags: --target aarch64-fuchsia +// [r11] needs-llvm-components: aarch64 +// [r12] compile-flags: --target aarch64-linux-android +// [r12] needs-llvm-components: aarch64 +// [r13] compile-flags: --target aarch64-pc-windows-msvc +// [r13] needs-llvm-components: aarch64 +// [r14] compile-flags: --target aarch64-unknown-linux-musl +// [r14] needs-llvm-components: aarch64 +// [r15] compile-flags: --target aarch64-unknown-none +// [r15] needs-llvm-components: aarch64 +// [r16] compile-flags: --target aarch64-unknown-none-softfloat +// [r16] needs-llvm-components: aarch64 +// [r17] compile-flags: --target arm-linux-androideabi +// [r17] needs-llvm-components: arm +// [r18] compile-flags: --target arm-unknown-linux-gnueabi +// [r18] needs-llvm-components: arm +// [r19] compile-flags: --target arm-unknown-linux-gnueabihf +// [r19] needs-llvm-components: arm +// [r20] compile-flags: --target arm-unknown-linux-musleabi +// [r20] needs-llvm-components: arm +// [r21] compile-flags: --target arm-unknown-linux-musleabihf +// [r21] needs-llvm-components: arm +// [r22] compile-flags: --target armebv7r-none-eabi +// [r22] needs-llvm-components: arm +// [r23] compile-flags: --target armebv7r-none-eabihf +// [r23] needs-llvm-components: arm +// [r24] compile-flags: --target armv5te-unknown-linux-gnueabi +// [r24] needs-llvm-components: arm +// [r25] compile-flags: --target armv5te-unknown-linux-musleabi +// [r25] needs-llvm-components: arm +// [r26] compile-flags: --target armv7-linux-androideabi +// [r26] needs-llvm-components: arm +// [r27] compile-flags: --target armv7a-none-eabi +// [r27] needs-llvm-components: arm +// [r28] compile-flags: --target armv7r-none-eabi +// [r28] needs-llvm-components: arm +// [r29] compile-flags: --target armv7r-none-eabihf +// [r29] needs-llvm-components: arm +// [r30] compile-flags: --target armv7-unknown-linux-gnueabi +// [r30] needs-llvm-components: arm +// [r31] compile-flags: --target armv7-unknown-linux-gnueabihf +// [r31] needs-llvm-components: arm +// [r32] compile-flags: --target armv7-unknown-linux-musleabi +// [r32] needs-llvm-components: arm +// [r33] compile-flags: --target armv7-unknown-linux-musleabihf +// [r33] needs-llvm-components: arm +// [r34] compile-flags: --target asmjs-unknown-emscripten +// [r34] needs-llvm-components: webassembly +// [r35] compile-flags: --target i586-pc-windows-msvc +// [r35] needs-llvm-components: x86 +// [r36] compile-flags: --target i586-unknown-linux-gnu +// [r36] needs-llvm-components: x86 +// [r37] compile-flags: --target i586-unknown-linux-musl +// [r37] needs-llvm-components: x86 +// [r38] compile-flags: --target i686-linux-android +// [r38] needs-llvm-components: x86 +// [r39] compile-flags: --target i686-unknown-freebsd +// [r39] needs-llvm-components: x86 +// [r40] compile-flags: --target i686-unknown-linux-musl +// [r40] needs-llvm-components: x86 +// [r41] compile-flags: --target mips-unknown-linux-gnu +// [r41] needs-llvm-components: mips +// [r42] compile-flags: --target mips-unknown-linux-musl +// [r42] needs-llvm-components: mips +// [r43] compile-flags: --target mips64-unknown-linux-gnuabi64 +// [r43] needs-llvm-components: mips +// [r44] compile-flags: --target mips64-unknown-linux-muslabi64 +// [r44] needs-llvm-components: mips +// [r45] compile-flags: --target mips64el-unknown-linux-gnuabi64 +// [r45] needs-llvm-components: mips +// [r46] compile-flags: --target mips64el-unknown-linux-muslabi64 +// [r46] needs-llvm-components: mips +// [r47] compile-flags: --target mipsel-unknown-linux-gnu +// [r47] needs-llvm-components: mips +// [r48] compile-flags: --target mipsel-unknown-linux-musl +// [r48] needs-llvm-components: mips +// [r49] compile-flags: --target nvptx64-nvidia-cuda +// [r49] needs-llvm-components: nvptx +// [r50] compile-flags: --target powerpc-unknown-linux-gnu +// [r50] needs-llvm-components: powerpc +// [r51] compile-flags: --target powerpc64-unknown-linux-gnu +// [r51] needs-llvm-components: powerpc +// [r52] compile-flags: --target powerpc64le-unknown-linux-gnu +// [r52] needs-llvm-components: powerpc +// [r53] compile-flags: --target riscv32i-unknown-none-elf +// [r53] needs-llvm-components: riscv +// [r54] compile-flags: --target riscv32imac-unknown-none-elf +// [r54] needs-llvm-components: riscv +// [r55] compile-flags:--target riscv32imc-unknown-none-elf +// [r55] needs-llvm-components: riscv +// [r56] compile-flags:--target riscv64gc-unknown-linux-gnu +// [r56] needs-llvm-components: riscv +// [r57] compile-flags:--target riscv64gc-unknown-none-elf +// [r57] needs-llvm-components: riscv +// [r58] compile-flags:--target riscv64imac-unknown-none-elf +// [r58] needs-llvm-components: riscv +// [r59] compile-flags:--target s390x-unknown-linux-gnu +// [r59] needs-llvm-components: systemz +// [r60] compile-flags:--target sparc64-unknown-linux-gnu +// [r60] needs-llvm-components: sparc +// [r61] compile-flags:--target sparcv9-sun-solaris +// [r61] needs-llvm-components: sparc +// [r62] compile-flags:--target thumbv6m-none-eabi +// [r62] needs-llvm-components: arm +// [r63] compile-flags:--target thumbv7em-none-eabi +// [r63] needs-llvm-components: arm +// [r64] compile-flags:--target thumbv7em-none-eabihf +// [r64] needs-llvm-components: arm +// [r65] compile-flags:--target thumbv7m-none-eabi +// [r65] needs-llvm-components: arm +// [r66] compile-flags:--target thumbv7neon-linux-androideabi +// [r66] needs-llvm-components: arm +// [r67] compile-flags:--target thumbv7neon-unknown-linux-gnueabihf +// [r67] needs-llvm-components: arm +// [r68] compile-flags:--target thumbv8m.base-none-eabi +// [r68] needs-llvm-components: arm +// [r69] compile-flags:--target thumbv8m.main-none-eabi +// [r69] needs-llvm-components: arm +// [r70] compile-flags:--target thumbv8m.main-none-eabihf +// [r70] needs-llvm-components: arm +// [r71] compile-flags:--target wasm32-unknown-emscripten +// [r71] needs-llvm-components: webassembly +// [r72] compile-flags:--target wasm32-unknown-unknown +// [r72] needs-llvm-components: webassembly +// [r73] compile-flags:--target wasm32-wasi +// [r73] needs-llvm-components: webassembly +// [r74] compile-flags:--target x86_64-apple-ios +// [r74] needs-llvm-components: x86 +// [r75] compile-flags:--target x86_64-fortanix-unknown-sgx +// [r75] needs-llvm-components: x86 +// [r75] min-llvm-version: 11.0.0 +// [r76] compile-flags:--target x86_64-fuchsia +// [r76] needs-llvm-components: x86 +// [r77] compile-flags:--target x86_64-linux-android +// [r77] needs-llvm-components: x86 +// [r78] compile-flags:--target x86_64-sun-solaris +// [r78] needs-llvm-components: x86 +// [r79] compile-flags:--target x86_64-unknown-freebsd +// [r79] needs-llvm-components: x86 +// [r80] compile-flags:--target x86_64-unknown-illumos +// [r80] needs-llvm-components: x86 +// [r81] compile-flags:--target x86_64-unknown-linux-gnux32 +// [r81] needs-llvm-components: x86 +// [r82] compile-flags:--target x86_64-unknown-linux-musl +// [r82] needs-llvm-components: x86 +// [r83] compile-flags:--target x86_64-unknown-netbsd +// [r83] needs-llvm-components: x86 +// [r84] compile-flags: --target x86_64-unknown-redox +// [r84] needs-llvm-components: x86 +// compile-flags: -Z stack-protector=all +// compile-flags: -C opt-level=2 + +#![crate_type = "lib"] + +#![feature(no_core, lang_items)] +#![crate_type = "lib"] +#![no_core] + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +#[no_mangle] +pub fn foo() { + // CHECK: foo{{:|()}} + + // MSVC does the stack checking within a stack-check function: + // r3: calll @__security_check_cookie + // r7: callq __security_check_cookie + // r13: bl __security_check_cookie + // r35: calll @__security_check_cookie + + // cuda doesn't support stack-smash protection + // r49-NOT: __security_check_cookie + // r49-NOT: __stack_chk_fail + + // Other targets do stack checking within the function, and call a failure function on error + // r1: __stack_chk_fail + // r2: __stack_chk_fail + // r4: __stack_chk_fail + // r5: __stack_chk_fail + // r6: __stack_chk_fail + // r8: __stack_chk_fail + // r9: __stack_chk_fail + // r10: __stack_chk_fail + // r11: __stack_chk_fail + // r12: __stack_chk_fail + // r14: __stack_chk_fail + // r15: __stack_chk_fail + // r16: __stack_chk_fail + // r17: __stack_chk_fail + // r18: __stack_chk_fail + // r19: __stack_chk_fail + // r20: __stack_chk_fail + // r21: __stack_chk_fail + // r22: __stack_chk_fail + // r23: __stack_chk_fail + // r24: __stack_chk_fail + // r25: __stack_chk_fail + // r26: __stack_chk_fail + // r27: __stack_chk_fail + // r28: __stack_chk_fail + // r29: __stack_chk_fail + // r30: __stack_chk_fail + // r31: __stack_chk_fail + // r32: __stack_chk_fail + // r33: __stack_chk_fail + // r34: __stack_chk_fail + // r36: __stack_chk_fail + // r37: __stack_chk_fail + // r38: __stack_chk_fail + // r39: __stack_chk_fail + // r40: __stack_chk_fail + // r41: __stack_chk_fail + // r42: __stack_chk_fail + // r43: __stack_chk_fail + // r44: __stack_chk_fail + // r45: __stack_chk_fail + // r46: __stack_chk_fail + // r47: __stack_chk_fail + // r48: __stack_chk_fail + // r50: __stack_chk_fail + // r51: __stack_chk_fail + // r52: __stack_chk_fail + // r53: __stack_chk_fail + // r54: __stack_chk_fail + // r55: __stack_chk_fail + // r56: __stack_chk_fail + // r57: __stack_chk_fail + // r58: __stack_chk_fail + // r59: __stack_chk_fail + // r60: __stack_chk_fail + // r61: __stack_chk_fail + // r62: __stack_chk_fail + // r63: __stack_chk_fail + // r64: __stack_chk_fail + // r65: __stack_chk_fail + // r66: __stack_chk_fail + // r67: __stack_chk_fail + // r68: __stack_chk_fail + // r69: __stack_chk_fail + // r70: __stack_chk_fail + // r71: __stack_chk_fail + // r72: __stack_chk_fail + // r73: __stack_chk_fail + // r74: __stack_chk_fail + // r75: __stack_chk_fail + // r76: __stack_chk_fail + // r77: __stack_chk_fail + // r78: __stack_chk_fail + // r79: __stack_chk_fail + // r80: __stack_chk_fail + // r81: __stack_chk_fail + // r82: __stack_chk_fail + // r83: __stack_chk_fail + // r84: __stack_chk_fail +} diff --git a/src/test/codegen/stack-protector.rs b/src/test/codegen/stack-protector.rs new file mode 100644 index 0000000000000..2198593eb57ae --- /dev/null +++ b/src/test/codegen/stack-protector.rs @@ -0,0 +1,33 @@ +// revisions: all strong basic none +// [all] compile-flags: -Z stack-protector=all +// [strong] compile-flags: -Z stack-protector=strong +// [basic] compile-flags: -Z stack-protector=basic + +#![crate_type = "lib"] + +#[no_mangle] +pub fn foo() { + // CHECK: @foo() unnamed_addr #0 + + // all-NOT: attributes #0 = { {{.*}} sspstrong {{.*}} } + // all-NOT: attributes #0 = { {{.*}} ssp {{.*}} } + // all: attributes #0 = { {{.*}} sspreq {{.*}} } + // all-NOT: attributes #0 = { {{.*}} sspstrong {{.*}} } + // all-NOT: attributes #0 = { {{.*}} ssp {{.*}} } + + // strong-NOT: attributes #0 = { {{.*}} sspreq {{.*}} } + // strong-NOT: attributes #0 = { {{.*}} ssp {{.*}} } + // strong: attributes #0 = { {{.*}} sspstrong {{.*}} } + // strong-NOT: attributes #0 = { {{.*}} sspreq {{.*}} } + // strong-NOT: attributes #0 = { {{.*}} ssp {{.*}} } + + // basic-NOT: attributes #0 = { {{.*}} sspreq {{.*}} } + // basic-NOT: attributes #0 = { {{.*}} sspstrong {{.*}} } + // basic: attributes #0 = { {{.*}} ssp {{.*}} } + // basic-NOT: attributes #0 = { {{.*}} sspreq {{.*}} } + // basic-NOT: attributes #0 = { {{.*}} sspstrong {{.*}} } + + // none-NOT: attributes #0 = { {{.*}} sspreq {{.*}} } + // none-NOT: attributes #0 = { {{.*}} sspstrong {{.*}} } + // none-NOT: attributes #0 = { {{.*}} ssp {{.*}} } +} diff --git a/src/test/pretty/anonymous-types.rs b/src/test/pretty/anonymous-types.rs deleted file mode 100644 index 5ff452e8e43c4..0000000000000 --- a/src/test/pretty/anonymous-types.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Test for issue 85480 -// Pretty print anonymous struct and union types - -// pp-exact -// pretty-compare-only - -struct Foo { - _: union { - _: struct { - a: u8, - b: u16, - }, - c: u32, - }, - d: u64, - e: f32, -} - -type A = - struct { - field: u8, - }; - -fn main() { } diff --git a/src/test/ui/abi/stack-protector.rs b/src/test/ui/abi/stack-protector.rs new file mode 100644 index 0000000000000..24bd2e2194313 --- /dev/null +++ b/src/test/ui/abi/stack-protector.rs @@ -0,0 +1,99 @@ +// run-pass +// only-x86_64-unknown-linux-gnu +// revisions: ssp no-ssp +// [ssp] compile-flags: -Z stack-protector=all +// compile-flags: -C opt-level=2 +// compile-flags: -g + +use std::env; +use std::process::{Command, ExitStatus}; + +fn main() { + if env::args().len() == 1 { + // The test is initially run without arguments. Start the process again, + // this time *with* an argument; in this configuration, the test program + // will deliberately smash the stack. + let cur_argv0 = env::current_exe().unwrap(); + let mut child = Command::new(&cur_argv0); + child.arg("stacksmash"); + + if cfg!(ssp) { + assert_stack_smash_prevented(&mut child); + } else { + assert_stack_smashed(&mut child); + } + } else { + vulnerable_function(); + // If we return here the test is broken: it should either have called + // malicious_code() which terminates the process, or be caught by the + // stack check which also terminates the process. + panic!("TEST BUG: stack smash unsuccessful"); + } +} + +// Avoid inlining to make sure the return address is pushed to stack. +#[inline(never)] +fn vulnerable_function() { + let mut x = 5usize; + let stackaddr = &mut x as *mut usize; + let bad_code_ptr = malicious_code as usize; + // Overwrite the on-stack return address with the address of `malicious_code()`, + // thereby jumping to that function when returning from `vulnerable_function()`. + unsafe { fill(stackaddr, bad_code_ptr, 20); } +} + +// Use an uninlined function with its own stack frame to make sure that we don't +// clobber e.g. the counter or address local variable. +#[inline(never)] +unsafe fn fill(addr: *mut usize, val: usize, count: usize) { + let mut addr = addr; + for _ in 0..count { + *addr = val; + addr = addr.add(1); + } +} + +// We jump to malicious_code() having wreaked havoc with the previous stack +// frame and not setting up a new one. This function is therefore constrained, +// e.g. both println!() and std::process::exit() segfaults if called. We +// therefore keep the amount of work to a minimum by calling POSIX functions +// directly. +// The function is un-inlined just to make it possible to set a breakpoint here. +#[inline(never)] +fn malicious_code() { + let msg = [112u8, 119u8, 110u8, 101u8, 100u8, 33u8, 0u8]; // "pwned!\0" ascii + unsafe { + write(1, &msg as *const u8, msg.len()); + _exit(0); + } +} +extern "C" { + fn write(fd: i32, buf: *const u8, count: usize) -> isize; + fn _exit(status: i32) -> !; +} + + +fn assert_stack_smash_prevented(cmd: &mut Command) { + let (status, stdout, stderr) = run(cmd); + assert!(!status.success()); + assert!(stdout.is_empty()); + assert!(stderr.contains("stack smashing detected")); +} + +fn assert_stack_smashed(cmd: &mut Command) { + let (status, stdout, stderr) = run(cmd); + assert!(status.success()); + assert!(stdout.contains("pwned!")); + assert!(stderr.is_empty()); +} + + +fn run(cmd: &mut Command) -> (ExitStatus, String, String) { + let output = cmd.output().unwrap(); + let stdout = String::from_utf8_lossy(&output.stdout); + let stderr = String::from_utf8_lossy(&output.stderr); + println!("status: {}", output.status); + println!("stdout: {}", stdout); + println!("stderr: {}", stderr); + (output.status, stdout.to_string(), stderr.to_string()) +} diff --git a/src/test/ui/feature-gates/feature-gate-unnamed_fields.rs b/src/test/ui/feature-gates/feature-gate-unnamed_fields.rs deleted file mode 100644 index bd815dbcc9242..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-unnamed_fields.rs +++ /dev/null @@ -1,27 +0,0 @@ -struct Foo { - foo: u8, - _: union { //~ ERROR unnamed fields are not yet fully implemented [E0658] - //~^ ERROR unnamed fields are not yet fully implemented [E0658] - //~| ERROR anonymous unions are unimplemented - bar: u8, - baz: u16 - } -} - -union Bar { - foobar: u8, - _: struct { //~ ERROR unnamed fields are not yet fully implemented [E0658] - //~^ ERROR unnamed fields are not yet fully implemented [E0658] - //~| ERROR anonymous structs are unimplemented - //~| ERROR unions may not contain fields that need dropping [E0740] - foobaz: u8, - barbaz: u16 - } -} - -struct S; -struct Baz { - _: S //~ ERROR unnamed fields are not yet fully implemented [E0658] -} - -fn main(){} diff --git a/src/test/ui/feature-gates/feature-gate-unnamed_fields.stderr b/src/test/ui/feature-gates/feature-gate-unnamed_fields.stderr deleted file mode 100644 index 4f3ab85c98792..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-unnamed_fields.stderr +++ /dev/null @@ -1,111 +0,0 @@ -error[E0658]: unnamed fields are not yet fully implemented - --> $DIR/feature-gate-unnamed_fields.rs:3:5 - | -LL | _: union { - | ^ - | - = note: see issue #49804 for more information - = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable - -error[E0658]: unnamed fields are not yet fully implemented - --> $DIR/feature-gate-unnamed_fields.rs:3:8 - | -LL | _: union { - | ________^ -LL | | -LL | | -LL | | bar: u8, -LL | | baz: u16 -LL | | } - | |_____^ - | - = note: see issue #49804 for more information - = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable - -error[E0658]: unnamed fields are not yet fully implemented - --> $DIR/feature-gate-unnamed_fields.rs:13:5 - | -LL | _: struct { - | ^ - | - = note: see issue #49804 for more information - = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable - -error[E0658]: unnamed fields are not yet fully implemented - --> $DIR/feature-gate-unnamed_fields.rs:13:8 - | -LL | _: struct { - | ________^ -LL | | -LL | | -LL | | -LL | | foobaz: u8, -LL | | barbaz: u16 -LL | | } - | |_____^ - | - = note: see issue #49804 for more information - = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable - -error[E0658]: unnamed fields are not yet fully implemented - --> $DIR/feature-gate-unnamed_fields.rs:24:5 - | -LL | _: S - | ^ - | - = note: see issue #49804 for more information - = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable - -error: anonymous unions are unimplemented - --> $DIR/feature-gate-unnamed_fields.rs:3:8 - | -LL | _: union { - | ________^ -LL | | -LL | | -LL | | bar: u8, -LL | | baz: u16 -LL | | } - | |_____^ - -error: anonymous structs are unimplemented - --> $DIR/feature-gate-unnamed_fields.rs:13:8 - | -LL | _: struct { - | ________^ -LL | | -LL | | -LL | | -LL | | foobaz: u8, -LL | | barbaz: u16 -LL | | } - | |_____^ - -error[E0740]: unions may not contain fields that need dropping - --> $DIR/feature-gate-unnamed_fields.rs:13:5 - | -LL | / _: struct { -LL | | -LL | | -LL | | -LL | | foobaz: u8, -LL | | barbaz: u16 -LL | | } - | |_____^ - | -note: `std::mem::ManuallyDrop` can be used to wrap the type - --> $DIR/feature-gate-unnamed_fields.rs:13:5 - | -LL | / _: struct { -LL | | -LL | | -LL | | -LL | | foobaz: u8, -LL | | barbaz: u16 -LL | | } - | |_____^ - -error: aborting due to 8 previous errors - -Some errors have detailed explanations: E0658, E0740. -For more information about an error, try `rustc --explain E0658`. diff --git a/src/test/ui/parser/issue-88583-union-as-ident.rs b/src/test/ui/parser/issue-88583-union-as-ident.rs new file mode 100644 index 0000000000000..b3d66d46b1d4b --- /dev/null +++ b/src/test/ui/parser/issue-88583-union-as-ident.rs @@ -0,0 +1,15 @@ +// check-pass + +#![allow(non_camel_case_types)] + +struct union; + +impl union { + pub fn new() -> Self { + union { } + } +} + +fn main() { + let _u = union::new(); +} diff --git a/src/test/ui/stack-protector/warn-stack-protector-unsupported.all.stderr b/src/test/ui/stack-protector/warn-stack-protector-unsupported.all.stderr new file mode 100644 index 0000000000000..54887715523c1 --- /dev/null +++ b/src/test/ui/stack-protector/warn-stack-protector-unsupported.all.stderr @@ -0,0 +1,4 @@ +warning: `-Z stack-protector=all` is not supported for target nvptx64-nvidia-cuda and will be ignored + +warning: 1 warning emitted + diff --git a/src/test/ui/stack-protector/warn-stack-protector-unsupported.basic.stderr b/src/test/ui/stack-protector/warn-stack-protector-unsupported.basic.stderr new file mode 100644 index 0000000000000..f7a1ee39fb9af --- /dev/null +++ b/src/test/ui/stack-protector/warn-stack-protector-unsupported.basic.stderr @@ -0,0 +1,4 @@ +warning: `-Z stack-protector=basic` is not supported for target nvptx64-nvidia-cuda and will be ignored + +warning: 1 warning emitted + diff --git a/src/test/ui/stack-protector/warn-stack-protector-unsupported.rs b/src/test/ui/stack-protector/warn-stack-protector-unsupported.rs new file mode 100644 index 0000000000000..6df5d3cd5ae1b --- /dev/null +++ b/src/test/ui/stack-protector/warn-stack-protector-unsupported.rs @@ -0,0 +1,19 @@ +// build-pass +// revisions: all strong basic +// compile-flags: --target nvptx64-nvidia-cuda +// needs-llvm-components: nvptx +// [all] compile-flags: -Z stack-protector=all +// [strong] compile-flags: -Z stack-protector=strong +// [basic] compile-flags: -Z stack-protector=basic + +#![crate_type = "lib"] +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +pub fn main(){} diff --git a/src/test/ui/stack-protector/warn-stack-protector-unsupported.strong.stderr b/src/test/ui/stack-protector/warn-stack-protector-unsupported.strong.stderr new file mode 100644 index 0000000000000..ccc2f9f2cc5b8 --- /dev/null +++ b/src/test/ui/stack-protector/warn-stack-protector-unsupported.strong.stderr @@ -0,0 +1,4 @@ +warning: `-Z stack-protector=strong` is not supported for target nvptx64-nvidia-cuda and will be ignored + +warning: 1 warning emitted + diff --git a/src/test/ui/unnamed_fields/restrict_anonymous.rs b/src/test/ui/unnamed_fields/restrict_anonymous.rs deleted file mode 100644 index 99637d1105301..0000000000000 --- a/src/test/ui/unnamed_fields/restrict_anonymous.rs +++ /dev/null @@ -1,52 +0,0 @@ -#![allow(incomplete_features)] -#![feature(unnamed_fields)] - -fn f() -> struct { field: u8 } {} //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields -//~^ ERROR anonymous structs are unimplemented - -fn f2(a: struct { field: u8 } ) {} //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields -//~^ ERROR anonymous structs are unimplemented - -union G { - field: struct { field: u8 } //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields - //~^ ERROR anonymous structs are unimplemented -} -//~| ERROR unions may not contain fields that need dropping [E0740] - -struct H { _: u8 } // Should error after hir checks - -struct I(struct { field: u8 }, u8); //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields -//~^ ERROR anonymous structs are unimplemented - -enum J { - K(struct { field: u8 }), //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields - //~^ ERROR anonymous structs are unimplemented - L { - _ : struct { field: u8 } //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields - //~^ ERROR anonymous fields are not allowed outside of structs or unions - //~| ERROR anonymous structs are unimplemented - }, - M { - _ : u8 //~ ERROR anonymous fields are not allowed outside of structs or unions - } -} - -static M: union { field: u8 } = 0; //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields -//~^ ERROR anonymous unions are unimplemented - -type N = union { field: u8 }; //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields -//~^ ERROR anonymous unions are unimplemented - -fn main() { - const O: struct { field: u8 } = 0; //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields - //~^ ERROR anonymous structs are unimplemented - - let p: [struct { field: u8 }; 1]; //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields - //~^ ERROR anonymous structs are unimplemented - - let q: (struct { field: u8 }, u8); //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields - //~^ ERROR anonymous structs are unimplemented - - let cl = || -> struct { field: u8 } {}; //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields - //~^ ERROR anonymous structs are unimplemented -} diff --git a/src/test/ui/unnamed_fields/restrict_anonymous.stderr b/src/test/ui/unnamed_fields/restrict_anonymous.stderr deleted file mode 100644 index efcf544fde4dc..0000000000000 --- a/src/test/ui/unnamed_fields/restrict_anonymous.stderr +++ /dev/null @@ -1,175 +0,0 @@ -error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous.rs:4:11 - | -LL | fn f() -> struct { field: u8 } {} - | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here - -error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous.rs:7:10 - | -LL | fn f2(a: struct { field: u8 } ) {} - | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here - -error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous.rs:11:12 - | -LL | field: struct { field: u8 } - | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here - -error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous.rs:18:10 - | -LL | struct I(struct { field: u8 }, u8); - | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here - -error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous.rs:22:7 - | -LL | K(struct { field: u8 }), - | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here - -error: anonymous fields are not allowed outside of structs or unions - --> $DIR/restrict_anonymous.rs:25:9 - | -LL | _ : struct { field: u8 } - | -^^^^^^^^^^^^^^^^^^^^^^^ - | | - | anonymous field declared here - -error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous.rs:25:13 - | -LL | _ : struct { field: u8 } - | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here - -error: anonymous fields are not allowed outside of structs or unions - --> $DIR/restrict_anonymous.rs:30:9 - | -LL | _ : u8 - | -^^^^^ - | | - | anonymous field declared here - -error: anonymous unions are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous.rs:34:11 - | -LL | static M: union { field: u8 } = 0; - | ^^^^^^^^^^^^^^^^^^^ anonymous union declared here - -error: anonymous unions are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous.rs:37:10 - | -LL | type N = union { field: u8 }; - | ^^^^^^^^^^^^^^^^^^^ anonymous union declared here - -error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous.rs:41:14 - | -LL | const O: struct { field: u8 } = 0; - | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here - -error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous.rs:44:13 - | -LL | let p: [struct { field: u8 }; 1]; - | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here - -error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous.rs:47:13 - | -LL | let q: (struct { field: u8 }, u8); - | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here - -error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous.rs:50:20 - | -LL | let cl = || -> struct { field: u8 } {}; - | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here - -error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous.rs:4:11 - | -LL | fn f() -> struct { field: u8 } {} - | ^^^^^^^^^^^^^^^^^^^^ - -error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous.rs:7:10 - | -LL | fn f2(a: struct { field: u8 } ) {} - | ^^^^^^^^^^^^^^^^^^^^ - -error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous.rs:11:12 - | -LL | field: struct { field: u8 } - | ^^^^^^^^^^^^^^^^^^^^ - -error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous.rs:18:10 - | -LL | struct I(struct { field: u8 }, u8); - | ^^^^^^^^^^^^^^^^^^^^ - -error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous.rs:22:7 - | -LL | K(struct { field: u8 }), - | ^^^^^^^^^^^^^^^^^^^^ - -error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous.rs:25:13 - | -LL | _ : struct { field: u8 } - | ^^^^^^^^^^^^^^^^^^^^ - -error: anonymous unions are unimplemented - --> $DIR/restrict_anonymous.rs:34:11 - | -LL | static M: union { field: u8 } = 0; - | ^^^^^^^^^^^^^^^^^^^ - -error: anonymous unions are unimplemented - --> $DIR/restrict_anonymous.rs:37:10 - | -LL | type N = union { field: u8 }; - | ^^^^^^^^^^^^^^^^^^^ - -error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous.rs:44:13 - | -LL | let p: [struct { field: u8 }; 1]; - | ^^^^^^^^^^^^^^^^^^^^ - -error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous.rs:47:13 - | -LL | let q: (struct { field: u8 }, u8); - | ^^^^^^^^^^^^^^^^^^^^ - -error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous.rs:50:20 - | -LL | let cl = || -> struct { field: u8 } {}; - | ^^^^^^^^^^^^^^^^^^^^ - -error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous.rs:41:14 - | -LL | const O: struct { field: u8 } = 0; - | ^^^^^^^^^^^^^^^^^^^^ - -error[E0740]: unions may not contain fields that need dropping - --> $DIR/restrict_anonymous.rs:11:5 - | -LL | field: struct { field: u8 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: `std::mem::ManuallyDrop` can be used to wrap the type - --> $DIR/restrict_anonymous.rs:11:5 - | -LL | field: struct { field: u8 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 27 previous errors - -For more information about this error, try `rustc --explain E0740`. diff --git a/src/tools/cargo b/src/tools/cargo index 18751dd3f238d..e515c3277bf06 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 18751dd3f238d94d384a7fe967abfac06cbfe0b9 +Subproject commit e515c3277bf0681bfc79a9e763861bfe26bb05db diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml index 2310370fb9fbe..40aaa5924df5b 100644 --- a/src/tools/clippy/Cargo.toml +++ b/src/tools/clippy/Cargo.toml @@ -21,37 +21,35 @@ name = "clippy-driver" path = "src/driver.rs" [dependencies] -# begin automatic update -clippy_lints = { version = "0.1.50", path = "clippy_lints" } -# end automatic update +clippy_lints = { version = "0.1", path = "clippy_lints" } semver = "0.11" -rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util" } -tempfile = { version = "3.1.0", optional = true } +rustc_tools_util = { version = "0.2", path = "rustc_tools_util" } +tempfile = { version = "3.2", optional = true } [dev-dependencies] cargo_metadata = "0.12" -compiletest_rs = { version = "0.6.0", features = ["tmp"] } +compiletest_rs = { version = "0.7", features = ["tmp"] } tester = "0.9" -regex = "1.4" +regex = "1.5" # This is used by the `collect-metadata` alias. filetime = "0.2" # A noop dependency that changes in the Rust repository, it's a bit of a hack. # See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust` # for more information. -rustc-workspace-hack = "1.0.0" +rustc-workspace-hack = "1.0" # UI test dependencies clippy_utils = { path = "clippy_utils" } derive-new = "0.5" if_chain = "1.0" -itertools = "0.10.1" -quote = "1" +itertools = "0.10" +quote = "1.0" serde = { version = "1.0", features = ["derive"] } -syn = { version = "1", features = ["full"] } +syn = { version = "1.0", features = ["full"] } [build-dependencies] -rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util" } +rustc_tools_util = { version = "0.2", path = "rustc_tools_util" } [features] deny-warnings = ["clippy_lints/deny-warnings"] diff --git a/src/tools/clippy/clippy_dev/Cargo.toml b/src/tools/clippy/clippy_dev/Cargo.toml index 0fae8c7b9afcf..d7d2655026b4b 100644 --- a/src/tools/clippy/clippy_dev/Cargo.toml +++ b/src/tools/clippy/clippy_dev/Cargo.toml @@ -6,11 +6,11 @@ edition = "2018" [dependencies] bytecount = "0.6" clap = "2.33" -itertools = "0.9" +itertools = "0.10" opener = "0.5" -regex = "1" +regex = "1.5" shell-escape = "0.1" -walkdir = "2" +walkdir = "2.3" [features] deny-warnings = [] diff --git a/src/tools/clippy/clippy_dummy/Cargo.toml b/src/tools/clippy/clippy_dummy/Cargo.toml index a1707bad5c268..c206a1eb07b50 100644 --- a/src/tools/clippy/clippy_dummy/Cargo.toml +++ b/src/tools/clippy/clippy_dummy/Cargo.toml @@ -13,4 +13,4 @@ keywords = ["clippy", "lint", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] [build-dependencies] -term = "0.6" +term = "0.7" diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml index 3c28024bf926a..e59175a55e184 100644 --- a/src/tools/clippy/clippy_lints/Cargo.toml +++ b/src/tools/clippy/clippy_lints/Cargo.toml @@ -11,21 +11,21 @@ edition = "2018" [dependencies] cargo_metadata = "0.12" clippy_utils = { path = "../clippy_utils" } -if_chain = "1.0.0" -itertools = "0.9" +if_chain = "1.0" +itertools = "0.10" pulldown-cmark = { version = "0.8", default-features = false } -quine-mc_cluskey = "0.2.2" +quine-mc_cluskey = "0.2" regex-syntax = "0.6" serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", optional = true } -toml = "0.5.3" +toml = "0.5" unicode-normalization = "0.1" -unicode-script = { version = "0.5.3", default-features = false } +unicode-script = { version = "0.5", default-features = false } semver = "0.11" -rustc-semver = "1.1.0" +rustc-semver = "1.1" # NOTE: cargo requires serde feat in its url dep # see -url = { version = "2.1.0", features = ["serde"] } +url = { version = "2.2", features = ["serde"] } [features] deny-warnings = ["clippy_utils/deny-warnings"] diff --git a/src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs b/src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs index bd5426ba707a8..162911b77d615 100644 --- a/src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs +++ b/src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs @@ -1,7 +1,5 @@ //! lint on missing cargo common metadata -use std::path::PathBuf; - use clippy_utils::{diagnostics::span_lint, is_lint_allowed}; use rustc_hir::{hir_id::CRATE_HIR_ID, Crate}; use rustc_lint::{LateContext, LateLintPass}; @@ -69,12 +67,8 @@ fn missing_warning(cx: &LateContext<'_>, package: &cargo_metadata::Package, fiel span_lint(cx, CARGO_COMMON_METADATA, DUMMY_SP, &message); } -fn is_empty_str(value: &Option) -> bool { - value.as_ref().map_or(true, String::is_empty) -} - -fn is_empty_path(value: &Option) -> bool { - value.as_ref().and_then(|x| x.to_str()).map_or(true, str::is_empty) +fn is_empty_str>(value: &Option) -> bool { + value.as_ref().map_or(true, |s| s.as_ref().is_empty()) } fn is_empty_vec(value: &[String]) -> bool { @@ -98,7 +92,7 @@ impl LateLintPass<'_> for CargoCommonMetadata { missing_warning(cx, &package, "package.description"); } - if is_empty_str(&package.license) && is_empty_path(&package.license_file) { + if is_empty_str(&package.license) && is_empty_str(&package.license_file) { missing_warning(cx, &package, "either package.license or package.license_file"); } @@ -106,7 +100,7 @@ impl LateLintPass<'_> for CargoCommonMetadata { missing_warning(cx, &package, "package.repository"); } - if is_empty_path(&package.readme) { + if is_empty_str(&package.readme) { missing_warning(cx, &package, "package.readme"); } diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml index 4c038a997952a..7c24e830e71dc 100644 --- a/src/tools/clippy/clippy_utils/Cargo.toml +++ b/src/tools/clippy/clippy_utils/Cargo.toml @@ -5,8 +5,8 @@ edition = "2018" publish = false [dependencies] -if_chain = "1.0.0" -rustc-semver="1.1.0" +if_chain = "1.0" +rustc-semver = "1.1" [features] deny-warnings = [] diff --git a/src/tools/clippy/lintcheck/Cargo.toml b/src/tools/clippy/lintcheck/Cargo.toml index ada033de6e3ab..f33f1b65eabdb 100644 --- a/src/tools/clippy/lintcheck/Cargo.toml +++ b/src/tools/clippy/lintcheck/Cargo.toml @@ -11,15 +11,15 @@ publish = false [dependencies] clap = "2.33" -flate2 = {version = "1.0.19"} -fs_extra = {version = "1.2.0"} -rayon = {version = "1.5.0"} -serde = {version = "1.0", features = ["derive"]} -serde_json = {version = "1.0"} -tar = {version = "0.4.30"} -toml = {version = "0.5"} -ureq = {version = "2.0.0-rc3"} -walkdir = {version = "2.3.2"} +flate2 = "1.0" +fs_extra = "1.2" +rayon = "1.5" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +tar = "0.4" +toml = "0.5" +ureq = "2.2" +walkdir = "2.3" [features] deny-warnings = [] diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 2483d0570d9ea..14041539b9dfd 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -6,7 +6,7 @@ use std::cmp::{max, min, Ordering}; use regex::Regex; use rustc_ast::visit; use rustc_ast::{ast, ptr}; -use rustc_span::{symbol, BytePos, Span}; +use rustc_span::{symbol, BytePos, Span, DUMMY_SP}; use crate::attr::filter_inline_attrs; use crate::comment::{ @@ -31,7 +31,12 @@ use crate::stmt::Stmt; use crate::utils::*; use crate::vertical::rewrite_with_alignment; use crate::visitor::FmtVisitor; -use crate::DEFAULT_VISIBILITY; + +const DEFAULT_VISIBILITY: ast::Visibility = ast::Visibility { + kind: ast::VisibilityKind::Inherited, + span: DUMMY_SP, + tokens: None, +}; fn type_annotation_separator(config: &Config) -> &str { colon_spaces(config) @@ -972,7 +977,7 @@ impl<'a> StructParts<'a> { format_header(context, self.prefix, self.ident, self.vis, offset) } - pub(crate) fn from_variant(variant: &'a ast::Variant) -> Self { + fn from_variant(variant: &'a ast::Variant) -> Self { StructParts { prefix: "", ident: variant.ident, diff --git a/src/tools/rustfmt/src/lib.rs b/src/tools/rustfmt/src/lib.rs index 206d2f782909c..47a7b9d4dbe3c 100644 --- a/src/tools/rustfmt/src/lib.rs +++ b/src/tools/rustfmt/src/lib.rs @@ -32,7 +32,7 @@ use std::path::PathBuf; use std::rc::Rc; use rustc_ast::ast; -use rustc_span::{symbol, DUMMY_SP}; +use rustc_span::symbol; use thiserror::Error; use crate::comment::LineClasses; @@ -96,11 +96,6 @@ mod types; mod vertical; pub(crate) mod visitor; -const DEFAULT_VISIBILITY: ast::Visibility = ast::Visibility { - kind: ast::VisibilityKind::Inherited, - span: DUMMY_SP, - tokens: None, -}; /// The various errors that can occur during formatting. Note that not all of /// these can currently be propagated to clients. #[derive(Error, Debug)] diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index 640d127e86098..76bf58e875b1f 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -1,15 +1,15 @@ use std::iter::ExactSizeIterator; use std::ops::Deref; -use rustc_ast::ast::{self, AttrVec, FnRetTy, Mutability}; -use rustc_span::{symbol::kw, symbol::Ident, BytePos, Pos, Span}; +use rustc_ast::ast::{self, FnRetTy, Mutability}; +use rustc_span::{symbol::kw, BytePos, Pos, Span}; +use crate::comment::{combine_strs_with_missing_comments, contains_comment}; use crate::config::lists::*; use crate::config::{IndentStyle, TypeDensity, Version}; use crate::expr::{ format_expr, rewrite_assign_rhs, rewrite_call, rewrite_tuple, rewrite_unary_prefix, ExprType, }; -use crate::items::StructParts; use crate::lists::{ definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, }; @@ -24,11 +24,6 @@ use crate::utils::{ colon_spaces, extra_offset, first_line_width, format_extern, format_mutability, last_line_extendable, last_line_width, mk_sp, rewrite_ident, }; -use crate::DEFAULT_VISIBILITY; -use crate::{ - comment::{combine_strs_with_missing_comments, contains_comment}, - items::format_struct_struct, -}; #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub(crate) enum PathContext { @@ -769,54 +764,6 @@ impl Rewrite for ast::Ty { ast::TyKind::Tup(ref items) => { rewrite_tuple(context, items.iter(), self.span, shape, items.len() == 1) } - ast::TyKind::AnonymousStruct(ref fields, recovered) => { - let ident = Ident::new( - kw::Struct, - mk_sp(self.span.lo(), self.span.lo() + BytePos(6)), - ); - let data = ast::VariantData::Struct(fields.clone(), recovered); - let variant = ast::Variant { - attrs: AttrVec::new(), - id: self.id, - span: self.span, - vis: DEFAULT_VISIBILITY, - ident, - data, - disr_expr: None, - is_placeholder: false, - }; - format_struct_struct( - &context, - &StructParts::from_variant(&variant), - fields, - shape.indent, - None, - ) - } - ast::TyKind::AnonymousUnion(ref fields, recovered) => { - let ident = Ident::new( - kw::Union, - mk_sp(self.span.lo(), self.span.lo() + BytePos(5)), - ); - let data = ast::VariantData::Struct(fields.clone(), recovered); - let variant = ast::Variant { - attrs: AttrVec::new(), - id: self.id, - span: self.span, - vis: DEFAULT_VISIBILITY, - ident, - data, - disr_expr: None, - is_placeholder: false, - }; - format_struct_struct( - &context, - &StructParts::from_variant(&variant), - fields, - shape.indent, - None, - ) - } ast::TyKind::Path(ref q_self, ref path) => { rewrite_path(context, PathContext::Type, q_self.as_ref(), path, shape) }