diff --git a/Cargo.lock b/Cargo.lock index 07ee10deee519..4f1a5ca35fa00 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1966,6 +1966,10 @@ dependencies = [ "walkdir", ] +[[package]] +name = "lld-wrapper" +version = "0.1.0" + [[package]] name = "lock_api" version = "0.4.1" diff --git a/Cargo.toml b/Cargo.toml index dedfe45aca49b..626f9ae9bd29f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,6 +35,7 @@ members = [ "src/tools/expand-yaml-anchors", "src/tools/jsondocck", "src/tools/html-checker", + "src/tools/lld-wrapper", ] exclude = [ diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 30bc4edd7e69c..038d31e7c98ae 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -1,11 +1,11 @@ use rustc_ast as ast; use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor}; use rustc_ast::{AssocTyConstraint, AssocTyConstraintKind, NodeId}; -use rustc_ast::{PatKind, RangeEnd}; +use rustc_ast::{PatKind, RangeEnd, VariantData}; use rustc_errors::struct_span_err; use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP}; use rustc_feature::{Features, GateIssue}; -use rustc_session::parse::feature_err_issue; +use rustc_session::parse::{feature_err, feature_err_issue}; use rustc_session::Session; use rustc_span::source_map::Spanned; use rustc_span::symbol::sym; @@ -218,6 +218,46 @@ impl<'a> PostExpansionVisitor<'a> { } } + fn maybe_report_invalid_custom_discriminants(&self, variants: &[ast::Variant]) { + let has_fields = variants.iter().any(|variant| match variant.data { + VariantData::Tuple(..) | VariantData::Struct(..) => true, + VariantData::Unit(..) => false, + }); + + let discriminant_spans = variants + .iter() + .filter(|variant| match variant.data { + VariantData::Tuple(..) | VariantData::Struct(..) => false, + VariantData::Unit(..) => true, + }) + .filter_map(|variant| variant.disr_expr.as_ref().map(|c| c.value.span)) + .collect::>(); + + if !discriminant_spans.is_empty() && has_fields { + let mut err = feature_err( + &self.sess.parse_sess, + sym::arbitrary_enum_discriminant, + discriminant_spans.clone(), + "custom discriminant values are not allowed in enums with tuple or struct variants", + ); + for sp in discriminant_spans { + err.span_label(sp, "disallowed custom discriminant"); + } + for variant in variants.iter() { + match &variant.data { + VariantData::Struct(..) => { + err.span_label(variant.span, "struct variant defined here"); + } + VariantData::Tuple(..) => { + err.span_label(variant.span, "tuple variant defined here"); + } + VariantData::Unit(..) => {} + } + } + err.emit(); + } + } + fn check_gat(&self, generics: &ast::Generics, span: Span) { if !generics.params.is_empty() { gate_feature_post!( @@ -362,6 +402,26 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } + ast::ItemKind::Enum(ast::EnumDef { ref variants, .. }, ..) => { + for variant in variants { + match (&variant.data, &variant.disr_expr) { + (ast::VariantData::Unit(..), _) => {} + (_, Some(disr_expr)) => gate_feature_post!( + &self, + arbitrary_enum_discriminant, + disr_expr.value.span, + "discriminants on non-unit variants are experimental" + ), + _ => {} + } + } + + let has_feature = self.features.arbitrary_enum_discriminant; + if !has_feature && !i.span.allows_unstable(sym::arbitrary_enum_discriminant) { + self.maybe_report_invalid_custom_discriminants(&variants); + } + } + ast::ItemKind::Impl(box ast::ImplKind { polarity, defaultness, ref of_trait, .. }) => { diff --git a/compiler/rustc_builtin_macros/src/assert.rs b/compiler/rustc_builtin_macros/src/assert.rs index 93ba54da3424e..1e2646e4d348f 100644 --- a/compiler/rustc_builtin_macros/src/assert.rs +++ b/compiler/rustc_builtin_macros/src/assert.rs @@ -1,10 +1,10 @@ -use rustc_errors::{Applicability, DiagnosticBuilder}; - +use crate::panic::use_panic_2021; use rustc_ast::ptr::P; use rustc_ast::token; use rustc_ast::tokenstream::{DelimSpan, TokenStream}; use rustc_ast::{self as ast, *}; use rustc_ast_pretty::pprust; +use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_expand::base::*; use rustc_parse::parser::Parser; use rustc_span::symbol::{sym, Ident, Symbol}; @@ -28,7 +28,7 @@ pub fn expand_assert<'cx>( let sp = cx.with_call_site_ctxt(span); let panic_call = if let Some(tokens) = custom_message { - let path = if span.rust_2021() { + let path = if use_panic_2021(span) { // On edition 2021, we always call `$crate::panic::panic_2021!()`. Path { span: sp, diff --git a/compiler/rustc_builtin_macros/src/panic.rs b/compiler/rustc_builtin_macros/src/panic.rs index 6f5962d435c33..54ab596bf3eb8 100644 --- a/compiler/rustc_builtin_macros/src/panic.rs +++ b/compiler/rustc_builtin_macros/src/panic.rs @@ -2,6 +2,7 @@ use rustc_ast::ptr::P; use rustc_ast::tokenstream::{DelimSpan, TokenStream}; use rustc_ast::*; use rustc_expand::base::*; +use rustc_span::edition::Edition; use rustc_span::symbol::sym; use rustc_span::Span; @@ -19,7 +20,7 @@ pub fn expand_panic<'cx>( sp: Span, tts: TokenStream, ) -> Box { - let panic = if sp.rust_2021() { sym::panic_2021 } else { sym::panic_2015 }; + let panic = if use_panic_2021(sp) { sym::panic_2021 } else { sym::panic_2015 }; let sp = cx.with_call_site_ctxt(sp); @@ -46,3 +47,19 @@ pub fn expand_panic<'cx>( ), ) } + +pub fn use_panic_2021(mut span: Span) -> bool { + // To determine the editon, we check the first span up the expansion + // stack that does not have #[allow_internal_unstable(edition_panic)]. + // (To avoid using the edition of e.g. the assert!() or debug_assert!() definition.) + loop { + let expn = span.ctxt().outer_expn_data(); + if let Some(features) = expn.allow_internal_unstable { + if features.iter().any(|&f| f == sym::edition_panic) { + span = expn.call_site; + continue; + } + } + break expn.edition >= Edition::Edition2021; + } +} diff --git a/compiler/rustc_codegen_cranelift/src/vtable.rs b/compiler/rustc_codegen_cranelift/src/vtable.rs index f97d416b66f9f..36b3725ef42bc 100644 --- a/compiler/rustc_codegen_cranelift/src/vtable.rs +++ b/compiler/rustc_codegen_cranelift/src/vtable.rs @@ -68,7 +68,7 @@ pub(crate) fn get_vtable<'tcx>( ty: Ty<'tcx>, trait_ref: Option>, ) -> Value { - let alloc_id = fx.tcx.vtable_allocation(ty, trait_ref); + let alloc_id = fx.tcx.vtable_allocation((ty, trait_ref)); let data_id = data_id_for_alloc_id(&mut fx.constants_cx, &mut *fx.module, alloc_id, Mutability::Not); let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func); diff --git a/compiler/rustc_codegen_ssa/src/meth.rs b/compiler/rustc_codegen_ssa/src/meth.rs index efeec5b728413..3267d3206f73f 100644 --- a/compiler/rustc_codegen_ssa/src/meth.rs +++ b/compiler/rustc_codegen_ssa/src/meth.rs @@ -72,7 +72,7 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>( return val; } - let vtable_alloc_id = tcx.vtable_allocation(ty, trait_ref); + let vtable_alloc_id = tcx.vtable_allocation((ty, trait_ref)); let vtable_allocation = tcx.global_alloc(vtable_alloc_id).unwrap_memory(); let vtable_const = cx.const_data_from_alloc(vtable_allocation); let align = cx.data_layout().pointer_align.abi; diff --git a/compiler/rustc_error_codes/src/error_codes/E0732.md b/compiler/rustc_error_codes/src/error_codes/E0732.md index 9536fdbf0df87..7347e6654c5b3 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0732.md +++ b/compiler/rustc_error_codes/src/error_codes/E0732.md @@ -3,6 +3,8 @@ An `enum` with a discriminant must specify a `#[repr(inttype)]`. Erroneous code example: ```compile_fail,E0732 +#![feature(arbitrary_enum_discriminant)] + enum Enum { // error! Unit = 1, Tuple() = 2, @@ -18,6 +20,8 @@ is a well-defined way to extract a variant's discriminant from a value; for instance: ``` +#![feature(arbitrary_enum_discriminant)] + #[repr(u8)] enum Enum { Unit = 3, diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 725f8b8763af1..f557a4c97c7f4 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -289,13 +289,11 @@ declare_features! ( (accepted, member_constraints, "1.54.0", Some(61997), None), /// Allows bindings in the subpattern of a binding pattern. /// For example, you can write `x @ Some(y)`. - (accepted, bindings_after_at, "1.54.0", Some(65490), None), + (accepted, bindings_after_at, "1.56.0", Some(65490), None), /// Allows calling `transmute` in const fn (accepted, const_fn_transmute, "1.56.0", Some(53605), None), /// Allows accessing fields of unions inside `const` functions. (accepted, const_fn_union, "1.56.0", Some(51909), None), - /// Allows explicit discriminants on non-unit enum variants. - (accepted, arbitrary_enum_discriminant, "1.56.0", Some(60553), None), // ------------------------------------------------------------------------- // feature-group-end: accepted features diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index d409746584274..743c40ce05ace 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -468,6 +468,9 @@ declare_features! ( /// Allows #[repr(transparent)] on unions (RFC 2645). (active, transparent_unions, "1.37.0", Some(60405), None), + /// Allows explicit discriminants on non-unit enum variants. + (active, arbitrary_enum_discriminant, "1.37.0", Some(60553), None), + /// Allows `async || body` closures. (active, async_closure, "1.37.0", Some(62290), None), diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index dada94edc95ff..ed32bb16d474a 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1006,6 +1006,13 @@ rustc_queries! { key.1, key.0 } } + query vtable_allocation(key: (Ty<'tcx>, Option>)) -> mir::interpret::AllocId { + desc { |tcx| "vtable const allocation for <{} as {}>", + key.0, + key.1.map(|trait_ref| format!("{}", trait_ref)).unwrap_or("_".to_owned()) + } + } + query codegen_fulfill_obligation( key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) ) -> Result, ErrorReported> { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index de7c6d9e09530..4def27e42de25 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -10,7 +10,7 @@ use crate::middle; use crate::middle::cstore::EncodedMetadata; use crate::middle::resolve_lifetime::{self, LifetimeScopeForPath, ObjectLifetimeDefault}; use crate::middle::stability; -use crate::mir::interpret::{self, AllocId, Allocation, ConstValue, Scalar}; +use crate::mir::interpret::{self, Allocation, ConstValue, Scalar}; use crate::mir::{Body, Field, Local, Place, PlaceElem, ProjectionKind, Promoted}; use crate::thir::Thir; use crate::traits; @@ -1062,9 +1062,6 @@ pub struct GlobalCtxt<'tcx> { layout_interner: ShardedHashMap<&'tcx Layout, ()>, output_filenames: Arc, - - pub(super) vtables_cache: - Lock, Option>), AllocId>>, } impl<'tcx> TyCtxt<'tcx> { @@ -1212,7 +1209,6 @@ impl<'tcx> TyCtxt<'tcx> { const_stability_interner: Default::default(), alloc_map: Lock::new(interpret::AllocMap::new()), output_filenames: Arc::new(output_filenames), - vtables_cache: Default::default(), } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index d01ca27b85118..1bb9a86110cf6 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2046,6 +2046,7 @@ pub fn provide(providers: &mut ty::query::Providers) { trait_impls_of: trait_def::trait_impls_of_provider, type_uninhabited_from: inhabitedness::type_uninhabited_from, const_param_default: consts::const_param_default, + vtable_allocation: vtable::vtable_allocation_provider, ..*providers }; } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index db4a1d94d1a7c..18b52badd0bbe 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2177,6 +2177,7 @@ forward_display_to_print! { // because `for<'tcx>` isn't possible yet. ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>, ty::Binder<'tcx, ty::TraitRef<'tcx>>, + ty::Binder<'tcx, ty::ExistentialTraitRef<'tcx>>, ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, ty::Binder<'tcx, ty::FnSig<'tcx>>, ty::Binder<'tcx, ty::TraitPredicate<'tcx>>, diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs index 5904f133e78c3..f766cad2b3d21 100644 --- a/compiler/rustc_middle/src/ty/vtable.rs +++ b/compiler/rustc_middle/src/ty/vtable.rs @@ -43,85 +43,72 @@ pub const COMMON_VTABLE_ENTRIES_DROPINPLACE: usize = 0; pub const COMMON_VTABLE_ENTRIES_SIZE: usize = 1; pub const COMMON_VTABLE_ENTRIES_ALIGN: usize = 2; -impl<'tcx> TyCtxt<'tcx> { - /// Retrieves an allocation that represents the contents of a vtable. - /// There's a cache within `TyCtxt` so it will be deduplicated. - pub fn vtable_allocation( - self, - ty: Ty<'tcx>, - poly_trait_ref: Option>, - ) -> AllocId { - let tcx = self; - let vtables_cache = tcx.vtables_cache.lock(); - if let Some(alloc_id) = vtables_cache.get(&(ty, poly_trait_ref)).cloned() { - return alloc_id; - } - drop(vtables_cache); - - let vtable_entries = if let Some(poly_trait_ref) = poly_trait_ref { - let trait_ref = poly_trait_ref.with_self_ty(tcx, ty); - let trait_ref = tcx.erase_regions(trait_ref); +/// Retrieves an allocation that represents the contents of a vtable. +/// Since this is a query, allocations are cached and not duplicated. +pub(super) fn vtable_allocation_provider<'tcx>( + tcx: TyCtxt<'tcx>, + key: (Ty<'tcx>, Option>), +) -> AllocId { + let (ty, poly_trait_ref) = key; - tcx.vtable_entries(trait_ref) - } else { - COMMON_VTABLE_ENTRIES - }; + let vtable_entries = if let Some(poly_trait_ref) = poly_trait_ref { + let trait_ref = poly_trait_ref.with_self_ty(tcx, ty); + let trait_ref = tcx.erase_regions(trait_ref); - let layout = tcx - .layout_of(ty::ParamEnv::reveal_all().and(ty)) - .expect("failed to build vtable representation"); - assert!(!layout.is_unsized(), "can't create a vtable for an unsized type"); - let size = layout.size.bytes(); - let align = layout.align.abi.bytes(); + tcx.vtable_entries(trait_ref) + } else { + COMMON_VTABLE_ENTRIES + }; - let ptr_size = tcx.data_layout.pointer_size; - let ptr_align = tcx.data_layout.pointer_align.abi; + let layout = tcx + .layout_of(ty::ParamEnv::reveal_all().and(ty)) + .expect("failed to build vtable representation"); + assert!(!layout.is_unsized(), "can't create a vtable for an unsized type"); + let size = layout.size.bytes(); + let align = layout.align.abi.bytes(); - let vtable_size = ptr_size * u64::try_from(vtable_entries.len()).unwrap(); - let mut vtable = - Allocation::uninit(vtable_size, ptr_align, /* panic_on_fail */ true).unwrap(); + let ptr_size = tcx.data_layout.pointer_size; + let ptr_align = tcx.data_layout.pointer_align.abi; - // No need to do any alignment checks on the memory accesses below, because we know the - // allocation is correctly aligned as we created it above. Also we're only offsetting by - // multiples of `ptr_align`, which means that it will stay aligned to `ptr_align`. + let vtable_size = ptr_size * u64::try_from(vtable_entries.len()).unwrap(); + let mut vtable = Allocation::uninit(vtable_size, ptr_align, /* panic_on_fail */ true).unwrap(); - for (idx, entry) in vtable_entries.iter().enumerate() { - let idx: u64 = u64::try_from(idx).unwrap(); - let scalar = match entry { - VtblEntry::MetadataDropInPlace => { - let instance = ty::Instance::resolve_drop_in_place(tcx, ty); - let fn_alloc_id = tcx.create_fn_alloc(instance); - let fn_ptr = Pointer::from(fn_alloc_id); - ScalarMaybeUninit::from_pointer(fn_ptr, &tcx) - } - VtblEntry::MetadataSize => Scalar::from_uint(size, ptr_size).into(), - VtblEntry::MetadataAlign => Scalar::from_uint(align, ptr_size).into(), - VtblEntry::Vacant => continue, - VtblEntry::Method(instance) => { - // Prepare the fn ptr we write into the vtable. - let instance = instance.polymorphize(tcx); - let fn_alloc_id = tcx.create_fn_alloc(instance); - let fn_ptr = Pointer::from(fn_alloc_id); - ScalarMaybeUninit::from_pointer(fn_ptr, &tcx) - } - VtblEntry::TraitVPtr(trait_ref) => { - let super_trait_ref = trait_ref.map_bound(|trait_ref| { - ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref) - }); - let supertrait_alloc_id = self.vtable_allocation(ty, Some(super_trait_ref)); - let vptr = Pointer::from(supertrait_alloc_id); - ScalarMaybeUninit::from_pointer(vptr, &tcx) - } - }; - vtable - .write_scalar(&tcx, alloc_range(ptr_size * idx, ptr_size), scalar) - .expect("failed to build vtable representation"); - } + // No need to do any alignment checks on the memory accesses below, because we know the + // allocation is correctly aligned as we created it above. Also we're only offsetting by + // multiples of `ptr_align`, which means that it will stay aligned to `ptr_align`. - vtable.mutability = Mutability::Not; - let alloc_id = tcx.create_memory_alloc(tcx.intern_const_alloc(vtable)); - let mut vtables_cache = self.vtables_cache.lock(); - vtables_cache.insert((ty, poly_trait_ref), alloc_id); - alloc_id + for (idx, entry) in vtable_entries.iter().enumerate() { + let idx: u64 = u64::try_from(idx).unwrap(); + let scalar = match entry { + VtblEntry::MetadataDropInPlace => { + let instance = ty::Instance::resolve_drop_in_place(tcx, ty); + let fn_alloc_id = tcx.create_fn_alloc(instance); + let fn_ptr = Pointer::from(fn_alloc_id); + ScalarMaybeUninit::from_pointer(fn_ptr, &tcx) + } + VtblEntry::MetadataSize => Scalar::from_uint(size, ptr_size).into(), + VtblEntry::MetadataAlign => Scalar::from_uint(align, ptr_size).into(), + VtblEntry::Vacant => continue, + VtblEntry::Method(instance) => { + // Prepare the fn ptr we write into the vtable. + let instance = instance.polymorphize(tcx); + let fn_alloc_id = tcx.create_fn_alloc(instance); + let fn_ptr = Pointer::from(fn_alloc_id); + ScalarMaybeUninit::from_pointer(fn_ptr, &tcx) + } + VtblEntry::TraitVPtr(trait_ref) => { + let super_trait_ref = trait_ref + .map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)); + let supertrait_alloc_id = tcx.vtable_allocation((ty, Some(super_trait_ref))); + let vptr = Pointer::from(supertrait_alloc_id); + ScalarMaybeUninit::from_pointer(vptr, &tcx) + } + }; + vtable + .write_scalar(&tcx, alloc_range(ptr_size * idx, ptr_size), scalar) + .expect("failed to build vtable representation"); } + + vtable.mutability = Mutability::Not; + tcx.create_memory_alloc(tcx.intern_const_alloc(vtable)) } diff --git a/compiler/rustc_mir/src/interpret/traits.rs b/compiler/rustc_mir/src/interpret/traits.rs index a6ba00ec6952e..131674decc961 100644 --- a/compiler/rustc_mir/src/interpret/traits.rs +++ b/compiler/rustc_mir/src/interpret/traits.rs @@ -30,7 +30,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ensure_monomorphic_enough(*self.tcx, ty)?; ensure_monomorphic_enough(*self.tcx, poly_trait_ref)?; - let vtable_allocation = self.tcx.vtable_allocation(ty, poly_trait_ref); + let vtable_allocation = self.tcx.vtable_allocation((ty, poly_trait_ref)); let vtable_ptr = self.memory.global_base_pointer(Pointer::from(vtable_allocation))?; diff --git a/compiler/rustc_mir/src/transform/simplify_try.rs b/compiler/rustc_mir/src/transform/simplify_try.rs index 7c35dab694f3c..9c3055c6796d2 100644 --- a/compiler/rustc_mir/src/transform/simplify_try.rs +++ b/compiler/rustc_mir/src/transform/simplify_try.rs @@ -544,6 +544,12 @@ pub struct SimplifyBranchSame; impl<'tcx> MirPass<'tcx> for SimplifyBranchSame { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + // This optimization is disabled by default for now due to + // soundness concerns; see issue #89485 and PR #89489. + if !tcx.sess.opts.debugging_opts.unsound_mir_opts { + return; + } + trace!("Running SimplifyBranchSame on {:?}", body.source); let finder = SimplifyBranchSameOptimizationFinder { body, tcx }; let opts = finder.find(); @@ -706,12 +712,24 @@ impl<'a, 'tcx> SimplifyBranchSameOptimizationFinder<'a, 'tcx> { let helper = |rhs: &Rvalue<'tcx>, place: &Place<'tcx>, variant_index: &VariantIdx, + switch_value: u128, side_to_choose| { let place_type = place.ty(self.body, self.tcx).ty; let adt = match *place_type.kind() { ty::Adt(adt, _) if adt.is_enum() => adt, _ => return StatementEquality::NotEqual, }; + // We need to make sure that the switch value that targets the bb with + // SetDiscriminant is the same as the variant discriminant. + let variant_discr = adt.discriminant_for_variant(self.tcx, *variant_index).val; + if variant_discr != switch_value { + trace!( + "NO: variant discriminant {} does not equal switch value {}", + variant_discr, + switch_value + ); + return StatementEquality::NotEqual; + } let variant_is_fieldless = adt.variants[*variant_index].fields.is_empty(); if !variant_is_fieldless { trace!("NO: variant {:?} was not fieldless", variant_index); @@ -740,20 +758,28 @@ impl<'a, 'tcx> SimplifyBranchSameOptimizationFinder<'a, 'tcx> { ( StatementKind::Assign(box (_, rhs)), StatementKind::SetDiscriminant { place, variant_index }, - ) - // we need to make sure that the switch value that targets the bb with SetDiscriminant (y), is the same as the variant index - if Some(variant_index.index() as u128) == y_target_and_value.value => { + ) if y_target_and_value.value.is_some() => { // choose basic block of x, as that has the assign - helper(rhs, place, variant_index, x_target_and_value.target) + helper( + rhs, + place, + variant_index, + y_target_and_value.value.unwrap(), + x_target_and_value.target, + ) } ( StatementKind::SetDiscriminant { place, variant_index }, StatementKind::Assign(box (_, rhs)), - ) - // we need to make sure that the switch value that targets the bb with SetDiscriminant (x), is the same as the variant index - if Some(variant_index.index() as u128) == x_target_and_value.value => { + ) if x_target_and_value.value.is_some() => { // choose basic block of y, as that has the assign - helper(rhs, place, variant_index, y_target_and_value.target) + helper( + rhs, + place, + variant_index, + x_target_and_value.value.unwrap(), + y_target_and_value.target, + ) } _ => { trace!("NO: statements `{:?}` and `{:?}` not considered equal", x, y); diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs index c973eae6b0665..ad621d66cde13 100644 --- a/compiler/rustc_query_impl/src/keys.rs +++ b/compiler/rustc_query_impl/src/keys.rs @@ -72,6 +72,17 @@ impl<'tcx> Key for mir::interpret::GlobalId<'tcx> { } } +impl<'tcx> Key for (Ty<'tcx>, Option>) { + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true + } + + fn default_span(&self, _: TyCtxt<'_>) -> Span { + DUMMY_SP + } +} + impl<'tcx> Key for mir::interpret::LitToConstInput<'tcx> { #[inline(always)] fn query_crate_is_local(&self) -> bool { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 675c5108720bb..5150900e9d83a 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -558,6 +558,7 @@ symbols! { dyn_metadata, dyn_trait, edition_macro_pats, + edition_panic, eh_catch_typeinfo, eh_personality, emit_enum, diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 3c9d5b4def4e7..8a91738a2c5ae 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -1391,7 +1391,7 @@ fn check_enum<'tcx>( } } - if tcx.adt_def(def_id).repr.int.is_none() { + if tcx.adt_def(def_id).repr.int.is_none() && tcx.features().arbitrary_enum_discriminant { let is_unit = |var: &hir::Variant<'_>| matches!(var.data, hir::VariantData::Unit(..)); let has_disr = |var: &hir::Variant<'_>| var.disr_expr.is_some(); diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index 917bf4ecd8c4a..524cda3d09be9 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -65,6 +65,7 @@ use std::iter; enum PlaceAncestryRelation { Ancestor, Descendant, + SamePlace, Divergent, } @@ -565,7 +566,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for possible_ancestor in min_cap_list.iter_mut() { match determine_place_ancestry_relation(&place, &possible_ancestor.place) { // current place is descendant of possible_ancestor - PlaceAncestryRelation::Descendant => { + PlaceAncestryRelation::Descendant | PlaceAncestryRelation::SamePlace => { ancestor_found = true; let backup_path_expr_id = possible_ancestor.info.path_expr_id; @@ -2303,15 +2304,17 @@ fn determine_place_ancestry_relation( let projections_b = &place_b.projections; let same_initial_projections = - iter::zip(projections_a, projections_b).all(|(proj_a, proj_b)| proj_a == proj_b); + iter::zip(projections_a, projections_b).all(|(proj_a, proj_b)| proj_a.kind == proj_b.kind); if same_initial_projections { + use std::cmp::Ordering; + // First min(n, m) projections are the same // Select Ancestor/Descendant - if projections_b.len() >= projections_a.len() { - PlaceAncestryRelation::Ancestor - } else { - PlaceAncestryRelation::Descendant + match projections_b.len().cmp(&projections_a.len()) { + Ordering::Greater => PlaceAncestryRelation::Ancestor, + Ordering::Equal => PlaceAncestryRelation::SamePlace, + Ordering::Less => PlaceAncestryRelation::Descendant, } } else { PlaceAncestryRelation::Divergent diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 41277b22da0e0..26a9ce6807aed 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -776,29 +776,31 @@ fn infer_placeholder_type<'a>( // us to improve in typeck so we do that now. match tcx.sess.diagnostic().steal_diagnostic(span, StashKey::ItemNoType) { Some(mut err) => { - // The parser provided a sub-optimal `HasPlaceholders` suggestion for the type. - // We are typeck and have the real type, so remove that and suggest the actual type. - err.suggestions.clear(); - - // Suggesting unnameable types won't help. - let mut mk_nameable = MakeNameable::new(tcx); - let ty = mk_nameable.fold_ty(ty); - let sugg_ty = if mk_nameable.success { Some(ty) } else { None }; - if let Some(sugg_ty) = sugg_ty { - err.span_suggestion( - span, - &format!("provide a type for the {item}", item = kind), - format!("{}: {}", item_ident, sugg_ty), - Applicability::MachineApplicable, - ); - } else { - err.span_note( - tcx.hir().body(body_id).value.span, - &format!("however, the inferred type `{}` cannot be named", ty.to_string()), - ); + if !ty.references_error() { + // The parser provided a sub-optimal `HasPlaceholders` suggestion for the type. + // We are typeck and have the real type, so remove that and suggest the actual type. + err.suggestions.clear(); + + // Suggesting unnameable types won't help. + let mut mk_nameable = MakeNameable::new(tcx); + let ty = mk_nameable.fold_ty(ty); + let sugg_ty = if mk_nameable.success { Some(ty) } else { None }; + if let Some(sugg_ty) = sugg_ty { + err.span_suggestion( + span, + &format!("provide a type for the {item}", item = kind), + format!("{}: {}", item_ident, sugg_ty), + Applicability::MachineApplicable, + ); + } else { + err.span_note( + tcx.hir().body(body_id).value.span, + &format!("however, the inferred type `{}` cannot be named", ty.to_string()), + ); + } } - err.emit_unless(ty.references_error()); + err.emit(); } None => { let mut diag = bad_placeholder_type(tcx, vec![span], kind); diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs index ba70006fe96b3..b5c4d6ac26167 100644 --- a/compiler/rustc_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_typeck/src/expr_use_visitor.rs @@ -619,6 +619,8 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { if let Some(hir::Guard::If(ref e)) = arm.guard { self.consume_expr(e) + } else if let Some(hir::Guard::IfLet(_, ref e)) = arm.guard { + self.consume_expr(e) } self.consume_expr(&arm.body); diff --git a/library/core/src/iter/adapters/intersperse.rs b/library/core/src/iter/adapters/intersperse.rs index bd21872e1ad4b..d8bbd424cf258 100644 --- a/library/core/src/iter/adapters/intersperse.rs +++ b/library/core/src/iter/adapters/intersperse.rs @@ -4,7 +4,7 @@ use super::Peekable; /// /// This `struct` is created by [`Iterator::intersperse`]. See its documentation /// for more information. -#[stable(feature = "iter_intersperse", since = "1.56.0")] +#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] #[derive(Debug, Clone)] pub struct Intersperse where @@ -24,7 +24,7 @@ where } } -#[stable(feature = "iter_intersperse", since = "1.56.0")] +#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] impl Iterator for Intersperse where I: Iterator, @@ -61,7 +61,7 @@ where /// /// This `struct` is created by [`Iterator::intersperse_with`]. See its /// documentation for more information. -#[stable(feature = "iter_intersperse", since = "1.56.0")] +#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] pub struct IntersperseWith where I: Iterator, @@ -71,7 +71,7 @@ where needs_sep: bool, } -#[stable(feature = "iter_intersperse", since = "1.56.0")] +#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] impl crate::fmt::Debug for IntersperseWith where I: Iterator + crate::fmt::Debug, @@ -87,7 +87,7 @@ where } } -#[stable(feature = "iter_intersperse", since = "1.56.0")] +#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] impl crate::clone::Clone for IntersperseWith where I: Iterator + crate::clone::Clone, @@ -113,7 +113,7 @@ where } } -#[stable(feature = "iter_intersperse", since = "1.56.0")] +#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] impl Iterator for IntersperseWith where I: Iterator, diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index f02d278aff5e4..056ccca1d01c9 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -42,7 +42,7 @@ pub use self::flatten::Flatten; #[stable(feature = "iter_copied", since = "1.36.0")] pub use self::copied::Copied; -#[stable(feature = "iter_intersperse", since = "1.56.0")] +#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] pub use self::intersperse::{Intersperse, IntersperseWith}; #[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")] diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index cd8a26025ffb6..7fb80f954ff40 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -414,7 +414,7 @@ pub use self::adapters::{ Chain, Cycle, Enumerate, Filter, FilterMap, FlatMap, Fuse, Inspect, Map, Peekable, Rev, Scan, Skip, SkipWhile, Take, TakeWhile, Zip, }; -#[stable(feature = "iter_intersperse", since = "1.56.0")] +#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] pub use self::adapters::{Intersperse, IntersperseWith}; pub(crate) use self::adapters::process_results; diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 330d3714247c5..850435b53cc7e 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -535,6 +535,8 @@ pub trait Iterator { /// Basic usage: /// /// ``` + /// #![feature(iter_intersperse)] + /// /// let mut a = [0, 1, 2].iter().intersperse(&100); /// assert_eq!(a.next(), Some(&0)); // The first element from `a`. /// assert_eq!(a.next(), Some(&100)); // The separator. @@ -545,8 +547,9 @@ pub trait Iterator { /// ``` /// /// `intersperse` can be very useful to join an iterator's items using a common element: - /// /// ``` + /// #![feature(iter_intersperse)] + /// /// let hello = ["Hello", "World", "!"].iter().copied().intersperse(" ").collect::(); /// assert_eq!(hello, "Hello World !"); /// ``` @@ -554,7 +557,7 @@ pub trait Iterator { /// [`Clone`]: crate::clone::Clone /// [`intersperse_with`]: Iterator::intersperse_with #[inline] - #[stable(feature = "iter_intersperse", since = "1.56.0")] + #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] fn intersperse(self, separator: Self::Item) -> Intersperse where Self: Sized, @@ -579,6 +582,8 @@ pub trait Iterator { /// Basic usage: /// /// ``` + /// #![feature(iter_intersperse)] + /// /// #[derive(PartialEq, Debug)] /// struct NotClone(usize); /// @@ -595,8 +600,9 @@ pub trait Iterator { /// /// `intersperse_with` can be used in situations where the separator needs /// to be computed: - /// /// ``` + /// #![feature(iter_intersperse)] + /// /// let src = ["Hello", "to", "all", "people", "!!"].iter().copied(); /// /// // The closure mutably borrows its context to generate an item. @@ -609,7 +615,7 @@ pub trait Iterator { /// [`Clone`]: crate::clone::Clone /// [`intersperse`]: Iterator::intersperse #[inline] - #[stable(feature = "iter_intersperse", since = "1.56.0")] + #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] fn intersperse_with(self, separator: G) -> IntersperseWith where Self: Sized, diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index a3a074ac131af..6f94e945d7b59 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -210,6 +210,7 @@ pub macro assert_matches { #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "debug_assert_macro"] +#[allow_internal_unstable(edition_panic)] macro_rules! debug_assert { ($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert!($($arg)*); }) } diff --git a/library/core/src/task/mod.rs b/library/core/src/task/mod.rs index 5f077f77bbc9f..3d6f4f5971a62 100644 --- a/library/core/src/task/mod.rs +++ b/library/core/src/task/mod.rs @@ -11,5 +11,5 @@ mod wake; pub use self::wake::{Context, RawWaker, RawWakerVTable, Waker}; mod ready; -#[stable(feature = "ready_macro", since = "1.56.0")] +#[unstable(feature = "ready_macro", issue = "70922")] pub use ready::ready; diff --git a/library/core/src/task/ready.rs b/library/core/src/task/ready.rs index 2834ca5fe2224..8fd6560a5180b 100644 --- a/library/core/src/task/ready.rs +++ b/library/core/src/task/ready.rs @@ -8,6 +8,8 @@ /// # Examples /// /// ``` +/// #![feature(ready_macro)] +/// /// use std::task::{ready, Context, Poll}; /// use std::future::{self, Future}; /// use std::pin::Pin; @@ -27,6 +29,7 @@ /// The `ready!` call expands to: /// /// ``` +/// # #![feature(ready_macro)] /// # use std::task::{Context, Poll}; /// # use std::future::{self, Future}; /// # use std::pin::Pin; @@ -45,7 +48,7 @@ /// # Poll::Ready(()) /// # } /// ``` -#[stable(feature = "ready_macro", since = "1.56.0")] +#[unstable(feature = "ready_macro", issue = "70922")] #[rustc_macro_transparency = "semitransparent"] pub macro ready($e:expr) { match $e { diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 19bcc45108dfd..1cf6e1d9176a3 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -48,6 +48,7 @@ #![feature(int_log)] #![feature(iter_advance_by)] #![feature(iter_partition_in_place)] +#![feature(iter_intersperse)] #![feature(iter_is_partitioned)] #![feature(iter_order_by)] #![feature(iter_map_while)] diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index df9e9bce41527..d5cc81b1cdcc2 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -1137,14 +1137,14 @@ impl Step for Assemble { // 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)), - ); - builder.copy( - &lld_install.join("bin").join(&src_exe), - &gcc_ld_dir.join(exe("ld64", target_compiler.host)), - ); + for flavor in ["ld", "ld64"] { + let lld_wrapper_exe = builder.ensure(crate::tool::LldWrapper { + compiler: build_compiler, + target: target_compiler.host, + flavor_feature: flavor, + }); + builder.copy(&lld_wrapper_exe, &gcc_ld_dir.join(exe(flavor, 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 7c1bb1a91481b..d4875cfe1b066 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -409,11 +409,14 @@ impl Step for Rustc { let rust_lld = exe("rust-lld", compiler.host); builder.copy(&src_dir.join(&rust_lld), &dst_dir.join(&rust_lld)); // 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(&rust_lld), &gcc_lld_dir.join(exe("ld", compiler.host))); - builder - .copy(&src_dir.join(&rust_lld), &gcc_lld_dir.join(exe("ld64", compiler.host))); + let gcc_lld_src_dir = src_dir.join("gcc-ld"); + let gcc_lld_dst_dir = dst_dir.join("gcc-ld"); + t!(fs::create_dir(&gcc_lld_dst_dir)); + for flavor in ["ld", "ld64"] { + let exe_name = exe(flavor, compiler.host); + builder + .copy(&gcc_lld_src_dir.join(&exe_name), &gcc_lld_dst_dir.join(&exe_name)); + } } // Copy over llvm-dwp if it's there diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index f5e3f61dcc88f..365ba9f8dfee0 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -663,6 +663,38 @@ impl Step for Cargo { } } +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct LldWrapper { + pub compiler: Compiler, + pub target: TargetSelection, + pub flavor_feature: &'static str, +} + +impl Step for LldWrapper { + type Output = PathBuf; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.never() + } + + fn run(self, builder: &Builder<'_>) -> PathBuf { + let src_exe = builder + .ensure(ToolBuild { + compiler: self.compiler, + target: self.target, + tool: "lld-wrapper", + mode: Mode::ToolStd, + path: "src/tools/lld-wrapper", + is_optional_tool: false, + source_type: SourceType::InTree, + extra_features: vec![self.flavor_feature.to_owned()], + }) + .expect("expected to build -- essential tool"); + + src_exe + } +} + macro_rules! tool_extended { (($sel:ident, $builder:ident), $($name:ident, diff --git a/src/ci/docker/host-x86_64/dist-aarch64-linux/aarch64-linux-gnu.config b/src/ci/docker/host-x86_64/dist-aarch64-linux/aarch64-linux-gnu.config index 3d30ee49022d8..416fa50374fe4 100644 --- a/src/ci/docker/host-x86_64/dist-aarch64-linux/aarch64-linux-gnu.config +++ b/src/ci/docker/host-x86_64/dist-aarch64-linux/aarch64-linux-gnu.config @@ -37,7 +37,8 @@ CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y # CT_FORCE_DOWNLOAD is not set CT_CONNECT_TIMEOUT=10 # CT_ONLY_DOWNLOAD is not set -# CT_USE_MIRROR is not set +CT_USE_MIRROR=y +CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc" # # Extracting diff --git a/src/ci/docker/host-x86_64/dist-arm-linux/arm-linux-gnueabi.config b/src/ci/docker/host-x86_64/dist-arm-linux/arm-linux-gnueabi.config index acdf9a0e04185..e047db92652c2 100644 --- a/src/ci/docker/host-x86_64/dist-arm-linux/arm-linux-gnueabi.config +++ b/src/ci/docker/host-x86_64/dist-arm-linux/arm-linux-gnueabi.config @@ -611,7 +611,7 @@ CT_ISL_V_0_20=y # CT_ISL_V_0_15 is not set # CT_ISL_NO_VERSIONS is not set CT_ISL_VERSION="0.20" -CT_ISL_MIRRORS="http://isl.gforge.inria.fr" +CT_ISL_MIRRORS="https://ci-mirrors.rust-lang.org/rustc" CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}" CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz" diff --git a/src/ci/docker/host-x86_64/dist-arm-linux/build-toolchains.sh b/src/ci/docker/host-x86_64/dist-arm-linux/build-toolchains.sh index 3fd882521999a..ad53ba4dd1bc0 100755 --- a/src/ci/docker/host-x86_64/dist-arm-linux/build-toolchains.sh +++ b/src/ci/docker/host-x86_64/dist-arm-linux/build-toolchains.sh @@ -22,7 +22,8 @@ exit 1 mkdir build cd build cp ../arm-linux-gnueabi.config .config -ct-ng oldconfig +# FIXME ct-ng oldconfig is not working as intended. +# ct-ng oldconfig hide_output ct-ng build cd .. rm -rf build diff --git a/src/ci/docker/host-x86_64/dist-armhf-linux/arm-linux-gnueabihf.config b/src/ci/docker/host-x86_64/dist-armhf-linux/arm-linux-gnueabihf.config index 69f86663ec21b..e0f6417793de8 100644 --- a/src/ci/docker/host-x86_64/dist-armhf-linux/arm-linux-gnueabihf.config +++ b/src/ci/docker/host-x86_64/dist-armhf-linux/arm-linux-gnueabihf.config @@ -14,6 +14,7 @@ CT_CONFIGURE_has_autoconf_2_65_or_newer=y CT_CONFIGURE_has_autoreconf_2_65_or_newer=y CT_CONFIGURE_has_automake_1_15_or_newer=y CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y +CT_CONFIGURE_has_python_3_4_or_newer=y CT_CONFIGURE_has_bison_2_7_or_newer=y CT_CONFIGURE_has_python=y CT_CONFIGURE_has_git=y @@ -132,12 +133,6 @@ CT_ARCH_ARM=y # CT_ARCH_XTENSA is not set CT_ARCH="arm" CT_ARCH_CHOICE_KSYM="ARM" -# CT_ARCH_ALPHA_EV4 is not set -# CT_ARCH_ALPHA_EV45 is not set -# CT_ARCH_ALPHA_EV5 is not set -# CT_ARCH_ALPHA_EV56 is not set -# CT_ARCH_ALPHA_EV6 is not set -# CT_ARCH_ALPHA_EV67 is not set CT_ARCH_CPU="" CT_ARCH_TUNE="" CT_ARCH_ARM_SHOW=y @@ -372,8 +367,6 @@ CT_ALL_BINUTILS_CHOICES="BINUTILS" # C-library # CT_LIBC_GLIBC=y -# CT_LIBC_NEWLIB is not set -# CT_LIBC_NONE is not set # CT_LIBC_UCLIBC is not set CT_LIBC="glibc" CT_LIBC_CHOICE_KSYM="GLIBC" @@ -390,6 +383,7 @@ CT_GLIBC_USE="GLIBC" CT_GLIBC_PKG_NAME="glibc" CT_GLIBC_SRC_RELEASE=y CT_GLIBC_PATCH_ORDER="global" +# CT_GLIBC_V_2_29 is not set # CT_GLIBC_V_2_28 is not set # CT_GLIBC_V_2_27 is not set # CT_GLIBC_V_2_26 is not set @@ -408,7 +402,6 @@ CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz" CT_GLIBC_SIGNATURE_FORMAT="packed/.sig" CT_GLIBC_2_29_or_older=y CT_GLIBC_older_than_2_29=y -CT_GLIBC_REQUIRE_older_than_2_29=y CT_GLIBC_2_27_or_older=y CT_GLIBC_older_than_2_27=y CT_GLIBC_2_26_or_older=y @@ -448,12 +441,6 @@ CT_GLIBC_FORCE_UNWIND=y CT_GLIBC_KERNEL_VERSION_AS_HEADERS=y # CT_GLIBC_KERNEL_VERSION_CHOSEN is not set CT_GLIBC_MIN_KERNEL="3.2.101" -# CT_GLIBC_SSP_DEFAULT is not set -# CT_GLIBC_SSP_NO is not set -# CT_GLIBC_SSP_YES is not set -# CT_GLIBC_SSP_ALL is not set -# CT_GLIBC_SSP_STRONG is not set -# CT_NEWLIB_USE_REDHAT is not set CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC" CT_LIBC_SUPPORT_THREADS_ANY=y CT_LIBC_SUPPORT_THREADS_NATIVE=y @@ -625,7 +612,7 @@ CT_ISL_V_0_20=y # CT_ISL_V_0_15 is not set # CT_ISL_NO_VERSIONS is not set CT_ISL_VERSION="0.20" -CT_ISL_MIRRORS="http://isl.gforge.inria.fr" +CT_ISL_MIRRORS="https://ci-mirrors.rust-lang.org/rustc" CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}" CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz" diff --git a/src/ci/docker/host-x86_64/dist-armhf-linux/build-toolchains.sh b/src/ci/docker/host-x86_64/dist-armhf-linux/build-toolchains.sh index f425efd6057c6..6b5374422a62a 100755 --- a/src/ci/docker/host-x86_64/dist-armhf-linux/build-toolchains.sh +++ b/src/ci/docker/host-x86_64/dist-armhf-linux/build-toolchains.sh @@ -22,7 +22,8 @@ exit 1 mkdir build cd build cp ../arm-linux-gnueabihf.config .config -ct-ng oldconfig +# FIXME ct-ng oldconfig is not working as intended. +# ct-ng oldconfig hide_output ct-ng build cd .. rm -rf build diff --git a/src/ci/docker/host-x86_64/dist-armv7-linux/armv7-linux-gnueabihf.config b/src/ci/docker/host-x86_64/dist-armv7-linux/armv7-linux-gnueabihf.config index e3d032fc7e8fc..2d8167f1f3328 100644 --- a/src/ci/docker/host-x86_64/dist-armv7-linux/armv7-linux-gnueabihf.config +++ b/src/ci/docker/host-x86_64/dist-armv7-linux/armv7-linux-gnueabihf.config @@ -17,8 +17,6 @@ CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y CT_CONFIGURE_has_python_3_4_or_newer=y CT_CONFIGURE_has_bison_2_7_or_newer=y CT_CONFIGURE_has_python=y -CT_CONFIGURE_has_dtc=y -CT_CONFIGURE_has_svn=y CT_CONFIGURE_has_git=y CT_CONFIGURE_has_md5sum=y CT_CONFIGURE_has_sha1sum=y @@ -612,7 +610,7 @@ CT_ISL_V_0_20=y # CT_ISL_V_0_15 is not set # CT_ISL_NO_VERSIONS is not set CT_ISL_VERSION="0.20" -CT_ISL_MIRRORS="http://isl.gforge.inria.fr" +CT_ISL_MIRRORS="https://ci-mirrors.rust-lang.org/rustc" CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}" CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz" diff --git a/src/ci/docker/host-x86_64/dist-armv7-linux/build-toolchains.sh b/src/ci/docker/host-x86_64/dist-armv7-linux/build-toolchains.sh index 17dda2dbd1680..602ad8ac87737 100755 --- a/src/ci/docker/host-x86_64/dist-armv7-linux/build-toolchains.sh +++ b/src/ci/docker/host-x86_64/dist-armv7-linux/build-toolchains.sh @@ -22,7 +22,8 @@ exit 1 mkdir build cd build cp ../armv7-linux-gnueabihf.config .config -ct-ng oldconfig +# FIXME ct-ng oldconfig is not working as intended. +# ct-ng oldconfig hide_output ct-ng build cd .. rm -rf build diff --git a/src/ci/docker/host-x86_64/dist-powerpc-linux/powerpc-linux-gnu.config b/src/ci/docker/host-x86_64/dist-powerpc-linux/powerpc-linux-gnu.config index b358dce3cdfe8..814e1fa16f87d 100644 --- a/src/ci/docker/host-x86_64/dist-powerpc-linux/powerpc-linux-gnu.config +++ b/src/ci/docker/host-x86_64/dist-powerpc-linux/powerpc-linux-gnu.config @@ -37,7 +37,8 @@ CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y # CT_FORCE_DOWNLOAD is not set CT_CONNECT_TIMEOUT=10 # CT_ONLY_DOWNLOAD is not set -# CT_USE_MIRROR is not set +CT_USE_MIRROR=y +CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc" # # Extracting diff --git a/src/ci/docker/host-x86_64/dist-powerpc64-linux/powerpc64-linux-gnu.config b/src/ci/docker/host-x86_64/dist-powerpc64-linux/powerpc64-linux-gnu.config index aa13119d50c19..83439bb81e23d 100644 --- a/src/ci/docker/host-x86_64/dist-powerpc64-linux/powerpc64-linux-gnu.config +++ b/src/ci/docker/host-x86_64/dist-powerpc64-linux/powerpc64-linux-gnu.config @@ -37,7 +37,8 @@ CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y # CT_FORCE_DOWNLOAD is not set CT_CONNECT_TIMEOUT=10 # CT_ONLY_DOWNLOAD is not set -# CT_USE_MIRROR is not set +CT_USE_MIRROR=y +CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc" # # Extracting diff --git a/src/ci/docker/host-x86_64/dist-riscv64-linux/riscv64-unknown-linux-gnu.config b/src/ci/docker/host-x86_64/dist-riscv64-linux/riscv64-unknown-linux-gnu.config index 45d5ff756cdca..7400a8a038d0c 100644 --- a/src/ci/docker/host-x86_64/dist-riscv64-linux/riscv64-unknown-linux-gnu.config +++ b/src/ci/docker/host-x86_64/dist-riscv64-linux/riscv64-unknown-linux-gnu.config @@ -722,7 +722,7 @@ CT_ISL_V_0_20=y # CT_ISL_V_0_15 is not set # CT_ISL_NO_VERSIONS is not set CT_ISL_VERSION="0.20" -CT_ISL_MIRRORS="http://isl.gforge.inria.fr" +CT_ISL_MIRRORS="https://ci-mirrors.rust-lang.org/rustc" CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}" CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz" diff --git a/src/ci/docker/host-x86_64/dist-s390x-linux/s390x-linux-gnu.config b/src/ci/docker/host-x86_64/dist-s390x-linux/s390x-linux-gnu.config index c9c141afad131..2e995b2c0bdfd 100644 --- a/src/ci/docker/host-x86_64/dist-s390x-linux/s390x-linux-gnu.config +++ b/src/ci/docker/host-x86_64/dist-s390x-linux/s390x-linux-gnu.config @@ -37,7 +37,8 @@ CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y # CT_FORCE_DOWNLOAD is not set CT_CONNECT_TIMEOUT=10 # CT_ONLY_DOWNLOAD is not set -# CT_USE_MIRROR is not set +CT_USE_MIRROR=y +CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc" # # Extracting diff --git a/src/doc/unstable-book/src/language-features/arbitrary-enum-discriminant.md b/src/doc/unstable-book/src/language-features/arbitrary-enum-discriminant.md new file mode 100644 index 0000000000000..e0bb782270e22 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/arbitrary-enum-discriminant.md @@ -0,0 +1,37 @@ +# `arbitrary_enum_discriminant` + +The tracking issue for this feature is: [#60553] + +[#60553]: https://github.com/rust-lang/rust/issues/60553 + +------------------------ + +The `arbitrary_enum_discriminant` feature permits tuple-like and +struct-like enum variants with `#[repr()]` to have explicit discriminants. + +## Examples + +```rust +#![feature(arbitrary_enum_discriminant)] + +#[allow(dead_code)] +#[repr(u8)] +enum Enum { + Unit = 3, + Tuple(u16) = 2, + Struct { + a: u8, + b: u16, + } = 1, +} + +impl Enum { + fn tag(&self) -> u8 { + unsafe { *(self as *const Self as *const u8) } + } +} + +assert_eq!(3, Enum::Unit.tag()); +assert_eq!(2, Enum::Tuple(5).tag()); +assert_eq!(1, Enum::Struct{a: 7, b: 11}.tag()); +``` diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index b81acd1a93fc2..de32e31ca872f 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -13,6 +13,7 @@ #![feature(never_type)] #![feature(once_cell)] #![feature(type_ascription)] +#![feature(iter_intersperse)] #![recursion_limit = "256"] #![warn(rustc::internal)] diff --git a/src/test/incremental/reorder_vtable.rs b/src/test/incremental/reorder_vtable.rs new file mode 100644 index 0000000000000..8dacba63351ef --- /dev/null +++ b/src/test/incremental/reorder_vtable.rs @@ -0,0 +1,41 @@ +// revisions:rpass1 rpass2 + +// This test case makes sure re-order the methods in a vtable will +// trigger recompilation of codegen units that instantiate it. +// +// See https://github.com/rust-lang/rust/issues/89598 + +trait Foo { + #[cfg(rpass1)] + fn method1(&self) -> u32; + + fn method2(&self) -> u32; + + #[cfg(rpass2)] + fn method1(&self) -> u32; +} + +impl Foo for u32 { + fn method1(&self) -> u32 { 17 } + fn method2(&self) -> u32 { 42 } +} + +fn main() { + // Before #89598 was fixed, the vtable allocation would be cached during + // a MIR optimization pass and then the codegen pass for the main object + // file would not register a dependency on it (because of the missing + // dep-tracking). + // + // In the rpass2 session, the main object file would not be re-compiled, + // thus the mod1::foo(x) call would pass in an outdated vtable, while the + // mod1 object would expect the new, re-ordered vtable, resulting in a + // call to the wrong method. + let x: &dyn Foo = &0u32; + assert_eq!(mod1::foo(x), 17); +} + +mod mod1 { + pub(super) fn foo(x: &dyn super::Foo) -> u32 { + x.method1() + } +} diff --git a/src/test/ui/closures/2229_closure_analysis/issue-88118-2.rs b/src/test/ui/closures/2229_closure_analysis/issue-88118-2.rs new file mode 100644 index 0000000000000..0cfb1a55bf27f --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/issue-88118-2.rs @@ -0,0 +1,24 @@ +// edition:2021 +// run-pass +#![feature(if_let_guard)] +#[allow(unused_must_use)] +#[allow(dead_code)] + +fn print_error_count(registry: &Registry) { + |x: &Registry| { + match &x { + Registry if let _ = registry.try_find_description() => { } + //~^ WARNING: irrefutable `if let` guard pattern + _ => {} + } + }; +} + +struct Registry; +impl Registry { + pub fn try_find_description(&self) { + unimplemented!() + } +} + +fn main() {} diff --git a/src/test/ui/closures/2229_closure_analysis/issue-88118-2.stderr b/src/test/ui/closures/2229_closure_analysis/issue-88118-2.stderr new file mode 100644 index 0000000000000..15689023d818a --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/issue-88118-2.stderr @@ -0,0 +1,12 @@ +warning: irrefutable `if let` guard pattern + --> $DIR/issue-88118-2.rs:10:29 + | +LL | Registry if let _ = registry.try_find_description() => { } + | ^ + | + = note: `#[warn(irrefutable_let_patterns)]` on by default + = note: this pattern will always match, so the guard is useless + = help: consider removing the guard and adding a `let` inside the match arm + +warning: 1 warning emitted + diff --git a/src/test/ui/closures/2229_closure_analysis/issue-89606.rs b/src/test/ui/closures/2229_closure_analysis/issue-89606.rs new file mode 100644 index 0000000000000..1bb6aa40f06fa --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/issue-89606.rs @@ -0,0 +1,40 @@ +// Regression test for #89606. Used to ICE. +// +// check-pass +// revisions: twenty_eighteen twenty_twentyone +// [twenty_eighteen]compile-flags: --edition 2018 +// [twenty_twentyone]compile-flags: --edition 2021 + +struct S<'a>(Option<&'a mut i32>); + +fn by_ref(s: &mut S<'_>) { + (|| { + let S(_o) = s; + s.0 = None; + })(); +} + +fn by_value(s: S<'_>) { + (|| { + let S(ref _o) = s; + let _g = s.0; + })(); +} + +struct V<'a>((Option<&'a mut i32>,)); + +fn nested(v: &mut V<'_>) { + (|| { + let V((_o,)) = v; + v.0 = (None, ); + })(); +} + +fn main() { + let mut s = S(None); + by_ref(&mut s); + by_value(s); + + let mut v = V((None, )); + nested(&mut v); +} diff --git a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.rs b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.rs index a6e5f70fdefa6..4da7b5ab24b29 100644 --- a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.rs +++ b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.rs @@ -1,4 +1,5 @@ #![crate_type="lib"] +#![feature(arbitrary_enum_discriminant)] enum Enum { //~^ ERROR `#[repr(inttype)]` must be specified diff --git a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr index 7af063c591d56..2db5372da0c6e 100644 --- a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr +++ b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr @@ -1,5 +1,5 @@ error[E0732]: `#[repr(inttype)]` must be specified - --> $DIR/arbitrary_enum_discriminant-no-repr.rs:3:1 + --> $DIR/arbitrary_enum_discriminant-no-repr.rs:4:1 | LL | / enum Enum { LL | | diff --git a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs index 360bddb7bd1e4..f2270602d87eb 100644 --- a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs +++ b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs @@ -1,5 +1,5 @@ // run-pass -#![feature(const_raw_ptr_deref, test)] +#![feature(arbitrary_enum_discriminant, const_raw_ptr_deref, test)] extern crate test; diff --git a/src/test/ui/enum-discriminant/discriminant_value.rs b/src/test/ui/enum-discriminant/discriminant_value.rs index 7ed1d9660a69c..eb60aaf4b2d04 100644 --- a/src/test/ui/enum-discriminant/discriminant_value.rs +++ b/src/test/ui/enum-discriminant/discriminant_value.rs @@ -1,6 +1,6 @@ // run-pass #![allow(stable_features)] -#![feature(core, core_intrinsics)] +#![feature(arbitrary_enum_discriminant, core, core_intrinsics)] extern crate core; use core::intrinsics::discriminant_value; diff --git a/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.rs b/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.rs new file mode 100644 index 0000000000000..3e90af4d36af3 --- /dev/null +++ b/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.rs @@ -0,0 +1,10 @@ +#![crate_type="lib"] + +enum Enum { + Unit = 1, + //~^ ERROR custom discriminant values are not allowed in enums with tuple or struct variants + Tuple() = 2, + //~^ ERROR discriminants on non-unit variants are experimental + Struct{} = 3, + //~^ ERROR discriminants on non-unit variants are experimental +} diff --git a/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.stderr b/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.stderr new file mode 100644 index 0000000000000..b5f61e6e991d8 --- /dev/null +++ b/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.stderr @@ -0,0 +1,36 @@ +error[E0658]: discriminants on non-unit variants are experimental + --> $DIR/feature-gate-arbitrary_enum_discriminant.rs:6:13 + | +LL | Tuple() = 2, + | ^ + | + = note: see issue #60553 for more information + = help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable + +error[E0658]: discriminants on non-unit variants are experimental + --> $DIR/feature-gate-arbitrary_enum_discriminant.rs:8:14 + | +LL | Struct{} = 3, + | ^ + | + = note: see issue #60553 for more information + = help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable + +error[E0658]: custom discriminant values are not allowed in enums with tuple or struct variants + --> $DIR/feature-gate-arbitrary_enum_discriminant.rs:4:10 + | +LL | Unit = 1, + | ^ disallowed custom discriminant +LL | +LL | Tuple() = 2, + | ----------- tuple variant defined here +LL | +LL | Struct{} = 3, + | ------------ struct variant defined here + | + = note: see issue #60553 for more information + = help: add `#![feature(arbitrary_enum_discriminant)]` 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/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs b/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs index ad9fcc25b4127..f927dd189038a 100644 --- a/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs +++ b/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs @@ -1,4 +1,4 @@ -#![feature(core_intrinsics)] +#![feature(arbitrary_enum_discriminant, core_intrinsics)] extern crate core; use core::intrinsics::discriminant_value; diff --git a/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs index 42a062239d34a..e62582fb5161a 100644 --- a/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs +++ b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs @@ -1,4 +1,4 @@ -#![feature(core_intrinsics)] +#![feature(arbitrary_enum_discriminant, core_intrinsics)] extern crate core; use core::intrinsics::discriminant_value; diff --git a/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs b/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs index 3adac7b72621c..ae389e1146645 100644 --- a/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs +++ b/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs @@ -1,5 +1,5 @@ // run-pass -#![feature(repr128)] +#![feature(repr128, arbitrary_enum_discriminant)] //~^ WARN the feature `repr128` is incomplete #[derive(PartialEq, Debug)] diff --git a/src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr b/src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr index 04fb13f37a006..5bf6ea56ebc77 100644 --- a/src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr +++ b/src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr @@ -1,7 +1,7 @@ warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-70509-partial_eq.rs:2:12 | -LL | #![feature(repr128)] +LL | #![feature(repr128, arbitrary_enum_discriminant)] | ^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default diff --git a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs index 88ef8182f0238..72c0d7913e525 100644 --- a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs +++ b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs @@ -5,7 +5,7 @@ // This test checks panic emitted from `mem::{uninitialized,zeroed}`. -#![feature(never_type)] +#![feature(never_type, arbitrary_enum_discriminant)] #![allow(deprecated, invalid_value)] use std::{ diff --git a/src/test/ui/mir/issue-89485.rs b/src/test/ui/mir/issue-89485.rs new file mode 100644 index 0000000000000..cb507eefebbe5 --- /dev/null +++ b/src/test/ui/mir/issue-89485.rs @@ -0,0 +1,18 @@ +// Regression test for issue #89485. + +// run-pass + +#[derive(Debug, Eq, PartialEq)] +pub enum Type { + A = 1, + B = 2, +} +pub fn encode(v: Type) -> Type { + match v { + Type::A => Type::B, + _ => v, + } +} +fn main() { + assert_eq!(Type::B, encode(Type::A)); +} diff --git a/src/test/ui/parser/issue-17383.rs b/src/test/ui/parser/issue-17383.rs new file mode 100644 index 0000000000000..7bf0e64f2c0a3 --- /dev/null +++ b/src/test/ui/parser/issue-17383.rs @@ -0,0 +1,7 @@ +enum X { + A = 3, + //~^ ERROR custom discriminant values are not allowed in enums with tuple or struct variants + B(usize) +} + +fn main() {} diff --git a/src/test/ui/parser/issue-17383.stderr b/src/test/ui/parser/issue-17383.stderr new file mode 100644 index 0000000000000..265d6e1486614 --- /dev/null +++ b/src/test/ui/parser/issue-17383.stderr @@ -0,0 +1,15 @@ +error[E0658]: custom discriminant values are not allowed in enums with tuple or struct variants + --> $DIR/issue-17383.rs:2:9 + | +LL | A = 3, + | ^ disallowed custom discriminant +LL | +LL | B(usize) + | -------- tuple variant defined here + | + = note: see issue #60553 for more information + = help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/parser/issue-89574.rs b/src/test/ui/parser/issue-89574.rs new file mode 100644 index 0000000000000..0a477f1aa5fb6 --- /dev/null +++ b/src/test/ui/parser/issue-89574.rs @@ -0,0 +1,4 @@ +fn main() { + const EMPTY_ARRAY = []; + //~^ missing type for `const` item +} diff --git a/src/test/ui/parser/issue-89574.stderr b/src/test/ui/parser/issue-89574.stderr new file mode 100644 index 0000000000000..cbee3d35155c7 --- /dev/null +++ b/src/test/ui/parser/issue-89574.stderr @@ -0,0 +1,8 @@ +error: missing type for `const` item + --> $DIR/issue-89574.rs:2:11 + | +LL | const EMPTY_ARRAY = []; + | ^^^^^^^^^^^ help: provide a type for the item: `EMPTY_ARRAY: ` + +error: aborting due to previous error + diff --git a/src/test/ui/parser/item-free-const-no-body-semantic-fail.rs b/src/test/ui/parser/item-free-const-no-body-semantic-fail.rs index 15a15a207b1ca..613b3c9856171 100644 --- a/src/test/ui/parser/item-free-const-no-body-semantic-fail.rs +++ b/src/test/ui/parser/item-free-const-no-body-semantic-fail.rs @@ -4,3 +4,4 @@ fn main() {} const A: u8; //~ ERROR free constant item without body const B; //~ ERROR free constant item without body +//~^ ERROR missing type for `const` item diff --git a/src/test/ui/parser/item-free-const-no-body-semantic-fail.stderr b/src/test/ui/parser/item-free-const-no-body-semantic-fail.stderr index aa75e5cee01d4..c340e958ee585 100644 --- a/src/test/ui/parser/item-free-const-no-body-semantic-fail.stderr +++ b/src/test/ui/parser/item-free-const-no-body-semantic-fail.stderr @@ -14,5 +14,11 @@ LL | const B; | | | help: provide a definition for the constant: `= ;` -error: aborting due to 2 previous errors +error: missing type for `const` item + --> $DIR/item-free-const-no-body-semantic-fail.rs:6:7 + | +LL | const B; + | ^ help: provide a type for the item: `B: ` + +error: aborting due to 3 previous errors diff --git a/src/test/ui/parser/item-free-static-no-body-semantic-fail.rs b/src/test/ui/parser/item-free-static-no-body-semantic-fail.rs index 61d3eab24d8c7..780479e3d26ac 100644 --- a/src/test/ui/parser/item-free-static-no-body-semantic-fail.rs +++ b/src/test/ui/parser/item-free-static-no-body-semantic-fail.rs @@ -4,6 +4,8 @@ fn main() {} static A: u8; //~ ERROR free static item without body static B; //~ ERROR free static item without body +//~^ ERROR missing type for `static` item static mut C: u8; //~ ERROR free static item without body static mut D; //~ ERROR free static item without body +//~^ ERROR missing type for `static mut` item diff --git a/src/test/ui/parser/item-free-static-no-body-semantic-fail.stderr b/src/test/ui/parser/item-free-static-no-body-semantic-fail.stderr index 7b408323674de..4d542b79861fd 100644 --- a/src/test/ui/parser/item-free-static-no-body-semantic-fail.stderr +++ b/src/test/ui/parser/item-free-static-no-body-semantic-fail.stderr @@ -15,7 +15,7 @@ LL | static B; | help: provide a definition for the static: `= ;` error: free static item without body - --> $DIR/item-free-static-no-body-semantic-fail.rs:8:1 + --> $DIR/item-free-static-no-body-semantic-fail.rs:9:1 | LL | static mut C: u8; | ^^^^^^^^^^^^^^^^- @@ -23,12 +23,24 @@ LL | static mut C: u8; | help: provide a definition for the static: `= ;` error: free static item without body - --> $DIR/item-free-static-no-body-semantic-fail.rs:9:1 + --> $DIR/item-free-static-no-body-semantic-fail.rs:10:1 | LL | static mut D; | ^^^^^^^^^^^^- | | | help: provide a definition for the static: `= ;` -error: aborting due to 4 previous errors +error: missing type for `static` item + --> $DIR/item-free-static-no-body-semantic-fail.rs:6:8 + | +LL | static B; + | ^ help: provide a type for the item: `B: ` + +error: missing type for `static mut` item + --> $DIR/item-free-static-no-body-semantic-fail.rs:10:12 + | +LL | static mut D; + | ^ help: provide a type for the item: `D: ` + +error: aborting due to 6 previous errors diff --git a/src/test/ui/parser/tag-variant-disr-non-nullary.rs b/src/test/ui/parser/tag-variant-disr-non-nullary.rs new file mode 100644 index 0000000000000..a9cfdd549c752 --- /dev/null +++ b/src/test/ui/parser/tag-variant-disr-non-nullary.rs @@ -0,0 +1,12 @@ +enum Color { + Red = 0xff0000, + //~^ ERROR custom discriminant values are not allowed in enums with tuple or struct variants + Green = 0x00ff00, + Blue = 0x0000ff, + Black = 0x000000, + White = 0xffffff, + Other(usize), + Other2(usize, usize), +} + +fn main() {} diff --git a/src/test/ui/parser/tag-variant-disr-non-nullary.stderr b/src/test/ui/parser/tag-variant-disr-non-nullary.stderr new file mode 100644 index 0000000000000..79f044a0675b7 --- /dev/null +++ b/src/test/ui/parser/tag-variant-disr-non-nullary.stderr @@ -0,0 +1,25 @@ +error[E0658]: custom discriminant values are not allowed in enums with tuple or struct variants + --> $DIR/tag-variant-disr-non-nullary.rs:2:11 + | +LL | Red = 0xff0000, + | ^^^^^^^^ disallowed custom discriminant +LL | +LL | Green = 0x00ff00, + | ^^^^^^^^ disallowed custom discriminant +LL | Blue = 0x0000ff, + | ^^^^^^^^ disallowed custom discriminant +LL | Black = 0x000000, + | ^^^^^^^^ disallowed custom discriminant +LL | White = 0xffffff, + | ^^^^^^^^ disallowed custom discriminant +LL | Other(usize), + | ------------ tuple variant defined here +LL | Other2(usize, usize), + | -------------------- tuple variant defined here + | + = note: see issue #60553 for more information + = help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/rust-2021/panic.rs b/src/test/ui/rust-2021/panic.rs new file mode 100644 index 0000000000000..394fc3c8f8254 --- /dev/null +++ b/src/test/ui/rust-2021/panic.rs @@ -0,0 +1,24 @@ +// edition:2021 + +fn main() { + debug_assert!(false, 123); + //~^ ERROR must be a string literal + assert!(false, 123); + //~^ ERROR must be a string literal + panic!(false, 123); + //~^ ERROR must be a string literal + + std::debug_assert!(false, 123); + //~^ ERROR must be a string literal + std::assert!(false, 123); + //~^ ERROR must be a string literal + std::panic!(false, 123); + //~^ ERROR must be a string literal + + core::debug_assert!(false, 123); + //~^ ERROR must be a string literal + core::assert!(false, 123); + //~^ ERROR must be a string literal + core::panic!(false, 123); + //~^ ERROR must be a string literal +} diff --git a/src/test/ui/rust-2021/panic.stderr b/src/test/ui/rust-2021/panic.stderr new file mode 100644 index 0000000000000..40b62d279a509 --- /dev/null +++ b/src/test/ui/rust-2021/panic.stderr @@ -0,0 +1,101 @@ +error: format argument must be a string literal + --> $DIR/panic.rs:4:26 + | +LL | debug_assert!(false, 123); + | ^^^ + | +help: you might be missing a string literal to format with + | +LL | debug_assert!(false, "{}", 123); + | +++++ + +error: format argument must be a string literal + --> $DIR/panic.rs:6:20 + | +LL | assert!(false, 123); + | ^^^ + | +help: you might be missing a string literal to format with + | +LL | assert!(false, "{}", 123); + | +++++ + +error: format argument must be a string literal + --> $DIR/panic.rs:8:12 + | +LL | panic!(false, 123); + | ^^^^^ + | +help: you might be missing a string literal to format with + | +LL | panic!("{} {}", false, 123); + | ++++++++ + +error: format argument must be a string literal + --> $DIR/panic.rs:11:31 + | +LL | std::debug_assert!(false, 123); + | ^^^ + | +help: you might be missing a string literal to format with + | +LL | std::debug_assert!(false, "{}", 123); + | +++++ + +error: format argument must be a string literal + --> $DIR/panic.rs:13:25 + | +LL | std::assert!(false, 123); + | ^^^ + | +help: you might be missing a string literal to format with + | +LL | std::assert!(false, "{}", 123); + | +++++ + +error: format argument must be a string literal + --> $DIR/panic.rs:15:17 + | +LL | std::panic!(false, 123); + | ^^^^^ + | +help: you might be missing a string literal to format with + | +LL | std::panic!("{} {}", false, 123); + | ++++++++ + +error: format argument must be a string literal + --> $DIR/panic.rs:18:32 + | +LL | core::debug_assert!(false, 123); + | ^^^ + | +help: you might be missing a string literal to format with + | +LL | core::debug_assert!(false, "{}", 123); + | +++++ + +error: format argument must be a string literal + --> $DIR/panic.rs:20:26 + | +LL | core::assert!(false, 123); + | ^^^ + | +help: you might be missing a string literal to format with + | +LL | core::assert!(false, "{}", 123); + | +++++ + +error: format argument must be a string literal + --> $DIR/panic.rs:22:18 + | +LL | core::panic!(false, 123); + | ^^^^^ + | +help: you might be missing a string literal to format with + | +LL | core::panic!("{} {}", false, 123); + | ++++++++ + +error: aborting due to 9 previous errors + diff --git a/src/test/ui/typeck/issue-79040.rs b/src/test/ui/typeck/issue-79040.rs index af2a9c1ba87ef..941612542207c 100644 --- a/src/test/ui/typeck/issue-79040.rs +++ b/src/test/ui/typeck/issue-79040.rs @@ -1,5 +1,5 @@ fn main() { const FOO = "hello" + 1; //~ ERROR cannot add `{integer}` to `&str` - //~^ ERROR cannot add `{integer}` to `&str` + //~^ missing type for `const` item println!("{}", FOO); } diff --git a/src/test/ui/typeck/issue-79040.stderr b/src/test/ui/typeck/issue-79040.stderr index 32049e5d96860..aec2e1ec9e4ef 100644 --- a/src/test/ui/typeck/issue-79040.stderr +++ b/src/test/ui/typeck/issue-79040.stderr @@ -6,13 +6,11 @@ LL | const FOO = "hello" + 1; | | | &str -error[E0369]: cannot add `{integer}` to `&str` - --> $DIR/issue-79040.rs:2:25 +error: missing type for `const` item + --> $DIR/issue-79040.rs:2:11 | LL | const FOO = "hello" + 1; - | ------- ^ - {integer} - | | - | &str + | ^^^ help: provide a type for the item: `FOO: ` error: aborting due to 2 previous errors diff --git a/src/tools/lld-wrapper/Cargo.toml b/src/tools/lld-wrapper/Cargo.toml new file mode 100644 index 0000000000000..8fe1f890ef504 --- /dev/null +++ b/src/tools/lld-wrapper/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "lld-wrapper" +version = "0.1.0" +edition = "2018" +license = "MIT OR Apache-2.0" + +[dependencies] + +[features] +ld = [] +ld64 = [] diff --git a/src/tools/lld-wrapper/src/main.rs b/src/tools/lld-wrapper/src/main.rs new file mode 100644 index 0000000000000..1601bf1b34e9c --- /dev/null +++ b/src/tools/lld-wrapper/src/main.rs @@ -0,0 +1,125 @@ +//! Script to invoke the bundled rust-lld with the correct flavor. The flavor is selected by +//! feature. +//! +//! lld supports multiple command line interfaces. If `-flavor ` are passed as the first +//! two arguments the `` command line interface is used to process the remaining arguments. +//! If no `-flavor` argument is present the flavor is determined by the executable name. +//! +//! In Rust with `-Z gcc-ld=lld` we have gcc or clang invoke rust-lld. Since there is no way to +//! make gcc/clang pass `-flavor ` as the first two arguments in the linker invocation +//! and since Windows does not support symbolic links for files this wrapper is used in place of a +//! symblic link. It execs `../rust-lld -flavor ld` if the feature `ld` is enabled and +//! `../rust-lld -flavor ld64` if `ld64` is enabled. On Windows it spawns a `..\rust-lld.exe` +//! child process. + +#[cfg(not(any(feature = "ld", feature = "ld64")))] +compile_error!("One of the features ld and ld64 must be enabled."); + +#[cfg(all(feature = "ld", feature = "ld64"))] +compile_error!("Only one of the feature ld or ld64 can be enabled."); + +#[cfg(feature = "ld")] +const FLAVOR: &str = "ld"; + +#[cfg(feature = "ld64")] +const FLAVOR: &str = "ld64"; + +use std::env; +use std::fmt::Display; +use std::path::{Path, PathBuf}; +use std::process; + +trait ResultExt { + fn unwrap_or_exit_with(self, context: &str) -> T; +} + +impl ResultExt for Result +where + E: Display, +{ + fn unwrap_or_exit_with(self, context: &str) -> T { + match self { + Ok(t) => t, + Err(e) => { + eprintln!("lld-wrapper: {}: {}", context, e); + process::exit(1); + } + } + } +} + +trait OptionExt { + fn unwrap_or_exit_with(self, context: &str) -> T; +} + +impl OptionExt for Option { + fn unwrap_or_exit_with(self, context: &str) -> T { + match self { + Some(t) => t, + None => { + eprintln!("lld-wrapper: {}", context); + process::exit(1); + } + } + } +} + +/// Returns the path to rust-lld in the parent directory. +/// +/// Exits if the parent directory cannot be determined. +fn get_rust_lld_path(current_exe_path: &Path) -> PathBuf { + let mut rust_lld_exe_name = "rust-lld".to_owned(); + rust_lld_exe_name.push_str(env::consts::EXE_SUFFIX); + let mut rust_lld_path = current_exe_path + .parent() + .unwrap_or_exit_with("directory containing current executable could not be determined") + .parent() + .unwrap_or_exit_with("parent directory could not be determined") + .to_owned(); + rust_lld_path.push(rust_lld_exe_name); + rust_lld_path +} + +/// Returns the command for invoking rust-lld with the correct flavor. +/// +/// Exits on error. +fn get_rust_lld_command(current_exe_path: &Path) -> process::Command { + let rust_lld_path = get_rust_lld_path(current_exe_path); + let mut command = process::Command::new(rust_lld_path); + command.arg("-flavor"); + command.arg(FLAVOR); + command.args(env::args_os().skip(1)); + command +} + +#[cfg(unix)] +fn exec_lld(mut command: process::Command) { + use std::os::unix::prelude::CommandExt; + Result::<(), _>::Err(command.exec()).unwrap_or_exit_with("could not exec rust-lld"); + unreachable!("lld-wrapper: after exec without error"); +} + +#[cfg(not(unix))] +fn exec_lld(mut command: process::Command) { + // Windows has no exec(), spawn a child process and wait for it + let exit_status = command.status().unwrap_or_exit_with("error running rust-lld child process"); + if !exit_status.success() { + match exit_status.code() { + Some(code) => { + // return the original lld exit code + process::exit(code) + } + None => { + eprintln!("lld-wrapper: rust-lld child process exited with error: {}", exit_status,); + process::exit(1); + } + } + } +} + +fn main() { + let current_exe_path = + env::current_exe().unwrap_or_exit_with("could not get the path of the current executable"); + + exec_lld(get_rust_lld_command(current_exe_path.as_ref())); +}