diff options
330 files changed, 5135 insertions, 4554 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4cf603519b1..540e1eb157e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -289,8 +289,9 @@ jobs: os: ubuntu-20.04-4core-16gb env: {} - name: x86_64-gnu-integration + env: + CI_ONLY_WHEN_CHANNEL: nightly os: ubuntu-20.04-16core-64gb - env: {} - name: x86_64-gnu-debug os: ubuntu-20.04-8core-32gb env: {} diff --git a/Cargo.lock b/Cargo.lock index 117d8c2610e..5d78e29de0e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4340,6 +4340,7 @@ dependencies = [ name = "rustc_pattern_analysis" version = "0.0.0" dependencies = [ + "derivative", "rustc_apfloat", "rustc_arena", "rustc_data_structures", diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 5252472261f..ec3ab828b71 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -11,6 +11,24 @@ use crate::{ Variants, WrappingRange, }; +// A variant is absent if it's uninhabited and only has ZST fields. +// Present uninhabited variants only require space for their fields, +// but *not* an encoding of the discriminant (e.g., a tag value). +// See issue #49298 for more details on the need to leave space +// for non-ZST uninhabited data (mostly partial initialization). +fn absent<'a, FieldIdx, VariantIdx, F>(fields: &IndexSlice<FieldIdx, F>) -> bool +where + FieldIdx: Idx, + VariantIdx: Idx, + F: Deref<Target = &'a LayoutS<FieldIdx, VariantIdx>> + fmt::Debug, +{ + let uninhabited = fields.iter().any(|f| f.abi.is_uninhabited()); + // We cannot ignore alignment; that might lead us to entirely discard a variant and + // produce an enum that is less aligned than it should be! + let is_1zst = fields.iter().all(|f| f.is_1zst()); + uninhabited && is_1zst +} + pub trait LayoutCalculator { type TargetDataLayoutRef: Borrow<TargetDataLayout>; @@ -162,24 +180,6 @@ pub trait LayoutCalculator { let dl = self.current_data_layout(); let dl = dl.borrow(); - let scalar_unit = |value: Primitive| { - let size = value.size(dl); - assert!(size.bits() <= 128); - Scalar::Initialized { value, valid_range: WrappingRange::full(size) } - }; - - // A variant is absent if it's uninhabited and only has ZST fields. - // Present uninhabited variants only require space for their fields, - // but *not* an encoding of the discriminant (e.g., a tag value). - // See issue #49298 for more details on the need to leave space - // for non-ZST uninhabited data (mostly partial initialization). - let absent = |fields: &IndexSlice<FieldIdx, F>| { - let uninhabited = fields.iter().any(|f| f.abi.is_uninhabited()); - // We cannot ignore alignment; that might lead us to entirely discard a variant and - // produce an enum that is less aligned than it should be! - let is_1zst = fields.iter().all(|f| f.is_1zst()); - uninhabited && is_1zst - }; let (present_first, present_second) = { let mut present_variants = variants .iter_enumerated() @@ -197,574 +197,37 @@ pub trait LayoutCalculator { None => VariantIdx::new(0), }; - let is_struct = !is_enum || - // Only one variant is present. - (present_second.is_none() && - // Representation optimizations are allowed. - !repr.inhibit_enum_layout_opt()); - if is_struct { - // Struct, or univariant enum equivalent to a struct. - // (Typechecking will reject discriminant-sizing attrs.) - - let v = present_first; - let kind = if is_enum || variants[v].is_empty() || always_sized { - StructKind::AlwaysSized - } else { - StructKind::MaybeUnsized - }; - - let mut st = self.univariant(dl, &variants[v], repr, kind)?; - st.variants = Variants::Single { index: v }; - - if is_unsafe_cell { - let hide_niches = |scalar: &mut _| match scalar { - Scalar::Initialized { value, valid_range } => { - *valid_range = WrappingRange::full(value.size(dl)) - } - // Already doesn't have any niches - Scalar::Union { .. } => {} - }; - match &mut st.abi { - Abi::Uninhabited => {} - Abi::Scalar(scalar) => hide_niches(scalar), - Abi::ScalarPair(a, b) => { - hide_niches(a); - hide_niches(b); - } - Abi::Vector { element, count: _ } => hide_niches(element), - Abi::Aggregate { sized: _ } => {} - } - st.largest_niche = None; - return Some(st); - } - - let (start, end) = scalar_valid_range; - match st.abi { - Abi::Scalar(ref mut scalar) | Abi::ScalarPair(ref mut scalar, _) => { - // Enlarging validity ranges would result in missed - // optimizations, *not* wrongly assuming the inner - // value is valid. e.g. unions already enlarge validity ranges, - // because the values may be uninitialized. - // - // Because of that we only check that the start and end - // of the range is representable with this scalar type. - - let max_value = scalar.size(dl).unsigned_int_max(); - if let Bound::Included(start) = start { - // FIXME(eddyb) this might be incorrect - it doesn't - // account for wrap-around (end < start) ranges. - assert!(start <= max_value, "{start} > {max_value}"); - scalar.valid_range_mut().start = start; - } - if let Bound::Included(end) = end { - // FIXME(eddyb) this might be incorrect - it doesn't - // account for wrap-around (end < start) ranges. - assert!(end <= max_value, "{end} > {max_value}"); - scalar.valid_range_mut().end = end; - } - - // Update `largest_niche` if we have introduced a larger niche. - let niche = Niche::from_scalar(dl, Size::ZERO, *scalar); - if let Some(niche) = niche { - match st.largest_niche { - Some(largest_niche) => { - // Replace the existing niche even if they're equal, - // because this one is at a lower offset. - if largest_niche.available(dl) <= niche.available(dl) { - st.largest_niche = Some(niche); - } - } - None => st.largest_niche = Some(niche), - } - } - } - _ => assert!( - start == Bound::Unbounded && end == Bound::Unbounded, - "nonscalar layout for layout_scalar_valid_range type: {st:#?}", - ), - } - - return Some(st); - } - - // At this point, we have handled all unions and - // structs. (We have also handled univariant enums - // that allow representation optimization.) - assert!(is_enum); - - // Until we've decided whether to use the tagged or - // niche filling LayoutS, we don't want to intern the - // variant layouts, so we can't store them in the - // overall LayoutS. Store the overall LayoutS - // and the variant LayoutSs here until then. - struct TmpLayout<FieldIdx: Idx, VariantIdx: Idx> { - layout: LayoutS<FieldIdx, VariantIdx>, - variants: IndexVec<VariantIdx, LayoutS<FieldIdx, VariantIdx>>, - } - - let calculate_niche_filling_layout = || -> Option<TmpLayout<FieldIdx, VariantIdx>> { - if dont_niche_optimize_enum { - return None; - } - - if variants.len() < 2 { - return None; - } - - let mut align = dl.aggregate_align; - let mut max_repr_align = repr.align; - let mut unadjusted_abi_align = align.abi; - - let mut variant_layouts = variants - .iter_enumerated() - .map(|(j, v)| { - let mut st = self.univariant(dl, v, repr, StructKind::AlwaysSized)?; - st.variants = Variants::Single { index: j }; - - align = align.max(st.align); - max_repr_align = max_repr_align.max(st.max_repr_align); - unadjusted_abi_align = unadjusted_abi_align.max(st.unadjusted_abi_align); - - Some(st) - }) - .collect::<Option<IndexVec<VariantIdx, _>>>()?; - - let largest_variant_index = variant_layouts - .iter_enumerated() - .max_by_key(|(_i, layout)| layout.size.bytes()) - .map(|(i, _layout)| i)?; - - let all_indices = variants.indices(); - let needs_disc = - |index: VariantIdx| index != largest_variant_index && !absent(&variants[index]); - let niche_variants = all_indices.clone().find(|v| needs_disc(*v)).unwrap() - ..=all_indices.rev().find(|v| needs_disc(*v)).unwrap(); - - let count = - (niche_variants.end().index() as u128 - niche_variants.start().index() as u128) + 1; - - // Find the field with the largest niche - let (field_index, niche, (niche_start, niche_scalar)) = variants[largest_variant_index] - .iter() - .enumerate() - .filter_map(|(j, field)| Some((j, field.largest_niche?))) - .max_by_key(|(_, niche)| niche.available(dl)) - .and_then(|(j, niche)| Some((j, niche, niche.reserve(dl, count)?)))?; - let niche_offset = - niche.offset + variant_layouts[largest_variant_index].fields.offset(field_index); - let niche_size = niche.value.size(dl); - let size = variant_layouts[largest_variant_index].size.align_to(align.abi); - - let all_variants_fit = variant_layouts.iter_enumerated_mut().all(|(i, layout)| { - if i == largest_variant_index { - return true; - } - - layout.largest_niche = None; - - if layout.size <= niche_offset { - // This variant will fit before the niche. - return true; - } - - // Determine if it'll fit after the niche. - let this_align = layout.align.abi; - let this_offset = (niche_offset + niche_size).align_to(this_align); - - if this_offset + layout.size > size { - return false; - } - - // It'll fit, but we need to make some adjustments. - match layout.fields { - FieldsShape::Arbitrary { ref mut offsets, .. } => { - for offset in offsets.iter_mut() { - *offset += this_offset; - } - } - FieldsShape::Primitive | FieldsShape::Array { .. } | FieldsShape::Union(..) => { - panic!("Layout of fields should be Arbitrary for variants") - } - } - - // It can't be a Scalar or ScalarPair because the offset isn't 0. - if !layout.abi.is_uninhabited() { - layout.abi = Abi::Aggregate { sized: true }; - } - layout.size += this_offset; - - true - }); - - if !all_variants_fit { - return None; - } - - let largest_niche = Niche::from_scalar(dl, niche_offset, niche_scalar); - - let others_zst = variant_layouts - .iter_enumerated() - .all(|(i, layout)| i == largest_variant_index || layout.size == Size::ZERO); - let same_size = size == variant_layouts[largest_variant_index].size; - let same_align = align == variant_layouts[largest_variant_index].align; - - let abi = if variant_layouts.iter().all(|v| v.abi.is_uninhabited()) { - Abi::Uninhabited - } else if same_size && same_align && others_zst { - match variant_layouts[largest_variant_index].abi { - // When the total alignment and size match, we can use the - // same ABI as the scalar variant with the reserved niche. - Abi::Scalar(_) => Abi::Scalar(niche_scalar), - Abi::ScalarPair(first, second) => { - // Only the niche is guaranteed to be initialised, - // so use union layouts for the other primitive. - if niche_offset == Size::ZERO { - Abi::ScalarPair(niche_scalar, second.to_union()) - } else { - Abi::ScalarPair(first.to_union(), niche_scalar) - } - } - _ => Abi::Aggregate { sized: true }, - } - } else { - Abi::Aggregate { sized: true } - }; - - let layout = LayoutS { - variants: Variants::Multiple { - tag: niche_scalar, - tag_encoding: TagEncoding::Niche { - untagged_variant: largest_variant_index, - niche_variants, - niche_start, - }, - tag_field: 0, - variants: IndexVec::new(), - }, - fields: FieldsShape::Arbitrary { - offsets: [niche_offset].into(), - memory_index: [0].into(), - }, - abi, - largest_niche, - size, - align, - max_repr_align, - unadjusted_abi_align, - }; - - Some(TmpLayout { layout, variants: variant_layouts }) - }; - - let niche_filling_layout = calculate_niche_filling_layout(); - - let (mut min, mut max) = (i128::MAX, i128::MIN); - let discr_type = repr.discr_type(); - let bits = Integer::from_attr(dl, discr_type).size().bits(); - for (i, mut val) in discriminants { - if variants[i].iter().any(|f| f.abi.is_uninhabited()) { - continue; - } - if discr_type.is_signed() { - // sign extend the raw representation to be an i128 - val = (val << (128 - bits)) >> (128 - bits); - } - if val < min { - min = val; - } - if val > max { - max = val; - } - } - // We might have no inhabited variants, so pretend there's at least one. - if (min, max) == (i128::MAX, i128::MIN) { - min = 0; - max = 0; - } - assert!(min <= max, "discriminant range is {min}...{max}"); - let (min_ity, signed) = discr_range_of_repr(min, max); //Integer::repr_discr(tcx, ty, &repr, min, max); - - let mut align = dl.aggregate_align; - let mut max_repr_align = repr.align; - let mut unadjusted_abi_align = align.abi; - - let mut size = Size::ZERO; - - // We're interested in the smallest alignment, so start large. - let mut start_align = Align::from_bytes(256).unwrap(); - assert_eq!(Integer::for_align(dl, start_align), None); - - // repr(C) on an enum tells us to make a (tag, union) layout, - // so we need to grow the prefix alignment to be at least - // the alignment of the union. (This value is used both for - // determining the alignment of the overall enum, and the - // determining the alignment of the payload after the tag.) - let mut prefix_align = min_ity.align(dl).abi; - if repr.c() { - for fields in variants { - for field in fields { - prefix_align = prefix_align.max(field.align.abi); - } - } - } - - // Create the set of structs that represent each variant. - let mut layout_variants = variants - .iter_enumerated() - .map(|(i, field_layouts)| { - let mut st = self.univariant( - dl, - field_layouts, - repr, - StructKind::Prefixed(min_ity.size(), prefix_align), - )?; - st.variants = Variants::Single { index: i }; - // Find the first field we can't move later - // to make room for a larger discriminant. - for field_idx in st.fields.index_by_increasing_offset() { - let field = &field_layouts[FieldIdx::new(field_idx)]; - if !field.is_1zst() { - start_align = start_align.min(field.align.abi); - break; - } - } - size = cmp::max(size, st.size); - align = align.max(st.align); - max_repr_align = max_repr_align.max(st.max_repr_align); - unadjusted_abi_align = unadjusted_abi_align.max(st.unadjusted_abi_align); - Some(st) - }) - .collect::<Option<IndexVec<VariantIdx, _>>>()?; - - // Align the maximum variant size to the largest alignment. - size = size.align_to(align.abi); - - // FIXME(oli-obk): deduplicate and harden these checks - if size.bytes() >= dl.obj_size_bound() { - return None; - } - - let typeck_ity = Integer::from_attr(dl, repr.discr_type()); - if typeck_ity < min_ity { - // It is a bug if Layout decided on a greater discriminant size than typeck for - // some reason at this point (based on values discriminant can take on). Mostly - // because this discriminant will be loaded, and then stored into variable of - // type calculated by typeck. Consider such case (a bug): typeck decided on - // byte-sized discriminant, but layout thinks we need a 16-bit to store all - // discriminant values. That would be a bug, because then, in codegen, in order - // to store this 16-bit discriminant into 8-bit sized temporary some of the - // space necessary to represent would have to be discarded (or layout is wrong - // on thinking it needs 16 bits) - panic!( - "layout decided on a larger discriminant type ({min_ity:?}) than typeck ({typeck_ity:?})" - ); - // However, it is fine to make discr type however large (as an optimisation) - // after this point – we’ll just truncate the value we load in codegen. - } - - // Check to see if we should use a different type for the - // discriminant. We can safely use a type with the same size - // as the alignment of the first field of each variant. - // We increase the size of the discriminant to avoid LLVM copying - // padding when it doesn't need to. This normally causes unaligned - // load/stores and excessive memcpy/memset operations. By using a - // bigger integer size, LLVM can be sure about its contents and - // won't be so conservative. - - // Use the initial field alignment - let mut ity = if repr.c() || repr.int.is_some() { - min_ity - } else { - Integer::for_align(dl, start_align).unwrap_or(min_ity) - }; - - // If the alignment is not larger than the chosen discriminant size, - // don't use the alignment as the final size. - if ity <= min_ity { - ity = min_ity; - } else { - // Patch up the variants' first few fields. - let old_ity_size = min_ity.size(); - let new_ity_size = ity.size(); - for variant in &mut layout_variants { - match variant.fields { - FieldsShape::Arbitrary { ref mut offsets, .. } => { - for i in offsets { - if *i <= old_ity_size { - assert_eq!(*i, old_ity_size); - *i = new_ity_size; - } - } - // We might be making the struct larger. - if variant.size <= old_ity_size { - variant.size = new_ity_size; - } - } - FieldsShape::Primitive | FieldsShape::Array { .. } | FieldsShape::Union(..) => { - panic!("encountered a non-arbitrary layout during enum layout") - } - } - } - } - - let tag_mask = ity.size().unsigned_int_max(); - let tag = Scalar::Initialized { - value: Primitive::Int(ity, signed), - valid_range: WrappingRange { - start: (min as u128 & tag_mask), - end: (max as u128 & tag_mask), - }, - }; - let mut abi = Abi::Aggregate { sized: true }; - - if layout_variants.iter().all(|v| v.abi.is_uninhabited()) { - abi = Abi::Uninhabited; - } else if tag.size(dl) == size { - // Make sure we only use scalar layout when the enum is entirely its - // own tag (i.e. it has no padding nor any non-ZST variant fields). - abi = Abi::Scalar(tag); + // take the struct path if it is an actual struct + if !is_enum || + // or for optimizing univariant enums + (present_second.is_none() && !repr.inhibit_enum_layout_opt()) + { + layout_of_struct( + self, + repr, + variants, + is_enum, + is_unsafe_cell, + scalar_valid_range, + always_sized, + dl, + present_first, + ) } else { - // Try to use a ScalarPair for all tagged enums. - // That's possible only if we can find a common primitive type for all variants. - let mut common_prim = None; - let mut common_prim_initialized_in_all_variants = true; - for (field_layouts, layout_variant) in iter::zip(variants, &layout_variants) { - let FieldsShape::Arbitrary { ref offsets, .. } = layout_variant.fields else { - panic!("encountered a non-arbitrary layout during enum layout"); - }; - // We skip *all* ZST here and later check if we are good in terms of alignment. - // This lets us handle some cases involving aligned ZST. - let mut fields = iter::zip(field_layouts, offsets).filter(|p| !p.0.is_zst()); - let (field, offset) = match (fields.next(), fields.next()) { - (None, None) => { - common_prim_initialized_in_all_variants = false; - continue; - } - (Some(pair), None) => pair, - _ => { - common_prim = None; - break; - } - }; - let prim = match field.abi { - Abi::Scalar(scalar) => { - common_prim_initialized_in_all_variants &= - matches!(scalar, Scalar::Initialized { .. }); - scalar.primitive() - } - _ => { - common_prim = None; - break; - } - }; - if let Some(pair) = common_prim { - // This is pretty conservative. We could go fancier - // by conflating things like i32 and u32, or even - // realising that (u8, u8) could just cohabit with - // u16 or even u32. - if pair != (prim, offset) { - common_prim = None; - break; - } - } else { - common_prim = Some((prim, offset)); - } - } - if let Some((prim, offset)) = common_prim { - let prim_scalar = if common_prim_initialized_in_all_variants { - scalar_unit(prim) - } else { - // Common prim might be uninit. - Scalar::Union { value: prim } - }; - let pair = self.scalar_pair::<FieldIdx, VariantIdx>(tag, prim_scalar); - let pair_offsets = match pair.fields { - FieldsShape::Arbitrary { ref offsets, ref memory_index } => { - assert_eq!(memory_index.raw, [0, 1]); - offsets - } - _ => panic!("encountered a non-arbitrary layout during enum layout"), - }; - if pair_offsets[FieldIdx::new(0)] == Size::ZERO - && pair_offsets[FieldIdx::new(1)] == *offset - && align == pair.align - && size == pair.size - { - // We can use `ScalarPair` only when it matches our - // already computed layout (including `#[repr(C)]`). - abi = pair.abi; - } - } - } - - // If we pick a "clever" (by-value) ABI, we might have to adjust the ABI of the - // variants to ensure they are consistent. This is because a downcast is - // semantically a NOP, and thus should not affect layout. - if matches!(abi, Abi::Scalar(..) | Abi::ScalarPair(..)) { - for variant in &mut layout_variants { - // We only do this for variants with fields; the others are not accessed anyway. - // Also do not overwrite any already existing "clever" ABIs. - if variant.fields.count() > 0 && matches!(variant.abi, Abi::Aggregate { .. }) { - variant.abi = abi; - // Also need to bump up the size and alignment, so that the entire value fits - // in here. - variant.size = cmp::max(variant.size, size); - variant.align.abi = cmp::max(variant.align.abi, align.abi); - } - } + // At this point, we have handled all unions and + // structs. (We have also handled univariant enums + // that allow representation optimization.) + assert!(is_enum); + layout_of_enum( + self, + repr, + variants, + discr_range_of_repr, + discriminants, + dont_niche_optimize_enum, + dl, + ) } - - let largest_niche = Niche::from_scalar(dl, Size::ZERO, tag); - - let tagged_layout = LayoutS { - variants: Variants::Multiple { - tag, - tag_encoding: TagEncoding::Direct, - tag_field: 0, - variants: IndexVec::new(), - }, - fields: FieldsShape::Arbitrary { - offsets: [Size::ZERO].into(), - memory_index: [0].into(), - }, - largest_niche, - abi, - align, - size, - max_repr_align, - unadjusted_abi_align, - }; - - let tagged_layout = TmpLayout { layout: tagged_layout, variants: layout_variants }; - - let mut best_layout = match (tagged_layout, niche_filling_layout) { - (tl, Some(nl)) => { - // Pick the smaller layout; otherwise, - // pick the layout with the larger niche; otherwise, - // pick tagged as it has simpler codegen. - use cmp::Ordering::*; - let niche_size = |tmp_l: &TmpLayout<FieldIdx, VariantIdx>| { - tmp_l.layout.largest_niche.map_or(0, |n| n.available(dl)) - }; - match (tl.layout.size.cmp(&nl.layout.size), niche_size(&tl).cmp(&niche_size(&nl))) { - (Greater, _) => nl, - (Equal, Less) => nl, - _ => tl, - } - } - (tl, None) => tl, - }; - - // Now we can intern the variant layouts and store them in the enum layout. - best_layout.layout.variants = match best_layout.layout.variants { - Variants::Multiple { tag, tag_encoding, tag_field, .. } => { - Variants::Multiple { tag, tag_encoding, tag_field, variants: best_layout.variants } - } - Variants::Single { .. } => { - panic!("encountered a single-variant enum during multi-variant layout") - } - }; - Some(best_layout.layout) } fn layout_of_union< @@ -872,6 +335,593 @@ pub trait LayoutCalculator { } } +/// single-variant enums are just structs, if you think about it +fn layout_of_struct<'a, LC, FieldIdx: Idx, VariantIdx: Idx, F>( + layout_calc: &LC, + repr: &ReprOptions, + variants: &IndexSlice<VariantIdx, IndexVec<FieldIdx, F>>, + is_enum: bool, + is_unsafe_cell: bool, + scalar_valid_range: (Bound<u128>, Bound<u128>), + always_sized: bool, + dl: &TargetDataLayout, + present_first: VariantIdx, +) -> Option<LayoutS<FieldIdx, VariantIdx>> +where + LC: LayoutCalculator + ?Sized, + F: Deref<Target = &'a LayoutS<FieldIdx, VariantIdx>> + fmt::Debug, +{ + // Struct, or univariant enum equivalent to a struct. + // (Typechecking will reject discriminant-sizing attrs.) + + let v = present_first; + let kind = if is_enum || variants[v].is_empty() || always_sized { + StructKind::AlwaysSized + } else { + StructKind::MaybeUnsized + }; + + let mut st = layout_calc.univariant(dl, &variants[v], repr, kind)?; + st.variants = Variants::Single { index: v }; + + if is_unsafe_cell { + let hide_niches = |scalar: &mut _| match scalar { + Scalar::Initialized { value, valid_range } => { + *valid_range = WrappingRange::full(value.size(dl)) + } + // Already doesn't have any niches + Scalar::Union { .. } => {} + }; + match &mut st.abi { + Abi::Uninhabited => {} + Abi::Scalar(scalar) => hide_niches(scalar), + Abi::ScalarPair(a, b) => { + hide_niches(a); + hide_niches(b); + } + Abi::Vector { element, count: _ } => hide_niches(element), + Abi::Aggregate { sized: _ } => {} + } + st.largest_niche = None; + return Some(st); + } + + let (start, end) = scalar_valid_range; + match st.abi { + Abi::Scalar(ref mut scalar) | Abi::ScalarPair(ref mut scalar, _) => { + // Enlarging validity ranges would result in missed + // optimizations, *not* wrongly assuming the inner + // value is valid. e.g. unions already enlarge validity ranges, + // because the values may be uninitialized. + // + // Because of that we only check that the start and end + // of the range is representable with this scalar type. + + let max_value = scalar.size(dl).unsigned_int_max(); + if let Bound::Included(start) = start { + // FIXME(eddyb) this might be incorrect - it doesn't + // account for wrap-around (end < start) ranges. + assert!(start <= max_value, "{start} > {max_value}"); + scalar.valid_range_mut().start = start; + } + if let Bound::Included(end) = end { + // FIXME(eddyb) this might be incorrect - it doesn't + // account for wrap-around (end < start) ranges. + assert!(end <= max_value, "{end} > {max_value}"); + scalar.valid_range_mut().end = end; + } + + // Update `largest_niche` if we have introduced a larger niche. + let niche = Niche::from_scalar(dl, Size::ZERO, *scalar); + if let Some(niche) = niche { + match st.largest_niche { + Some(largest_niche) => { + // Replace the existing niche even if they're equal, + // because this one is at a lower offset. + if largest_niche.available(dl) <= niche.available(dl) { + st.largest_niche = Some(niche); + } + } + None => st.largest_niche = Some(niche), + } + } + } + _ => assert!( + start == Bound::Unbounded && end == Bound::Unbounded, + "nonscalar layout for layout_scalar_valid_range type: {st:#?}", + ), + } + + Some(st) +} + +fn layout_of_enum<'a, LC, FieldIdx: Idx, VariantIdx: Idx, F>( + layout_calc: &LC, + repr: &ReprOptions, + variants: &IndexSlice<VariantIdx, IndexVec<FieldIdx, F>>, + discr_range_of_repr: impl Fn(i128, i128) -> (Integer, bool), + discriminants: impl Iterator<Item = (VariantIdx, i128)>, + dont_niche_optimize_enum: bool, + dl: &TargetDataLayout, +) -> Option<LayoutS<FieldIdx, VariantIdx>> +where + LC: LayoutCalculator + ?Sized, + F: Deref<Target = &'a LayoutS<FieldIdx, VariantIdx>> + fmt::Debug, +{ + // Until we've decided whether to use the tagged or + // niche filling LayoutS, we don't want to intern the + // variant layouts, so we can't store them in the + // overall LayoutS. Store the overall LayoutS + // and the variant LayoutSs here until then. + struct TmpLayout<FieldIdx: Idx, VariantIdx: Idx> { + layout: LayoutS<FieldIdx, VariantIdx>, + variants: IndexVec<VariantIdx, LayoutS<FieldIdx, VariantIdx>>, + } + + let calculate_niche_filling_layout = || -> Option<TmpLayout<FieldIdx, VariantIdx>> { + if dont_niche_optimize_enum { + return None; + } + + if variants.len() < 2 { + return None; + } + + let mut align = dl.aggregate_align; + let mut max_repr_align = repr.align; + let mut unadjusted_abi_align = align.abi; + + let mut variant_layouts = variants + .iter_enumerated() + .map(|(j, v)| { + let mut st = layout_calc.univariant(dl, v, repr, StructKind::AlwaysSized)?; + st.variants = Variants::Single { index: j }; + + align = align.max(st.align); + max_repr_align = max_repr_align.max(st.max_repr_align); + unadjusted_abi_align = unadjusted_abi_align.max(st.unadjusted_abi_align); + + Some(st) + }) + .collect::<Option<IndexVec<VariantIdx, _>>>()?; + + let largest_variant_index = variant_layouts + .iter_enumerated() + .max_by_key(|(_i, layout)| layout.size.bytes()) + .map(|(i, _layout)| i)?; + + let all_indices = variants.indices(); + let needs_disc = + |index: VariantIdx| index != largest_variant_index && !absent(&variants[index]); + let niche_variants = all_indices.clone().find(|v| needs_disc(*v)).unwrap() + ..=all_indices.rev().find(|v| needs_disc(*v)).unwrap(); + + let count = + (niche_variants.end().index() as u128 - niche_variants.start().index() as u128) + 1; + + // Find the field with the largest niche + let (field_index, niche, (niche_start, niche_scalar)) = variants[largest_variant_index] + .iter() + .enumerate() + .filter_map(|(j, field)| Some((j, field.largest_niche?))) + .max_by_key(|(_, niche)| niche.available(dl)) + .and_then(|(j, niche)| Some((j, niche, niche.reserve(dl, count)?)))?; + let niche_offset = + niche.offset + variant_layouts[largest_variant_index].fields.offset(field_index); + let niche_size = niche.value.size(dl); + let size = variant_layouts[largest_variant_index].size.align_to(align.abi); + + let all_variants_fit = variant_layouts.iter_enumerated_mut().all(|(i, layout)| { + if i == largest_variant_index { + return true; + } + + layout.largest_niche = None; + + if layout.size <= niche_offset { + // This variant will fit before the niche. + return true; + } + + // Determine if it'll fit after the niche. + let this_align = layout.align.abi; + let this_offset = (niche_offset + niche_size).align_to(this_align); + + if this_offset + layout.size > size { + return false; + } + + // It'll fit, but we need to make some adjustments. + match layout.fields { + FieldsShape::Arbitrary { ref mut offsets, .. } => { + for offset in offsets.iter_mut() { + *offset += this_offset; + } + } + FieldsShape::Primitive | FieldsShape::Array { .. } | FieldsShape::Union(..) => { + panic!("Layout of fields should be Arbitrary for variants") + } + } + + // It can't be a Scalar or ScalarPair because the offset isn't 0. + if !layout.abi.is_uninhabited() { + layout.abi = Abi::Aggregate { sized: true }; + } + layout.size += this_offset; + + true + }); + + if !all_variants_fit { + return None; + } + + let largest_niche = Niche::from_scalar(dl, niche_offset, niche_scalar); + + let others_zst = variant_layouts + .iter_enumerated() + .all(|(i, layout)| i == largest_variant_index || layout.size == Size::ZERO); + let same_size = size == variant_layouts[largest_variant_index].size; + let same_align = align == variant_layouts[largest_variant_index].align; + + let abi = if variant_layouts.iter().all(|v| v.abi.is_uninhabited()) { + Abi::Uninhabited + } else if same_size && same_align && others_zst { + match variant_layouts[largest_variant_index].abi { + // When the total alignment and size match, we can use the + // same ABI as the scalar variant with the reserved niche. + Abi::Scalar(_) => Abi::Scalar(niche_scalar), + Abi::ScalarPair(first, second) => { + // Only the niche is guaranteed to be initialised, + // so use union layouts for the other primitive. + if niche_offset == Size::ZERO { + Abi::ScalarPair(niche_scalar, second.to_union()) + } else { + Abi::ScalarPair(first.to_union(), niche_scalar) + } + } + _ => Abi::Aggregate { sized: true }, + } + } else { + Abi::Aggregate { sized: true } + }; + + let layout = LayoutS { + variants: Variants::Multiple { + tag: niche_scalar, + tag_encoding: TagEncoding::Niche { + untagged_variant: largest_variant_index, + niche_variants, + niche_start, + }, + tag_field: 0, + variants: IndexVec::new(), + }, + fields: FieldsShape::Arbitrary { + offsets: [niche_offset].into(), + memory_index: [0].into(), + }, + abi, + largest_niche, + size, + align, + max_repr_align, + unadjusted_abi_align, + }; + + Some(TmpLayout { layout, variants: variant_layouts }) + }; + + let niche_filling_layout = calculate_niche_filling_layout(); + + let (mut min, mut max) = (i128::MAX, i128::MIN); + let discr_type = repr.discr_type(); + let bits = Integer::from_attr(dl, discr_type).size().bits(); + for (i, mut val) in discriminants { + if variants[i].iter().any(|f| f.abi.is_uninhabited()) { + continue; + } + if discr_type.is_signed() { + // sign extend the raw representation to be an i128 + val = (val << (128 - bits)) >> (128 - bits); + } + if val < min { + min = val; + } + if val > max { + max = val; + } + } + // We might have no inhabited variants, so pretend there's at least one. + if (min, max) == (i128::MAX, i128::MIN) { + min = 0; + max = 0; + } + assert!(min <= max, "discriminant range is {min}...{max}"); + let (min_ity, signed) = discr_range_of_repr(min, max); //Integer::repr_discr(tcx, ty, &repr, min, max); + + let mut align = dl.aggregate_align; + let mut max_repr_align = repr.align; + let mut unadjusted_abi_align = align.abi; + + let mut size = Size::ZERO; + + // We're interested in the smallest alignment, so start large. + let mut start_align = Align::from_bytes(256).unwrap(); + assert_eq!(Integer::for_align(dl, start_align), None); + + // repr(C) on an enum tells us to make a (tag, union) layout, + // so we need to grow the prefix alignment to be at least + // the alignment of the union. (This value is used both for + // determining the alignment of the overall enum, and the + // determining the alignment of the payload after the tag.) + let mut prefix_align = min_ity.align(dl).abi; + if repr.c() { + for fields in variants { + for field in fields { + prefix_align = prefix_align.max(field.align.abi); + } + } + } + + // Create the set of structs that represent each variant. + let mut layout_variants = variants + .iter_enumerated() + .map(|(i, field_layouts)| { + let mut st = layout_calc.univariant( + dl, + field_layouts, + repr, + StructKind::Prefixed(min_ity.size(), prefix_align), + )?; + st.variants = Variants::Single { index: i }; + // Find the first field we can't move later + // to make room for a larger discriminant. + for field_idx in st.fields.index_by_increasing_offset() { + let field = &field_layouts[FieldIdx::new(field_idx)]; + if !field.is_1zst() { + start_align = start_align.min(field.align.abi); + break; + } + } + size = cmp::max(size, st.size); + align = align.max(st.align); + max_repr_align = max_repr_align.max(st.max_repr_align); + unadjusted_abi_align = unadjusted_abi_align.max(st.unadjusted_abi_align); + Some(st) + }) + .collect::<Option<IndexVec<VariantIdx, _>>>()?; + + // Align the maximum variant size to the largest alignment. + size = size.align_to(align.abi); + + // FIXME(oli-obk): deduplicate and harden these checks + if size.bytes() >= dl.obj_size_bound() { + return None; + } + + let typeck_ity = Integer::from_attr(dl, repr.discr_type()); + if typeck_ity < min_ity { + // It is a bug if Layout decided on a greater discriminant size than typeck for + // some reason at this point (based on values discriminant can take on). Mostly + // because this discriminant will be loaded, and then stored into variable of + // type calculated by typeck. Consider such case (a bug): typeck decided on + // byte-sized discriminant, but layout thinks we need a 16-bit to store all + // discriminant values. That would be a bug, because then, in codegen, in order + // to store this 16-bit discriminant into 8-bit sized temporary some of the + // space necessary to represent would have to be discarded (or layout is wrong + // on thinking it needs 16 bits) + panic!( + "layout decided on a larger discriminant type ({min_ity:?}) than typeck ({typeck_ity:?})" + ); + // However, it is fine to make discr type however large (as an optimisation) + // after this point – we’ll just truncate the value we load in codegen. + } + + // Check to see if we should use a different type for the + // discriminant. We can safely use a type with the same size + // as the alignment of the first field of each variant. + // We increase the size of the discriminant to avoid LLVM copying + // padding when it doesn't need to. This normally causes unaligned + // load/stores and excessive memcpy/memset operations. By using a + // bigger integer size, LLVM can be sure about its contents and + // won't be so conservative. + + // Use the initial field alignment + let mut ity = if repr.c() || repr.int.is_some() { + min_ity + } else { + Integer::for_align(dl, start_align).unwrap_or(min_ity) + }; + + // If the alignment is not larger than the chosen discriminant size, + // don't use the alignment as the final size. + if ity <= min_ity { + ity = min_ity; + } else { + // Patch up the variants' first few fields. + let old_ity_size = min_ity.size(); + let new_ity_size = ity.size(); + for variant in &mut layout_variants { + match variant.fields { + FieldsShape::Arbitrary { ref mut offsets, .. } => { + for i in offsets { + if *i <= old_ity_size { + assert_eq!(*i, old_ity_size); + *i = new_ity_size; + } + } + // We might be making the struct larger. + if variant.size <= old_ity_size { + variant.size = new_ity_size; + } + } + FieldsShape::Primitive | FieldsShape::Array { .. } | FieldsShape::Union(..) => { + panic!("encountered a non-arbitrary layout during enum layout") + } + } + } + } + + let tag_mask = ity.size().unsigned_int_max(); + let tag = Scalar::Initialized { + value: Primitive::Int(ity, signed), + valid_range: WrappingRange { + start: (min as u128 & tag_mask), + end: (max as u128 & tag_mask), + }, + }; + let mut abi = Abi::Aggregate { sized: true }; + + if layout_variants.iter().all(|v| v.abi.is_uninhabited()) { + abi = Abi::Uninhabited; + } else if tag.size(dl) == size { + // Make sure we only use scalar layout when the enum is entirely its + // own tag (i.e. it has no padding nor any non-ZST variant fields). + abi = Abi::Scalar(tag); + } else { + // Try to use a ScalarPair for all tagged enums. + // That's possible only if we can find a common primitive type for all variants. + let mut common_prim = None; + let mut common_prim_initialized_in_all_variants = true; + for (field_layouts, layout_variant) in iter::zip(variants, &layout_variants) { + let FieldsShape::Arbitrary { ref offsets, .. } = layout_variant.fields else { + panic!("encountered a non-arbitrary layout during enum layout"); + }; + // We skip *all* ZST here and later check if we are good in terms of alignment. + // This lets us handle some cases involving aligned ZST. + let mut fields = iter::zip(field_layouts, offsets).filter(|p| !p.0.is_zst()); + let (field, offset) = match (fields.next(), fields.next()) { + (None, None) => { + common_prim_initialized_in_all_variants = false; + continue; + } + (Some(pair), None) => pair, + _ => { + common_prim = None; + break; + } + }; + let prim = match field.abi { + Abi::Scalar(scalar) => { + common_prim_initialized_in_all_variants &= + matches!(scalar, Scalar::Initialized { .. }); + scalar.primitive() + } + _ => { + common_prim = None; + break; + } + }; + if let Some(pair) = common_prim { + // This is pretty conservative. We could go fancier + // by conflating things like i32 and u32, or even + // realising that (u8, u8) could just cohabit with + // u16 or even u32. + if pair != (prim, offset) { + common_prim = None; + break; + } + } else { + common_prim = Some((prim, offset)); + } + } + if let Some((prim, offset)) = common_prim { + let prim_scalar = if common_prim_initialized_in_all_variants { + let size = prim.size(dl); + assert!(size.bits() <= 128); + Scalar::Initialized { value: prim, valid_range: WrappingRange::full(size) } + } else { + // Common prim might be uninit. + Scalar::Union { value: prim } + }; + let pair = layout_calc.scalar_pair::<FieldIdx, VariantIdx>(tag, prim_scalar); + let pair_offsets = match pair.fields { + FieldsShape::Arbitrary { ref offsets, ref memory_index } => { + assert_eq!(memory_index.raw, [0, 1]); + offsets + } + _ => panic!("encountered a non-arbitrary layout during enum layout"), + }; + if pair_offsets[FieldIdx::new(0)] == Size::ZERO + && pair_offsets[FieldIdx::new(1)] == *offset + && align == pair.align + && size == pair.size + { + // We can use `ScalarPair` only when it matches our + // already computed layout (including `#[repr(C)]`). + abi = pair.abi; + } + } + } + + // If we pick a "clever" (by-value) ABI, we might have to adjust the ABI of the + // variants to ensure they are consistent. This is because a downcast is + // semantically a NOP, and thus should not affect layout. + if matches!(abi, Abi::Scalar(..) | Abi::ScalarPair(..)) { + for variant in &mut layout_variants { + // We only do this for variants with fields; the others are not accessed anyway. + // Also do not overwrite any already existing "clever" ABIs. + if variant.fields.count() > 0 && matches!(variant.abi, Abi::Aggregate { .. }) { + variant.abi = abi; + // Also need to bump up the size and alignment, so that the entire value fits + // in here. + variant.size = cmp::max(variant.size, size); + variant.align.abi = cmp::max(variant.align.abi, align.abi); + } + } + } + + let largest_niche = Niche::from_scalar(dl, Size::ZERO, tag); + + let tagged_layout = LayoutS { + variants: Variants::Multiple { + tag, + tag_encoding: TagEncoding::Direct, + tag_field: 0, + variants: IndexVec::new(), + }, + fields: FieldsShape::Arbitrary { offsets: [Size::ZERO].into(), memory_index: [0].into() }, + largest_niche, + abi, + align, + size, + max_repr_align, + unadjusted_abi_align, + }; + + let tagged_layout = TmpLayout { layout: tagged_layout, variants: layout_variants }; + + let mut best_layout = match (tagged_layout, niche_filling_layout) { + (tl, Some(nl)) => { + // Pick the smaller layout; otherwise, + // pick the layout with the larger niche; otherwise, + // pick tagged as it has simpler codegen. + use cmp::Ordering::*; + let niche_size = |tmp_l: &TmpLayout<FieldIdx, VariantIdx>| { + tmp_l.layout.largest_niche.map_or(0, |n| n.available(dl)) + }; + match (tl.layout.size.cmp(&nl.layout.size), niche_size(&tl).cmp(&niche_size(&nl))) { + (Greater, _) => nl, + (Equal, Less) => nl, + _ => tl, + } + } + (tl, None) => tl, + }; + + // Now we can intern the variant layouts and store them in the enum layout. + best_layout.layout.variants = match best_layout.layout.variants { + Variants::Multiple { tag, tag_encoding, tag_field, .. } => { + Variants::Multiple { tag, tag_encoding, tag_field, variants: best_layout.variants } + } + Variants::Single { .. } => { + panic!("encountered a single-variant enum during multi-variant layout") + } + }; + Some(best_layout.layout) +} + /// Determines towards which end of a struct layout optimizations will try to place the best niches. enum NicheBias { Start, diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index a121b5a9bed..3496cfc38c8 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -286,41 +286,16 @@ impl ParenthesizedArgs { pub use crate::node_id::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID}; -/// A modifier on a bound, e.g., `?Trait` or `~const Trait`. -/// -/// Negative bounds should also be handled here. +/// Modifiers on a trait bound like `~const`, `?` and `!`. #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)] -pub enum TraitBoundModifier { - /// No modifiers - None, - - /// `!Trait` - Negative, - - /// `?Trait` - Maybe, - - /// `~const Trait` - MaybeConst(Span), - - /// `~const !Trait` - // - // This parses but will be rejected during AST validation. - MaybeConstNegative, - - /// `~const ?Trait` - // - // This parses but will be rejected during AST validation. - MaybeConstMaybe, +pub struct TraitBoundModifiers { + pub constness: BoundConstness, + pub polarity: BoundPolarity, } -impl TraitBoundModifier { - pub fn to_constness(self) -> Const { - match self { - Self::MaybeConst(span) => Const::Yes(span), - _ => Const::No, - } - } +impl TraitBoundModifiers { + pub const NONE: Self = + Self { constness: BoundConstness::Never, polarity: BoundPolarity::Positive }; } /// The AST represents all type param bounds as types. @@ -329,7 +304,7 @@ impl TraitBoundModifier { /// detects `Copy`, `Send` and `Sync`. #[derive(Clone, Encodable, Decodable, Debug)] pub enum GenericBound { - Trait(PolyTraitRef, TraitBoundModifier), + Trait(PolyTraitRef, TraitBoundModifiers), Outlives(Lifetime), } @@ -779,8 +754,7 @@ pub enum PatKind { Ident(BindingAnnotation, Ident, Option<P<Pat>>), /// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`). - /// The `bool` is `true` in the presence of a `..`. - Struct(Option<P<QSelf>>, Path, ThinVec<PatField>, /* recovered */ bool), + Struct(Option<P<QSelf>>, Path, ThinVec<PatField>, PatFieldsRest), /// A tuple struct/variant pattern (`Variant(x, y, .., z)`). TupleStruct(Option<P<QSelf>>, Path, ThinVec<P<Pat>>), @@ -837,6 +811,15 @@ pub enum PatKind { MacCall(P<MacCall>), } +/// Whether the `..` is present in a struct fields pattern. +#[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq)] +pub enum PatFieldsRest { + /// `module::StructName { field, ..}` + Rest, + /// `module::StructName { field }` + None, +} + /// The kind of borrow in an `AddrOf` expression, /// e.g., `&place` or `&raw const place`. #[derive(Clone, Copy, PartialEq, Eq, Debug)] @@ -1193,7 +1176,7 @@ impl Expr { match &self.kind { ExprKind::Path(None, path) => Some(GenericBound::Trait( PolyTraitRef::new(ThinVec::new(), path.clone(), self.span), - TraitBoundModifier::None, + TraitBoundModifiers::NONE, )), _ => None, } @@ -1274,7 +1257,7 @@ impl Expr { ExprKind::Let(..) => ExprPrecedence::Let, ExprKind::If(..) => ExprPrecedence::If, ExprKind::While(..) => ExprPrecedence::While, - ExprKind::ForLoop(..) => ExprPrecedence::ForLoop, + ExprKind::ForLoop { .. } => ExprPrecedence::ForLoop, ExprKind::Loop(..) => ExprPrecedence::Loop, ExprKind::Match(..) => ExprPrecedence::Match, ExprKind::Closure(..) => ExprPrecedence::Closure, @@ -1436,10 +1419,10 @@ pub enum ExprKind { While(P<Expr>, P<Block>, Option<Label>), /// A `for` loop, with an optional label. /// - /// `'label: for pat in expr { block }` + /// `'label: for await? pat in iter { block }` /// /// This is desugared to a combination of `loop` and `match` expressions. - ForLoop(P<Pat>, P<Expr>, P<Block>, Option<Label>), + ForLoop { pat: P<Pat>, iter: P<Expr>, body: P<Block>, label: Option<Label>, kind: ForLoopKind }, /// Conditionless loop (can be exited with `break`, `continue`, or `return`). /// /// `'label: loop { block }` @@ -1542,6 +1525,13 @@ pub enum ExprKind { Err, } +/// Used to differentiate between `for` loops and `for await` loops. +#[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq, Eq)] +pub enum ForLoopKind { + For, + ForAwait, +} + /// Used to differentiate between `async {}` blocks and `gen {}` blocks. #[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)] pub enum GenBlockKind { @@ -2491,6 +2481,15 @@ pub enum Const { No, } +impl From<BoundConstness> for Const { + fn from(constness: BoundConstness) -> Self { + match constness { + BoundConstness::Maybe(span) => Self::Yes(span), + BoundConstness::Never => Self::No, + } + } +} + /// Item defaultness. /// For details see the [RFC #2532](https://github.com/rust-lang/rfcs/pull/2532). #[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] @@ -2516,7 +2515,9 @@ impl fmt::Debug for ImplPolarity { } } -#[derive(Copy, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)] +/// The polarity of a trait bound. +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)] +#[derive(HashStable_Generic)] pub enum BoundPolarity { /// `Type: Trait` Positive, @@ -2526,6 +2527,35 @@ pub enum BoundPolarity { Maybe(Span), } +impl BoundPolarity { + pub fn as_str(self) -> &'static str { + match self { + Self::Positive => "", + Self::Negative(_) => "!", + Self::Maybe(_) => "?", + } + } +} + +/// The constness of a trait bound. +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)] +#[derive(HashStable_Generic)] +pub enum BoundConstness { + /// `Type: Trait` + Never, + /// `Type: ~const Trait` + Maybe(Span), +} + +impl BoundConstness { + pub fn as_str(self) -> &'static str { + match self { + Self::Never => "", + Self::Maybe(_) => "~const", + } + } +} + #[derive(Clone, Encodable, Decodable, Debug)] pub enum FnRetTy { /// Returns type is not specified. @@ -3259,7 +3289,7 @@ mod size_asserts { static_assert_size!(ForeignItem, 96); static_assert_size!(ForeignItemKind, 24); static_assert_size!(GenericArg, 24); - static_assert_size!(GenericBound, 64); + static_assert_size!(GenericBound, 72); static_assert_size!(Generics, 40); static_assert_size!(Impl, 136); static_assert_size!(Item, 136); diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 557ae02a8f9..82f28143630 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1389,7 +1389,7 @@ pub fn noop_visit_expr<T: MutVisitor>( vis.visit_block(body); visit_opt(label, |label| vis.visit_label(label)); } - ExprKind::ForLoop(pat, iter, body, label) => { + ExprKind::ForLoop { pat, iter, body, label, kind: _ } => { vis.visit_pat(pat); vis.visit_expr(iter); vis.visit_block(body); diff --git a/compiler/rustc_ast/src/util/classify.rs b/compiler/rustc_ast/src/util/classify.rs index 4dece079783..65036bcdc36 100644 --- a/compiler/rustc_ast/src/util/classify.rs +++ b/compiler/rustc_ast/src/util/classify.rs @@ -19,7 +19,7 @@ pub fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool { | ast::ExprKind::Block(..) | ast::ExprKind::While(..) | ast::ExprKind::Loop(..) - | ast::ExprKind::ForLoop(..) + | ast::ExprKind::ForLoop { .. } | ast::ExprKind::TryBlock(..) | ast::ExprKind::ConstBlock(..) ) @@ -48,8 +48,16 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> { Closure(closure) => { expr = &closure.body; } - Gen(..) | Block(..) | ForLoop(..) | If(..) | Loop(..) | Match(..) | Struct(..) - | TryBlock(..) | While(..) | ConstBlock(_) => break Some(expr), + Gen(..) + | Block(..) + | ForLoop { .. } + | If(..) + | Loop(..) + | Match(..) + | Struct(..) + | TryBlock(..) + | While(..) + | ConstBlock(_) => break Some(expr), // FIXME: These can end in `}`, but changing these would break stable code. InlineAsm(_) | OffsetOf(_, _) | MacCall(_) | IncludedBytes(_) | FormatArgs(_) => { diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 27f1b84f372..45261ca48fc 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -844,11 +844,11 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { visitor.visit_expr(subexpression); visitor.visit_block(block); } - ExprKind::ForLoop(pattern, subexpression, block, opt_label) => { - walk_list!(visitor, visit_label, opt_label); - visitor.visit_pat(pattern); - visitor.visit_expr(subexpression); - visitor.visit_block(block); + ExprKind::ForLoop { pat, iter, body, label, kind: _ } => { + walk_list!(visitor, visit_label, label); + visitor.visit_pat(pat); + visitor.visit_expr(iter); + visitor.visit_block(body); } ExprKind::Loop(block, opt_label, _) => { walk_list!(visitor, visit_label, opt_label); diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 704f124dbcb..1f6d47ab453 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -56,12 +56,12 @@ impl<'hir> LoweringContext<'_, 'hir> { return ex; } // Desugar `ExprForLoop` - // from: `[opt_ident]: for <pat> in <head> <body>` + // from: `[opt_ident]: for await? <pat> in <iter> <body>` // // This also needs special handling because the HirId of the returned `hir::Expr` will not // correspond to the `e.id`, so `lower_expr_for` handles attribute lowering itself. - ExprKind::ForLoop(pat, head, body, opt_label) => { - return self.lower_expr_for(e, pat, head, body, *opt_label); + ExprKind::ForLoop { pat, iter, body, label, kind } => { + return self.lower_expr_for(e, pat, iter, body, *label, *kind); } _ => (), } @@ -337,7 +337,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ), ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr), - ExprKind::Paren(_) | ExprKind::ForLoop(..) => { + ExprKind::Paren(_) | ExprKind::ForLoop { .. } => { unreachable!("already handled") } @@ -670,7 +670,10 @@ impl<'hir> LoweringContext<'_, 'hir> { let params = arena_vec![self; param]; let body = self.lower_body(move |this| { - this.coroutine_kind = Some(hir::CoroutineKind::Async(async_coroutine_source)); + this.coroutine_kind = Some(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Async, + async_coroutine_source, + )); let old_ctx = this.task_context; this.task_context = Some(task_context_hid); @@ -724,7 +727,10 @@ impl<'hir> LoweringContext<'_, 'hir> { }); let body = self.lower_body(move |this| { - this.coroutine_kind = Some(hir::CoroutineKind::Gen(coroutine_source)); + this.coroutine_kind = Some(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Gen, + coroutine_source, + )); let res = body(this); (&[], res) @@ -802,7 +808,10 @@ impl<'hir> LoweringContext<'_, 'hir> { let params = arena_vec![self; param]; let body = self.lower_body(move |this| { - this.coroutine_kind = Some(hir::CoroutineKind::AsyncGen(async_coroutine_source)); + this.coroutine_kind = Some(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::AsyncGen, + async_coroutine_source, + )); let old_ctx = this.task_context; this.task_context = Some(task_context_hid); @@ -874,12 +883,25 @@ impl<'hir> LoweringContext<'_, 'hir> { /// } /// ``` fn lower_expr_await(&mut self, await_kw_span: Span, expr: &Expr) -> hir::ExprKind<'hir> { + let expr = self.arena.alloc(self.lower_expr_mut(expr)); + self.make_lowered_await(await_kw_span, expr, FutureKind::Future) + } + + /// Takes an expr that has already been lowered and generates a desugared await loop around it + fn make_lowered_await( + &mut self, + await_kw_span: Span, + expr: &'hir hir::Expr<'hir>, + await_kind: FutureKind, + ) -> hir::ExprKind<'hir> { let full_span = expr.span.to(await_kw_span); let is_async_gen = match self.coroutine_kind { - Some(hir::CoroutineKind::Async(_)) => false, - Some(hir::CoroutineKind::AsyncGen(_)) => true, - Some(hir::CoroutineKind::Coroutine) | Some(hir::CoroutineKind::Gen(_)) | None => { + Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) => false, + Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)) => true, + Some(hir::CoroutineKind::Coroutine) + | Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)) + | None => { return hir::ExprKind::Err(self.tcx.sess.emit_err(AwaitOnlyInAsyncFnAndBlocks { await_kw_span, item_span: self.current_item, @@ -887,13 +909,16 @@ impl<'hir> LoweringContext<'_, 'hir> { } }; - let span = self.mark_span_with_reason(DesugaringKind::Await, await_kw_span, None); + let features = match await_kind { + FutureKind::Future => None, + FutureKind::AsyncIterator => Some(self.allow_for_await.clone()), + }; + let span = self.mark_span_with_reason(DesugaringKind::Await, await_kw_span, features); let gen_future_span = self.mark_span_with_reason( DesugaringKind::Await, full_span, Some(self.allow_gen_future.clone()), ); - let expr = self.lower_expr_mut(expr); let expr_hir_id = expr.hir_id; // Note that the name of this binding must not be changed to something else because @@ -934,11 +959,18 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::LangItem::GetContext, arena_vec![self; task_context], ); - let call = self.expr_call_lang_item_fn( - span, - hir::LangItem::FuturePoll, - arena_vec![self; new_unchecked, get_context], - ); + let call = match await_kind { + FutureKind::Future => self.expr_call_lang_item_fn( + span, + hir::LangItem::FuturePoll, + arena_vec![self; new_unchecked, get_context], + ), + FutureKind::AsyncIterator => self.expr_call_lang_item_fn( + span, + hir::LangItem::AsyncIteratorPollNext, + arena_vec![self; new_unchecked, get_context], + ), + }; self.arena.alloc(self.expr_unsafe(call)) }; @@ -1020,11 +1052,16 @@ impl<'hir> LoweringContext<'_, 'hir> { let awaitee_arm = self.arm(awaitee_pat, loop_expr); // `match ::std::future::IntoFuture::into_future(<expr>) { ... }` - let into_future_expr = self.expr_call_lang_item_fn( - span, - hir::LangItem::IntoFutureIntoFuture, - arena_vec![self; expr], - ); + let into_future_expr = match await_kind { + FutureKind::Future => self.expr_call_lang_item_fn( + span, + hir::LangItem::IntoFutureIntoFuture, + arena_vec![self; *expr], + ), + // Not needed for `for await` because we expect to have already called + // `IntoAsyncIterator::into_async_iter` on it. + FutureKind::AsyncIterator => expr, + }; // match <into_future_expr> { // mut __awaitee => loop { .. } @@ -1097,9 +1134,9 @@ impl<'hir> LoweringContext<'_, 'hir> { Some(movability) } Some( - hir::CoroutineKind::Gen(_) - | hir::CoroutineKind::Async(_) - | hir::CoroutineKind::AsyncGen(_), + hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _) + | hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _) + | hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _), ) => { panic!("non-`async`/`gen` closure body turned `async`/`gen` during lowering"); } @@ -1612,9 +1649,9 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::ExprKind<'hir> { let is_async_gen = match self.coroutine_kind { - Some(hir::CoroutineKind::Gen(_)) => false, - Some(hir::CoroutineKind::AsyncGen(_)) => true, - Some(hir::CoroutineKind::Async(_)) => { + Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)) => false, + Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)) => true, + Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) => { return hir::ExprKind::Err( self.tcx.sess.emit_err(AsyncCoroutinesNotSupported { span }), ); @@ -1685,6 +1722,7 @@ impl<'hir> LoweringContext<'_, 'hir> { head: &Expr, body: &Block, opt_label: Option<Label>, + loop_kind: ForLoopKind, ) -> hir::Expr<'hir> { let head = self.lower_expr_mut(head); let pat = self.lower_pat(pat); @@ -1713,17 +1751,41 @@ impl<'hir> LoweringContext<'_, 'hir> { let (iter_pat, iter_pat_nid) = self.pat_ident_binding_mode(head_span, iter, hir::BindingAnnotation::MUT); - // `match Iterator::next(&mut iter) { ... }` let match_expr = { let iter = self.expr_ident(head_span, iter, iter_pat_nid); - let ref_mut_iter = self.expr_mut_addr_of(head_span, iter); - let next_expr = self.expr_call_lang_item_fn( - head_span, - hir::LangItem::IteratorNext, - arena_vec![self; ref_mut_iter], - ); + let next_expr = match loop_kind { + ForLoopKind::For => { + // `Iterator::next(&mut iter)` + let ref_mut_iter = self.expr_mut_addr_of(head_span, iter); + self.expr_call_lang_item_fn( + head_span, + hir::LangItem::IteratorNext, + arena_vec![self; ref_mut_iter], + ) + } + ForLoopKind::ForAwait => { + // we'll generate `unsafe { Pin::new_unchecked(&mut iter) })` and then pass this + // to make_lowered_await with `FutureKind::AsyncIterator` which will generator + // calls to `poll_next`. In user code, this would probably be a call to + // `Pin::as_mut` but here it's easy enough to do `new_unchecked`. + + // `&mut iter` + let iter = self.expr_mut_addr_of(head_span, iter); + // `Pin::new_unchecked(...)` + let iter = self.arena.alloc(self.expr_call_lang_item_fn_mut( + head_span, + hir::LangItem::PinNewUnchecked, + arena_vec![self; iter], + )); + // `unsafe { ... }` + let iter = self.arena.alloc(self.expr_unsafe(iter)); + let kind = self.make_lowered_await(head_span, iter, FutureKind::AsyncIterator); + self.arena.alloc(hir::Expr { hir_id: self.next_id(), kind, span: head_span }) + } + }; let arms = arena_vec![self; none_arm, some_arm]; + // `match $next_expr { ... }` self.expr_match(head_span, next_expr, arms, hir::MatchSource::ForLoopDesugar) }; let match_stmt = self.stmt_expr(for_span, match_expr); @@ -1743,13 +1805,34 @@ impl<'hir> LoweringContext<'_, 'hir> { // `mut iter => { ... }` let iter_arm = self.arm(iter_pat, loop_expr); - // `match ::std::iter::IntoIterator::into_iter(<head>) { ... }` - let into_iter_expr = { - self.expr_call_lang_item_fn( - head_span, - hir::LangItem::IntoIterIntoIter, - arena_vec![self; head], - ) + let into_iter_expr = match loop_kind { + ForLoopKind::For => { + // `::std::iter::IntoIterator::into_iter(<head>)` + self.expr_call_lang_item_fn( + head_span, + hir::LangItem::IntoIterIntoIter, + arena_vec![self; head], + ) + } + // ` unsafe { Pin::new_unchecked(&mut into_async_iter(<head>)) }` + ForLoopKind::ForAwait => { + // `::core::async_iter::IntoAsyncIterator::into_async_iter(<head>)` + let iter = self.expr_call_lang_item_fn( + head_span, + hir::LangItem::IntoAsyncIterIntoIter, + arena_vec![self; head], + ); + let iter = self.expr_mut_addr_of(head_span, iter); + // `Pin::new_unchecked(...)` + let iter = self.arena.alloc(self.expr_call_lang_item_fn_mut( + head_span, + hir::LangItem::PinNewUnchecked, + arena_vec![self; iter], + )); + // `unsafe { ... }` + let iter = self.arena.alloc(self.expr_unsafe(iter)); + iter + } }; let match_expr = self.arena.alloc(self.expr_match( @@ -2152,3 +2235,14 @@ impl<'hir> LoweringContext<'_, 'hir> { } } } + +/// Used by [`LoweringContext::make_lowered_await`] to customize the desugaring based on what kind +/// of future we are awaiting. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +enum FutureKind { + /// We are awaiting a normal future + Future, + /// We are awaiting something that's known to be an AsyncIterator (i.e. we are in the header of + /// a `for await` loop) + AsyncIterator, +} diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 5bddbe5f417..9c990cb4619 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1372,7 +1372,13 @@ impl<'hir> LoweringContext<'_, 'hir> { // need to compute this at all unless there is a Maybe bound. let mut is_param: Option<bool> = None; for bound in &bound_pred.bounds { - if !matches!(*bound, GenericBound::Trait(_, TraitBoundModifier::Maybe)) { + if !matches!( + *bound, + GenericBound::Trait( + _, + TraitBoundModifiers { polarity: BoundPolarity::Maybe(_), .. } + ) + ) { continue; } let is_param = *is_param.get_or_insert_with(compute_is_param); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 47b92981626..e35d7d62cad 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -130,6 +130,7 @@ struct LoweringContext<'a, 'hir> { allow_try_trait: Lrc<[Symbol]>, allow_gen_future: Lrc<[Symbol]>, allow_async_iterator: Lrc<[Symbol]>, + allow_for_await: Lrc<[Symbol]>, /// Mapping from generics `def_id`s to TAIT generics `def_id`s. /// For each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic @@ -174,6 +175,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } else { [sym::gen_future].into() }, + allow_for_await: [sym::async_iterator].into(), // FIXME(gen_blocks): how does `closure_track_caller`/`async_fn_track_caller` // interact with `gen`/`async gen` blocks allow_async_iterator: [sym::gen_future, sym::async_iterator].into(), @@ -1425,19 +1427,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { this.arena.alloc_from_iter(bounds.iter().filter_map(|bound| match bound { GenericBound::Trait( ty, - modifier @ (TraitBoundModifier::None - | TraitBoundModifier::MaybeConst(_) - | TraitBoundModifier::Negative), - ) => { - Some(this.lower_poly_trait_ref(ty, itctx, modifier.to_constness())) - } - // `~const ?Bound` will cause an error during AST validation - // anyways, so treat it like `?Bound` as compilation proceeds. + TraitBoundModifiers { + polarity: BoundPolarity::Positive | BoundPolarity::Negative(_), + constness, + }, + ) => Some(this.lower_poly_trait_ref(ty, itctx, (*constness).into())), + // We can safely ignore constness here, since AST validation + // will take care of invalid modifier combinations. GenericBound::Trait( _, - TraitBoundModifier::Maybe - | TraitBoundModifier::MaybeConstMaybe - | TraitBoundModifier::MaybeConstNegative, + TraitBoundModifiers { polarity: BoundPolarity::Maybe(_), .. }, ) => None, GenericBound::Outlives(lifetime) => { if lifetime_bound.is_none() { @@ -2028,9 +2027,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { itctx: &ImplTraitContext, ) -> hir::GenericBound<'hir> { match tpb { - GenericBound::Trait(p, modifier) => hir::GenericBound::Trait( - self.lower_poly_trait_ref(p, itctx, modifier.to_constness()), - self.lower_trait_bound_modifier(*modifier), + GenericBound::Trait(p, modifiers) => hir::GenericBound::Trait( + self.lower_poly_trait_ref(p, itctx, modifiers.constness.into()), + self.lower_trait_bound_modifiers(*modifiers), ), GenericBound::Outlives(lifetime) => { hir::GenericBound::Outlives(self.lower_lifetime(lifetime)) @@ -2316,25 +2315,29 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - fn lower_trait_bound_modifier(&mut self, f: TraitBoundModifier) -> hir::TraitBoundModifier { - match f { - TraitBoundModifier::None => hir::TraitBoundModifier::None, - TraitBoundModifier::MaybeConst(_) => hir::TraitBoundModifier::MaybeConst, - - TraitBoundModifier::Negative => { + fn lower_trait_bound_modifiers( + &mut self, + modifiers: TraitBoundModifiers, + ) -> hir::TraitBoundModifier { + match (modifiers.constness, modifiers.polarity) { + (BoundConstness::Never, BoundPolarity::Positive) => hir::TraitBoundModifier::None, + (BoundConstness::Never, BoundPolarity::Maybe(_)) => hir::TraitBoundModifier::Maybe, + (BoundConstness::Never, BoundPolarity::Negative(_)) => { if self.tcx.features().negative_bounds { hir::TraitBoundModifier::Negative } else { hir::TraitBoundModifier::None } } - - // `MaybeConstMaybe` will cause an error during AST validation, but we need to pick a - // placeholder for compilation to proceed. - TraitBoundModifier::MaybeConstMaybe | TraitBoundModifier::Maybe => { - hir::TraitBoundModifier::Maybe + (BoundConstness::Maybe(_), BoundPolarity::Positive) => { + hir::TraitBoundModifier::MaybeConst + } + // Invalid modifier combinations will cause an error during AST validation. + // Arbitrarily pick a placeholder for compilation to proceed. + (BoundConstness::Maybe(_), BoundPolarity::Maybe(_)) => hir::TraitBoundModifier::Maybe, + (BoundConstness::Maybe(_), BoundPolarity::Negative(_)) => { + hir::TraitBoundModifier::MaybeConst } - TraitBoundModifier::MaybeConstNegative => hir::TraitBoundModifier::MaybeConst, } } diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 017314ee4d1..3ffa4f1f2e6 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -82,7 +82,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: self.lower_span(f.span), } })); - break hir::PatKind::Struct(qpath, fs, *etc); + break hir::PatKind::Struct(qpath, fs, *etc == ast::PatFieldsRest::Rest); } PatKind::Tuple(pats) => { let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple"); diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index 1c5ad820bd6..ea3cd3e4bee 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -152,6 +152,8 @@ ast_passes_impl_trait_path = `impl Trait` is not allowed in path parameters ast_passes_incompatible_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed .help = remove one of these features +ast_passes_incompatible_trait_bound_modifiers = `{$left}` and `{$right}` are mutually exclusive + ast_passes_inherent_cannot_be = inherent impls cannot be {$annotation} .because = {$annotation} because of this .type = inherent impl for this type @@ -195,8 +197,6 @@ ast_passes_nomangle_ascii = `#[no_mangle]` requires ASCII identifier ast_passes_obsolete_auto = `impl Trait for .. {"{}"}` is an obsolete syntax .help = use `auto trait Trait {"{}"}` instead -ast_passes_optional_const_exclusive = `~const` and `{$modifier}` are mutually exclusive - ast_passes_optional_trait_object = `?Trait` is not permitted in trait object types ast_passes_optional_trait_supertrait = `?Trait` is not permitted in supertraits diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 887cb434a60..23a45749455 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1196,18 +1196,18 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } fn visit_param_bound(&mut self, bound: &'a GenericBound, ctxt: BoundKind) { - if let GenericBound::Trait(poly, modify) = bound { - match (ctxt, modify) { - (BoundKind::SuperTraits, TraitBoundModifier::Maybe) => { + if let GenericBound::Trait(poly, modifiers) = bound { + match (ctxt, modifiers.constness, modifiers.polarity) { + (BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_)) => { self.dcx().emit_err(errors::OptionalTraitSupertrait { span: poly.span, path_str: pprust::path_to_string(&poly.trait_ref.path), }); } - (BoundKind::TraitObject, TraitBoundModifier::Maybe) => { + (BoundKind::TraitObject, BoundConstness::Never, BoundPolarity::Maybe(_)) => { self.dcx().emit_err(errors::OptionalTraitObject { span: poly.span }); } - (_, &TraitBoundModifier::MaybeConst(span)) + (_, BoundConstness::Maybe(span), BoundPolarity::Positive) if let Some(reason) = &self.disallow_tilde_const => { let reason = match reason { @@ -1235,16 +1235,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> { }; self.dcx().emit_err(errors::TildeConstDisallowed { span, reason }); } - (_, TraitBoundModifier::MaybeConstMaybe) => { - self.dcx().emit_err(errors::OptionalConstExclusive { + ( + _, + BoundConstness::Maybe(_), + BoundPolarity::Maybe(_) | BoundPolarity::Negative(_), + ) => { + self.dcx().emit_err(errors::IncompatibleTraitBoundModifiers { span: bound.span(), - modifier: "?", - }); - } - (_, TraitBoundModifier::MaybeConstNegative) => { - self.dcx().emit_err(errors::OptionalConstExclusive { - span: bound.span(), - modifier: "!", + left: modifiers.constness.as_str(), + right: modifiers.polarity.as_str(), }); } _ => {} @@ -1252,7 +1251,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } // Negative trait bounds are not allowed to have associated constraints - if let GenericBound::Trait(trait_ref, TraitBoundModifier::Negative) = bound + if let GenericBound::Trait(trait_ref, modifiers) = bound + && let BoundPolarity::Negative(_) = modifiers.polarity && let Some(segment) = trait_ref.trait_ref.path.segments.last() && let Some(ast::GenericArgs::AngleBracketed(args)) = segment.args.as_deref() { @@ -1494,7 +1494,8 @@ fn deny_equality_constraints( for param in &generics.params { if param.ident == potential_param.ident { for bound in ¶m.bounds { - if let ast::GenericBound::Trait(trait_ref, TraitBoundModifier::None) = bound + if let ast::GenericBound::Trait(trait_ref, TraitBoundModifiers::NONE) = + bound { if let [trait_segment] = &trait_ref.trait_ref.path.segments[..] { let assoc = pprust::path_to_string(&ast::Path::from_ident( diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 304c5c1bde9..a5b842b320e 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -580,11 +580,12 @@ pub enum TildeConstReason { } #[derive(Diagnostic)] -#[diag(ast_passes_optional_const_exclusive)] -pub struct OptionalConstExclusive { +#[diag(ast_passes_incompatible_trait_bound_modifiers)] +pub struct IncompatibleTraitBoundModifiers { #[primary_span] pub span: Span, - pub modifier: &'static str, + pub left: &'static str, + pub right: &'static str, } #[derive(Diagnostic)] diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 1cc9309c45c..b20a0b9461f 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -527,6 +527,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { "async closures are unstable", "to use an async block, remove the `||`: `async {`" ); + gate_all!(async_for_loop, "`for await` loops are experimental"); gate_all!( closure_lifetime_binder, "`for<...>` binders for closures are experimental", diff --git a/compiler/rustc_ast_pretty/src/lib.rs b/compiler/rustc_ast_pretty/src/lib.rs index 670f2a45835..100b2988982 100644 --- a/compiler/rustc_ast_pretty/src/lib.rs +++ b/compiler/rustc_ast_pretty/src/lib.rs @@ -4,6 +4,7 @@ #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] #![feature(box_patterns)] +#![feature(let_chains)] #![recursion_limit = "256"] mod helpers; diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index d6c15ec35b6..12d37cf5a7a 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -17,7 +17,7 @@ use rustc_ast::util::comments::{gather_comments, Comment, CommentStyle}; use rustc_ast::util::parser; use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, BlockCheckMode, PatKind}; use rustc_ast::{attr, BindingAnnotation, ByRef, DelimArgs, RangeEnd, RangeSyntax, Term}; -use rustc_ast::{GenericArg, GenericBound, SelfKind, TraitBoundModifier}; +use rustc_ast::{GenericArg, GenericBound, SelfKind}; use rustc_ast::{InlineAsmOperand, InlineAsmRegOrRegClass}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_span::edition::Edition; @@ -1427,7 +1427,7 @@ impl<'a> State<'a> { } self.nbsp(); self.word("{"); - let empty = fields.is_empty() && !etc; + let empty = fields.is_empty() && *etc == ast::PatFieldsRest::None; if !empty { self.space(); } @@ -1445,7 +1445,7 @@ impl<'a> State<'a> { }, |f| f.pat.span, ); - if *etc { + if *etc == ast::PatFieldsRest::Rest { if !fields.is_empty() { self.word_space(","); } @@ -1559,26 +1559,20 @@ impl<'a> State<'a> { match bound { GenericBound::Trait(tref, modifier) => { - match modifier { - TraitBoundModifier::None => {} - TraitBoundModifier::Negative => { - self.word("!"); + match modifier.constness { + ast::BoundConstness::Never => {} + ast::BoundConstness::Maybe(_) => { + self.word_space(modifier.constness.as_str()); } - TraitBoundModifier::Maybe => { - self.word("?"); - } - TraitBoundModifier::MaybeConst(_) => { - self.word_space("~const"); - } - TraitBoundModifier::MaybeConstNegative => { - self.word_space("~const"); - self.word("!"); - } - TraitBoundModifier::MaybeConstMaybe => { - self.word_space("~const"); - self.word("?"); + } + + match modifier.polarity { + ast::BoundPolarity::Positive => {} + ast::BoundPolarity::Negative(_) | ast::BoundPolarity::Maybe(_) => { + self.word(modifier.polarity.as_str()); } } + self.print_poly_trait_ref(tref); } GenericBound::Outlives(lt) => self.print_lifetime(*lt), diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index f5ffcddb83d..f868beec812 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -1,5 +1,6 @@ use crate::pp::Breaks::Inconsistent; use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT}; +use ast::ForLoopKind; use itertools::{Itertools, Position}; use rustc_ast::ptr::P; use rustc_ast::token; @@ -418,20 +419,23 @@ impl<'a> State<'a> { self.space(); self.print_block_with_attrs(blk, attrs); } - ast::ExprKind::ForLoop(pat, iter, blk, opt_label) => { - if let Some(label) = opt_label { + ast::ExprKind::ForLoop { pat, iter, body, label, kind } => { + if let Some(label) = label { self.print_ident(label.ident); self.word_space(":"); } self.cbox(0); self.ibox(0); self.word_nbsp("for"); + if kind == &ForLoopKind::ForAwait { + self.word_nbsp("await"); + } self.print_pat(pat); self.space(); self.word_space("in"); self.print_expr_as_cond(iter); self.space(); - self.print_block_with_attrs(blk, attrs); + self.print_block_with_attrs(body, attrs); } ast::ExprKind::Loop(blk, opt_label, _) => { if let Some(label) = opt_label { diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 405ccc722d4..43561a1c020 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -5,7 +5,6 @@ use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT}; use ast::StaticItem; use itertools::{Itertools, Position}; use rustc_ast as ast; -use rustc_ast::GenericBound; use rustc_ast::ModKind; use rustc_span::symbol::Ident; @@ -338,19 +337,9 @@ impl<'a> State<'a> { self.word_nbsp("trait"); self.print_ident(item.ident); self.print_generic_params(&generics.params); - let mut real_bounds = Vec::with_capacity(bounds.len()); - for b in bounds.iter() { - if let GenericBound::Trait(ptr, ast::TraitBoundModifier::Maybe) = b { - self.space(); - self.word_space("for ?"); - self.print_trait_ref(&ptr.trait_ref); - } else { - real_bounds.push(b.clone()); - } - } - if !real_bounds.is_empty() { + if !bounds.is_empty() { self.word_nbsp(":"); - self.print_type_bounds(&real_bounds); + self.print_type_bounds(bounds); } self.print_where_clause(&generics.where_clause); self.word(" "); diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs index ce8e04defb2..fd2b0866867 100644 --- a/compiler/rustc_attr/src/session_diagnostics.rs +++ b/compiler/rustc_attr/src/session_diagnostics.rs @@ -2,7 +2,8 @@ use std::num::IntErrorKind; use rustc_ast as ast; use rustc_errors::{ - error_code, Applicability, DiagCtxt, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, + error_code, Applicability, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, + Level, }; use rustc_macros::Diagnostic; use rustc_span::{Span, Symbol}; @@ -50,14 +51,12 @@ pub(crate) struct UnknownMetaItem<'a> { } // Manual implementation to be able to format `expected` items correctly. -impl<'a> IntoDiagnostic<'a> for UnknownMetaItem<'_> { - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> { +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UnknownMetaItem<'_> { + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { let expected = self.expected.iter().map(|name| format!("`{name}`")).collect::<Vec<_>>(); - let mut diag = dcx.struct_span_err_with_code( - self.span, - fluent::attr_unknown_meta_item, - error_code!(E0541), - ); + let mut diag = DiagnosticBuilder::new(dcx, level, fluent::attr_unknown_meta_item); + diag.set_span(self.span); + diag.code(error_code!(E0541)); diag.set_arg("item", self.item); diag.set_arg("expected", expected.join(", ")); diag.span_label(self.span, fluent::attr_label); @@ -200,10 +199,11 @@ pub(crate) struct UnsupportedLiteral { pub start_point_span: Span, } -impl<'a> IntoDiagnostic<'a> for UnsupportedLiteral { - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - let mut diag = dcx.struct_span_err_with_code( - self.span, +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UnsupportedLiteral { + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { + let mut diag = DiagnosticBuilder::new( + dcx, + level, match self.reason { UnsupportedLiteralReason::Generic => fluent::attr_unsupported_literal_generic, UnsupportedLiteralReason::CfgString => fluent::attr_unsupported_literal_cfg_string, @@ -214,8 +214,9 @@ impl<'a> IntoDiagnostic<'a> for UnsupportedLiteral { fluent::attr_unsupported_literal_deprecated_kv_pair } }, - error_code!(E0565), ); + diag.set_span(self.span); + diag.code(error_code!(E0565)); if self.is_bytestr { diag.span_suggestion( self.start_point_span, diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index 6731ef12306..e527a91eb6f 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -1,5 +1,5 @@ use rustc_errors::{ - struct_span_err, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, ErrorGuaranteed, MultiSpan, + struct_span_err, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, MultiSpan, }; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; @@ -12,7 +12,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { place: &str, borrow_place: &str, value_place: &str, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { self.infcx.tcx.sess.create_err(crate::session_diagnostics::MoveBorrow { place, span, @@ -28,7 +28,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { desc: &str, borrow_span: Span, borrow_desc: &str, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { let mut err = struct_span_err!( self, span, @@ -50,7 +50,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { old_loan_span: Span, old_opt_via: &str, old_load_end_span: Option<Span>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { let via = |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {msg})") }; let mut err = struct_span_err!( self, @@ -97,7 +97,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { desc: &str, old_loan_span: Span, old_load_end_span: Option<Span>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { let mut err = struct_span_err!( self, new_loan_span, @@ -130,7 +130,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { noun_old: &str, old_opt_via: &str, previous_end_span: Option<Span>, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'cx> { let mut err = struct_span_err!( self, new_loan_span, @@ -162,7 +162,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { old_opt_via: &str, previous_end_span: Option<Span>, second_borrow_desc: &str, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'cx> { let mut err = struct_span_err!( self, new_loan_span, @@ -194,7 +194,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { kind_old: &str, msg_old: &str, old_load_end_span: Option<Span>, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'cx> { let via = |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {msg})") }; let mut err = struct_span_err!( self, @@ -235,7 +235,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { span: Span, borrow_span: Span, desc: &str, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'cx> { let mut err = struct_span_err!( self, span, @@ -254,16 +254,12 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { span: Span, desc: &str, is_arg: bool, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'cx> { let msg = if is_arg { "to immutable argument" } else { "twice to immutable variable" }; struct_span_err!(self, span, E0384, "cannot assign {} {}", msg, desc) } - pub(crate) fn cannot_assign( - &self, - span: Span, - desc: &str, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + pub(crate) fn cannot_assign(&self, span: Span, desc: &str) -> DiagnosticBuilder<'tcx> { struct_span_err!(self, span, E0594, "cannot assign to {}", desc) } @@ -271,7 +267,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { &self, move_from_span: Span, move_from_desc: &str, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'cx> { struct_span_err!(self, move_from_span, E0507, "cannot move out of {}", move_from_desc) } @@ -283,7 +279,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { move_from_span: Span, ty: Ty<'_>, is_index: Option<bool>, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'cx> { let type_name = match (&ty.kind(), is_index) { (&ty::Array(_, _), Some(true)) | (&ty::Array(_, _), None) => "array", (&ty::Slice(_), _) => "slice", @@ -305,7 +301,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { &self, move_from_span: Span, container_ty: Ty<'_>, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'cx> { let mut err = struct_span_err!( self, move_from_span, @@ -323,7 +319,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { verb: &str, optional_adverb_for_moved: &str, moved_path: Option<String>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { let moved_path = moved_path.map(|mp| format!(": `{mp}`")).unwrap_or_default(); struct_span_err!( @@ -342,7 +338,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { span: Span, path: &str, reason: &str, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { struct_span_err!(self, span, E0596, "cannot borrow {} as mutable{}", path, reason,) } @@ -353,7 +349,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { immutable_place: &str, immutable_section: &str, action: &str, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { let mut err = struct_span_err!( self, mutate_span, @@ -372,7 +368,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { &self, span: Span, yield_span: Span, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { let coroutine_kind = self.body.coroutine.as_ref().unwrap().coroutine_kind; let mut err = struct_span_err!( self, @@ -387,7 +383,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { pub(crate) fn cannot_borrow_across_destructor( &self, borrow_span: Span, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { struct_span_err!( self, borrow_span, @@ -400,7 +396,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { &self, span: Span, path: &str, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { struct_span_err!(self, span, E0597, "{} does not live long enough", path,) } @@ -410,7 +406,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { return_kind: &str, reference_desc: &str, path_desc: &str, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { let mut err = struct_span_err!( self, span, @@ -436,7 +432,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { borrowed_path: &str, capture_span: Span, scope: &str, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { let mut err = struct_span_err!( self, closure_span, @@ -452,14 +448,14 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { pub(crate) fn thread_local_value_does_not_live_long_enough( &self, span: Span, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { struct_span_err!(self, span, E0712, "thread-local variable borrowed past end of function",) } pub(crate) fn temporary_value_borrowed_for_too_long( &self, span: Span, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { struct_span_err!(self, span, E0716, "temporary value dropped while borrowed",) } @@ -470,7 +466,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { sp: S, msg: impl Into<DiagnosticMessage>, code: DiagnosticId, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { self.infcx.tcx.sess.struct_span_err_with_code(sp, msg, code) } } @@ -479,7 +475,7 @@ pub(crate) fn borrowed_data_escapes_closure<'tcx>( tcx: TyCtxt<'tcx>, escape_span: Span, escapes_from: &str, -) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { +) -> DiagnosticBuilder<'tcx> { struct_span_err!( tcx.sess, escape_span, diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index 924e68fa91d..e6881316a8f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -1,7 +1,7 @@ #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] -use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; +use rustc_errors::DiagnosticBuilder; use rustc_infer::infer::canonical::Canonical; use rustc_infer::infer::error_reporting::nice_region_error::NiceRegionError; use rustc_infer::infer::region_constraints::Constraint; @@ -147,11 +147,7 @@ impl<'tcx> ToUniverseInfo<'tcx> for ! { trait TypeOpInfo<'tcx> { /// Returns an error to be reported if rerunning the type op fails to /// recover the error's cause. - fn fallback_error( - &self, - tcx: TyCtxt<'tcx>, - span: Span, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>; + fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx>; fn base_universe(&self) -> ty::UniverseIndex; @@ -161,7 +157,7 @@ trait TypeOpInfo<'tcx> { cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option<ty::Region<'tcx>>, - ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>>; + ) -> Option<DiagnosticBuilder<'tcx>>; #[instrument(level = "debug", skip(self, mbcx))] fn report_error( @@ -224,11 +220,7 @@ struct PredicateQuery<'tcx> { } impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> { - fn fallback_error( - &self, - tcx: TyCtxt<'tcx>, - span: Span, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { tcx.sess.create_err(HigherRankedLifetimeError { cause: Some(HigherRankedErrorCause::CouldNotProve { predicate: self.canonical_query.value.value.predicate.to_string(), @@ -247,7 +239,7 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> { cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option<ty::Region<'tcx>>, - ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { + ) -> Option<DiagnosticBuilder<'tcx>> { let (infcx, key, _) = mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query); let ocx = ObligationCtxt::new(&infcx); @@ -265,11 +257,7 @@ impl<'tcx, T> TypeOpInfo<'tcx> for NormalizeQuery<'tcx, T> where T: Copy + fmt::Display + TypeFoldable<TyCtxt<'tcx>> + 'tcx, { - fn fallback_error( - &self, - tcx: TyCtxt<'tcx>, - span: Span, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { tcx.sess.create_err(HigherRankedLifetimeError { cause: Some(HigherRankedErrorCause::CouldNotNormalize { value: self.canonical_query.value.value.value.to_string(), @@ -288,7 +276,7 @@ where cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option<ty::Region<'tcx>>, - ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { + ) -> Option<DiagnosticBuilder<'tcx>> { let (infcx, key, _) = mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query); let ocx = ObligationCtxt::new(&infcx); @@ -312,11 +300,7 @@ struct AscribeUserTypeQuery<'tcx> { } impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> { - fn fallback_error( - &self, - tcx: TyCtxt<'tcx>, - span: Span, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { // FIXME: This error message isn't great, but it doesn't show up in the existing UI tests, // and is only the fallback when the nice error fails. Consider improving this some more. tcx.sess.create_err(HigherRankedLifetimeError { cause: None, span }) @@ -332,7 +316,7 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> { cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option<ty::Region<'tcx>>, - ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { + ) -> Option<DiagnosticBuilder<'tcx>> { let (infcx, key, _) = mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query); let ocx = ObligationCtxt::new(&infcx); @@ -342,11 +326,7 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> { } impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> { - fn fallback_error( - &self, - tcx: TyCtxt<'tcx>, - span: Span, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { // FIXME: This error message isn't great, but it doesn't show up in the existing UI tests, // and is only the fallback when the nice error fails. Consider improving this some more. tcx.sess.create_err(HigherRankedLifetimeError { cause: None, span }) @@ -362,7 +342,7 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> { _cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option<ty::Region<'tcx>>, - ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { + ) -> Option<DiagnosticBuilder<'tcx>> { try_extract_error_from_region_constraints( mbcx.infcx, placeholder_region, @@ -383,7 +363,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>( ocx: &ObligationCtxt<'_, 'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option<ty::Region<'tcx>>, -) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { +) -> Option<DiagnosticBuilder<'tcx>> { // We generally shouldn't have errors here because the query was // already run, but there's no point using `span_delayed_bug` // when we're going to emit an error here anyway. @@ -407,14 +387,19 @@ fn try_extract_error_from_region_constraints<'tcx>( region_constraints: &RegionConstraintData<'tcx>, mut region_var_origin: impl FnMut(RegionVid) -> RegionVariableOrigin, mut universe_of_region: impl FnMut(RegionVid) -> UniverseIndex, -) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { +) -> Option<DiagnosticBuilder<'tcx>> { + let placeholder_universe = match placeholder_region.kind() { + ty::RePlaceholder(p) => p.universe, + ty::ReVar(vid) => universe_of_region(vid), + _ => ty::UniverseIndex::ROOT, + }; let matches = |a_region: Region<'tcx>, b_region: Region<'tcx>| match (a_region.kind(), b_region.kind()) { (RePlaceholder(a_p), RePlaceholder(b_p)) => a_p.bound == b_p.bound, _ => a_region == b_region, }; - let check = |constraint: &Constraint<'tcx>, cause: &SubregionOrigin<'tcx>, exact| { - match *constraint { + let mut check = + |constraint: &Constraint<'tcx>, cause: &SubregionOrigin<'tcx>, exact| match *constraint { Constraint::RegSubReg(sub, sup) if ((exact && sup == placeholder_region) || (!exact && matches(sup, placeholder_region))) @@ -422,16 +407,16 @@ fn try_extract_error_from_region_constraints<'tcx>( { Some((sub, cause.clone())) } - // FIXME: Should this check the universe of the var? Constraint::VarSubReg(vid, sup) - if ((exact && sup == placeholder_region) - || (!exact && matches(sup, placeholder_region))) => + if (exact + && sup == placeholder_region + && !universe_of_region(vid).can_name(placeholder_universe)) + || (!exact && matches(sup, placeholder_region)) => { Some((ty::Region::new_var(infcx.tcx, vid), cause.clone())) } _ => None, - } - }; + }; let mut info = region_constraints .constraints .iter() diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index db0f4559a6b..1577b2896c3 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1,13 +1,11 @@ use either::Either; -use hir::PatField; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxIndexSet; -use rustc_errors::{ - struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, -}; +use rustc_errors::{struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{walk_block, walk_expr, Visitor}; +use rustc_hir::{CoroutineDesugaring, PatField}; use rustc_hir::{CoroutineKind, CoroutineSource, LangItem}; use rustc_infer::traits::ObligationCause; use rustc_middle::hir::nested_filter::OnlyBodies; @@ -324,7 +322,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut self, mpi: MovePathIndex, move_span: Span, - err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>, + err: &mut DiagnosticBuilder<'_>, in_pattern: &mut bool, move_spans: UseSpans<'_>, ) { @@ -483,7 +481,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { desired_action: InitializationRequiringAction, span: Span, use_spans: UseSpans<'tcx>, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'cx> { // We need all statements in the body where the binding was assigned to to later find all // the branching code paths where the binding *wasn't* assigned to. let inits = &self.move_data.init_path_map[mpi]; @@ -873,7 +871,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { location: Location, (place, _span): (Place<'tcx>, Span), borrow: &BorrowData<'tcx>, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'cx> { let borrow_spans = self.retrieve_borrow_spans(borrow); let borrow_span = borrow_spans.args_or_use(); @@ -921,7 +919,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { (place, span): (Place<'tcx>, Span), gen_borrow_kind: BorrowKind, issued_borrow: &BorrowData<'tcx>, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'cx> { let issued_spans = self.retrieve_borrow_spans(issued_borrow); let issued_span = issued_spans.args_or_use(); @@ -2025,7 +2023,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { drop_span: Span, borrow_spans: UseSpans<'tcx>, explanation: BorrowExplanation<'tcx>, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'cx> { debug!( "report_local_value_does_not_live_long_enough(\ {:?}, {:?}, {:?}, {:?}, {:?}\ @@ -2200,7 +2198,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut self, drop_span: Span, borrow_span: Span, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'cx> { debug!( "report_thread_local_value_does_not_live_long_enough(\ {:?}, {:?}\ @@ -2228,7 +2226,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { borrow_spans: UseSpans<'tcx>, proper_span: Span, explanation: BorrowExplanation<'tcx>, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'cx> { if let BorrowExplanation::MustBeValidFor { category, span, from_closure: false, .. } = explanation { @@ -2395,7 +2393,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { return_span: Span, category: ConstraintCategory<'tcx>, opt_place_desc: Option<&String>, - ) -> Option<DiagnosticBuilder<'cx, ErrorGuaranteed>> { + ) -> Option<DiagnosticBuilder<'cx>> { let return_kind = match category { ConstraintCategory::Return(_) => "return", ConstraintCategory::Yield => "yield", @@ -2490,7 +2488,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { constraint_span: Span, captured_var: &str, scope: &str, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'cx> { let tcx = self.infcx.tcx; let args_span = use_span.args_or_use(); @@ -2516,27 +2514,29 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }; let kind = match use_span.coroutine_kind() { Some(coroutine_kind) => match coroutine_kind { - CoroutineKind::Gen(kind) => match kind { + CoroutineKind::Desugared(CoroutineDesugaring::Gen, kind) => match kind { CoroutineSource::Block => "gen block", CoroutineSource::Closure => "gen closure", CoroutineSource::Fn => { bug!("gen block/closure expected, but gen function found.") } }, - CoroutineKind::AsyncGen(kind) => match kind { + CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, kind) => match kind { CoroutineSource::Block => "async gen block", CoroutineSource::Closure => "async gen closure", CoroutineSource::Fn => { bug!("gen block/closure expected, but gen function found.") } }, - CoroutineKind::Async(async_kind) => match async_kind { - CoroutineSource::Block => "async block", - CoroutineSource::Closure => "async closure", - CoroutineSource::Fn => { - bug!("async block/closure expected, but async function found.") + CoroutineKind::Desugared(CoroutineDesugaring::Async, async_kind) => { + match async_kind { + CoroutineSource::Block => "async block", + CoroutineSource::Closure => "async closure", + CoroutineSource::Fn => { + bug!("async block/closure expected, but async function found.") + } } - }, + } CoroutineKind::Coroutine => "coroutine", }, None => "closure", @@ -2566,7 +2566,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } ConstraintCategory::CallArgument(_) => { fr_name.highlight_region_name(&mut err); - if matches!(use_span.coroutine_kind(), Some(CoroutineKind::Async(_))) { + if matches!( + use_span.coroutine_kind(), + Some(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) + ) { err.note( "async blocks are not executed immediately and must either take a \ reference or ownership of outside variables they use", @@ -2593,7 +2596,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { upvar_span: Span, upvar_name: Symbol, escape_span: Span, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'cx> { let tcx = self.infcx.tcx; let escapes_from = tcx.def_descr(self.mir_def_id().to_def_id()); diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 43487b85a7b..f3b21d22c1a 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -1,4 +1,4 @@ -use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed}; +use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder}; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty}; use rustc_mir_dataflow::move_paths::{LookupResult, MovePathIndex}; @@ -288,7 +288,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { &mut self, place: Place<'tcx>, span: Span, - ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'a> { let description = if place.projection.len() == 1 { format!("static item {}", self.describe_any_place(place.as_ref())) } else { @@ -310,7 +310,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { deref_target_place: Place<'tcx>, span: Span, use_spans: Option<UseSpans<'tcx>>, - ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'a> { // Inspect the type of the content behind the // borrow to provide feedback about why this // was a move rather than a copy. diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index c3c1f1293d2..506933c470e 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -1,5 +1,5 @@ use hir::ExprKind; -use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed}; +use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::intravisit::Visitor; use rustc_hir::Node; @@ -711,7 +711,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { fn construct_mut_suggestion_for_local_binding_patterns( &self, - err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>, + err: &mut DiagnosticBuilder<'_>, local: Local, ) { let local_decl = &self.body.local_decls[local]; @@ -1025,7 +1025,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } } - fn suggest_using_iter_mut(&self, err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>) { + fn suggest_using_iter_mut(&self, err: &mut DiagnosticBuilder<'_>) { let source = self.body.source; let hir = self.infcx.tcx.hir(); if let InstanceDef::Item(def_id) = source.instance @@ -1067,12 +1067,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } } - fn suggest_make_local_mut( - &self, - err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>, - local: Local, - name: Symbol, - ) { + fn suggest_make_local_mut(&self, err: &mut DiagnosticBuilder<'_>, local: Local, name: Symbol) { let local_decl = &self.body.local_decls[local]; let (pointer_sigil, pointer_desc) = diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 759f5e910f7..f0b773b17ba 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -3,7 +3,7 @@ //! Error reporting machinery for lifetime errors. use rustc_data_structures::fx::FxIndexSet; -use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan}; +use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::Res::Def; use rustc_hir::def_id::DefId; @@ -202,7 +202,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // and the span which bounded to the trait for adding 'static lifetime suggestion fn suggest_static_lifetime_for_gat_from_hrtb( &self, - diag: &mut DiagnosticBuilder<'_, ErrorGuaranteed>, + diag: &mut DiagnosticBuilder<'_>, lower_bound: RegionVid, ) { let mut suggestions = vec![]; @@ -573,7 +573,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { &self, errci: &ErrorConstraintInfo<'tcx>, kind: ReturnConstraint, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { let ErrorConstraintInfo { outlived_fr, span, .. } = errci; let mut output_ty = self.regioncx.universal_regions().unnormalized_output_ty; @@ -645,7 +645,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { fn report_escaping_data_error( &self, errci: &ErrorConstraintInfo<'tcx>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { let ErrorConstraintInfo { span, category, .. } = errci; let fr_name_and_span = self.regioncx.get_var_name_and_span_for_region( @@ -744,10 +744,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// | ^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it /// | is returning data with lifetime `'b` /// ``` - fn report_general_error( - &self, - errci: &ErrorConstraintInfo<'tcx>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn report_general_error(&self, errci: &ErrorConstraintInfo<'tcx>) -> DiagnosticBuilder<'tcx> { let ErrorConstraintInfo { fr, fr_is_local, @@ -1049,7 +1046,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { .. }) => { let body = map.body(*body); - if !matches!(body.coroutine_kind, Some(hir::CoroutineKind::Async(..))) { + if !matches!( + body.coroutine_kind, + Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) + ) { closure_span = Some(expr.span.shrink_to_lo()); } } diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 8441dfaa7df..78d84f468e0 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -684,39 +684,46 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { hir::FnRetTy::Return(hir_ty) => (fn_decl.output.span(), Some(hir_ty)), }; let mir_description = match hir.body(body).coroutine_kind { - Some(hir::CoroutineKind::Async(src)) => match src { - hir::CoroutineSource::Block => " of async block", - hir::CoroutineSource::Closure => " of async closure", - hir::CoroutineSource::Fn => { - let parent_item = - tcx.hir_node_by_def_id(hir.get_parent_item(mir_hir_id).def_id); - let output = &parent_item - .fn_decl() - .expect("coroutine lowered from async fn should be in fn") - .output; - span = output.span(); - if let hir::FnRetTy::Return(ret) = output { - hir_ty = Some(self.get_future_inner_return_ty(*ret)); + Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, src)) => { + match src { + hir::CoroutineSource::Block => " of async block", + hir::CoroutineSource::Closure => " of async closure", + hir::CoroutineSource::Fn => { + let parent_item = + tcx.hir_node_by_def_id(hir.get_parent_item(mir_hir_id).def_id); + let output = &parent_item + .fn_decl() + .expect("coroutine lowered from async fn should be in fn") + .output; + span = output.span(); + if let hir::FnRetTy::Return(ret) = output { + hir_ty = Some(self.get_future_inner_return_ty(*ret)); + } + " of async function" } - " of async function" } - }, - Some(hir::CoroutineKind::Gen(src)) => match src { - hir::CoroutineSource::Block => " of gen block", - hir::CoroutineSource::Closure => " of gen closure", - hir::CoroutineSource::Fn => { - let parent_item = - tcx.hir_node_by_def_id(hir.get_parent_item(mir_hir_id).def_id); - let output = &parent_item - .fn_decl() - .expect("coroutine lowered from gen fn should be in fn") - .output; - span = output.span(); - " of gen function" + } + Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, src)) => { + match src { + hir::CoroutineSource::Block => " of gen block", + hir::CoroutineSource::Closure => " of gen closure", + hir::CoroutineSource::Fn => { + let parent_item = + tcx.hir_node_by_def_id(hir.get_parent_item(mir_hir_id).def_id); + let output = &parent_item + .fn_decl() + .expect("coroutine lowered from gen fn should be in fn") + .output; + span = output.span(); + " of gen function" + } } - }, + } - Some(hir::CoroutineKind::AsyncGen(src)) => match src { + Some(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::AsyncGen, + src, + )) => match src { hir::CoroutineSource::Block => " of async gen block", hir::CoroutineSource::Closure => " of async gen closure", hir::CoroutineSource::Fn => { diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 43f48f579a3..cf2d2ca7465 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -2407,8 +2407,8 @@ mod error { /// when errors in the map are being re-added to the error buffer so that errors with the /// same primary span come out in a consistent order. buffered_move_errors: - BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, DiagnosticBuilder<'tcx, ErrorGuaranteed>)>, - buffered_mut_errors: FxIndexMap<Span, (DiagnosticBuilder<'tcx, ErrorGuaranteed>, usize)>, + BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, DiagnosticBuilder<'tcx>)>, + buffered_mut_errors: FxIndexMap<Span, (DiagnosticBuilder<'tcx>, usize)>, /// Diagnostics to be reported buffer. buffered: Vec<Diagnostic>, /// Set to Some if we emit an error during borrowck @@ -2426,7 +2426,7 @@ mod error { } } - pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_, ErrorGuaranteed>) { + pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_>) { if let None = self.tainted_by_errors { self.tainted_by_errors = Some(self.tcx.sess.span_delayed_bug( t.span.clone_ignoring_labels(), @@ -2446,7 +2446,7 @@ mod error { } impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { - pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_, ErrorGuaranteed>) { + pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_>) { self.errors.buffer_error(t); } @@ -2457,7 +2457,7 @@ mod error { pub fn buffer_move_error( &mut self, move_out_indices: Vec<MoveOutIndex>, - place_and_err: (PlaceRef<'tcx>, DiagnosticBuilder<'tcx, ErrorGuaranteed>), + place_and_err: (PlaceRef<'tcx>, DiagnosticBuilder<'tcx>), ) -> bool { if let Some((_, diag)) = self.errors.buffered_move_errors.insert(move_out_indices, place_and_err) @@ -2473,16 +2473,11 @@ mod error { pub fn get_buffered_mut_error( &mut self, span: Span, - ) -> Option<(DiagnosticBuilder<'tcx, ErrorGuaranteed>, usize)> { + ) -> Option<(DiagnosticBuilder<'tcx>, usize)> { self.errors.buffered_mut_errors.remove(&span) } - pub fn buffer_mut_error( - &mut self, - span: Span, - t: DiagnosticBuilder<'tcx, ErrorGuaranteed>, - count: usize, - ) { + pub fn buffer_mut_error(&mut self, span: Span, t: DiagnosticBuilder<'tcx>, count: usize) { self.errors.buffered_mut_errors.insert(span, (t, count)); } @@ -2517,7 +2512,7 @@ mod error { pub fn has_move_error( &self, move_out_indices: &[MoveOutIndex], - ) -> Option<&(PlaceRef<'tcx>, DiagnosticBuilder<'cx, ErrorGuaranteed>)> { + ) -> Option<&(PlaceRef<'tcx>, DiagnosticBuilder<'cx>)> { self.errors.buffered_move_errors.get(move_out_indices) } } diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs index b54e119189a..d244897f8a5 100644 --- a/compiler/rustc_builtin_macros/src/assert/context.rs +++ b/compiler/rustc_builtin_macros/src/assert/context.rs @@ -303,7 +303,7 @@ impl<'cx, 'a> Context<'cx, 'a> { | ExprKind::Continue(_) | ExprKind::Err | ExprKind::Field(_, _) - | ExprKind::ForLoop(_, _, _, _) + | ExprKind::ForLoop { .. } | ExprKind::FormatArgs(_) | ExprKind::IncludedBytes(..) | ExprKind::InlineAsm(_) diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 6ffeb401453..e07eb2e490b 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -1,6 +1,6 @@ use rustc_errors::{ - AddToDiagnostic, DiagCtxt, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, MultiSpan, - SingleLabelManySpans, + AddToDiagnostic, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level, + MultiSpan, SingleLabelManySpans, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{symbol::Ident, Span, Symbol}; @@ -446,14 +446,14 @@ pub(crate) struct EnvNotDefinedWithUserMessage { } // Hand-written implementation to support custom user messages. -impl<'a> IntoDiagnostic<'a> for EnvNotDefinedWithUserMessage { +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for EnvNotDefinedWithUserMessage { #[track_caller] - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { #[expect( rustc::untranslatable_diagnostic, reason = "cannot translate user-provided messages" )] - let mut diag = dcx.struct_err(self.msg_from_user.to_string()); + let mut diag = DiagnosticBuilder::new(dcx, level, self.msg_from_user.to_string()); diag.set_span(self.span); diag } @@ -801,9 +801,13 @@ pub(crate) struct AsmClobberNoReg { pub(crate) clobbers: Vec<Span>, } -impl<'a> IntoDiagnostic<'a> for AsmClobberNoReg { - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - let mut diag = dcx.struct_err(crate::fluent_generated::builtin_macros_asm_clobber_no_reg); +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for AsmClobberNoReg { + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { + let mut diag = DiagnosticBuilder::new( + dcx, + level, + crate::fluent_generated::builtin_macros_asm_clobber_no_reg, + ); diag.set_span(self.spans.clone()); // eager translation as `span_labels` takes `AsRef<str>` let lbl1 = dcx.eagerly_translate_to_string( diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index c5fd535b036..2f23146096f 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -8,9 +8,7 @@ use rustc_ast::{ FormatDebugHex, FormatOptions, FormatPlaceholder, FormatSign, FormatTrait, }; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{ - Applicability, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, PResult, SingleLabelManySpans, -}; +use rustc_errors::{Applicability, DiagnosticBuilder, MultiSpan, PResult, SingleLabelManySpans}; use rustc_expand::base::{self, *}; use rustc_parse_format as parse; use rustc_span::symbol::{Ident, Symbol}; @@ -726,7 +724,7 @@ fn report_redundant_format_arguments<'a>( args: &FormatArguments, used: &[bool], placeholders: Vec<(Span, &str)>, -) -> Option<DiagnosticBuilder<'a, ErrorGuaranteed>> { +) -> Option<DiagnosticBuilder<'a>> { let mut fmt_arg_indices = vec![]; let mut args_spans = vec![]; let mut fmt_spans = vec![]; @@ -885,7 +883,6 @@ fn report_invalid_references( highlight: SingleLabelManySpans { spans: args.explicit_args().iter().map(|arg| arg.expr.span).collect(), label: "", - kind: rustc_errors::LabelKind::Label, }, }); // Point out `{:.*}` placeholders: those take an extra argument. diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index ec843a3a0cd..d760cea59a7 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -5,7 +5,7 @@ use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute}; use rustc_ast::ptr::P; use rustc_ast::{self as ast, attr, GenericParamKind}; use rustc_ast_pretty::pprust; -use rustc_errors::Applicability; +use rustc_errors::{Applicability, DiagnosticBuilder, Level}; use rustc_expand::base::*; use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::{ErrorGuaranteed, FileNameDisplayPreference, Span}; @@ -391,15 +391,14 @@ pub fn expand_test_or_bench( fn not_testable_error(cx: &ExtCtxt<'_>, attr_sp: Span, item: Option<&ast::Item>) { let dcx = cx.sess.dcx(); let msg = "the `#[test]` attribute may only be used on a non-associated function"; - let mut err = match item.map(|i| &i.kind) { + let level = match item.map(|i| &i.kind) { // These were a warning before #92959 and need to continue being that to avoid breaking // stable user code (#94508). - Some(ast::ItemKind::MacCall(_)) => dcx.struct_span_warn(attr_sp, msg), - // `.forget_guarantee()` needed to get these two arms to match types. Because of how - // locally close the `.emit()` call is I'm comfortable with it, but if it can be - // reworked in the future to not need it, it'd be nice. - _ => dcx.struct_span_err(attr_sp, msg).forget_guarantee(), + Some(ast::ItemKind::MacCall(_)) => Level::Warning(None), + _ => Level::Error { lint: false }, }; + let mut err = DiagnosticBuilder::<()>::new(dcx, level, msg); + err.set_span(attr_sp); if let Some(item) = item { err.span_label( item.span, diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock index 901d1dbea66..74e7afee7bc 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/Cargo.lock @@ -45,18 +45,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" -version = "0.102.0" +version = "0.103.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76eb38f2af690b5a4411d9a8782b6d77dabff3ca939e0518453ab9f9a4392d41" +checksum = "7c22542c0b95bd3302f7ed6839869c561f2324bac2fd5e7e99f5cfa65fdc8b92" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.102.0" +version = "0.103.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39526c036b92912417e8931f52c1e235796688068d3efdbbd8b164f299d19156" +checksum = "6b3db903ef2e9c8a4de2ea6db5db052c7857282952f9df604aa55d169e6000d8" dependencies = [ "bumpalo", "cranelift-bforest", @@ -75,39 +75,39 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.102.0" +version = "0.103.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb0deedc9fccf2db53a5a3c9c9d0163e44143b0d004dca9bf6ab6a0024cd79a" +checksum = "6590feb5a1d6438f974bf6a5ac4dddf69fca14e1f07f3265d880f69e61a94463" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.102.0" +version = "0.103.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea2d1b274e45aa8e61e9103efa1ba82d4b5a19d12bd1fd10744c3b7380ba3ff" +checksum = "7239038c56fafe77fddc8788fc8533dd6c474dc5bdc5637216404f41ba807330" [[package]] name = "cranelift-control" -version = "0.102.0" +version = "0.103.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea5977559a71e63db79a263f0e81a89b996e8a38212c4281e37dd1dbaa8b65c" +checksum = "f7dc9c595341404d381d27a3d950160856b35b402275f0c3990cd1ad683c8053" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.102.0" +version = "0.103.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f871ada808b58158d84dfc43a6a2e2d2756baaf4ed1c51fd969ca8330e6ca5c" +checksum = "44e3ee532fc4776c69bcedf7e62f9632cbb3f35776fa9a525cdade3195baa3f7" [[package]] name = "cranelift-frontend" -version = "0.102.0" +version = "0.103.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8e6890f587ef59824b3debe577e68fdf9b307b3808c54b8d93a18fd0b70941b" +checksum = "a612c94d09e653662ec37681dc2d6fd2b9856e6df7147be0afc9aabb0abf19df" dependencies = [ "cranelift-codegen", "log", @@ -117,15 +117,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.102.0" +version = "0.103.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d5fc6d5d3b52d1917002b17a8ecce448c2621b5bf394bb4e77e2f676893537" +checksum = "85db9830abeb1170b7d29b536ffd55af1d4d26ac8a77570b5d1aca003bf225cc" [[package]] name = "cranelift-jit" -version = "0.102.0" +version = "0.103.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a2d7744f743f59d9646d7589ad22ea17ed0d71e04906eb77c31e99bc13bd8b" +checksum = "4946271f1055e26544ef8c90fa24776f201566419dfac4b3962c39d5a804ff67" dependencies = [ "anyhow", "cranelift-codegen", @@ -143,9 +143,9 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.102.0" +version = "0.103.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b96cb196334698e612c197d7d0ae59af5e07667306ec20d7be414717db400873" +checksum = "cb7e3bdae2597556e59edeb8ecb62eb32c7e054c4f042d393732902979db69c3" dependencies = [ "anyhow", "cranelift-codegen", @@ -154,9 +154,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.102.0" +version = "0.103.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e10c2e7faa65d4ae7de9a83b44f2c31aca7dc638e17d0a79572fdf8103d720b" +checksum = "301ef0edafeaeda5771a5d2db64ac53e1818ae3111220a185677025fe91db4a1" dependencies = [ "cranelift-codegen", "libc", @@ -165,9 +165,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.102.0" +version = "0.103.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83ce94e18756058af8a66e3c0ba1123ae15517c72162d8060d0cb0974642adf2" +checksum = "59e0ee3d013728903e0c513c31afa389b559bfd4fe8a44f80335c799e3132a41" dependencies = [ "anyhow", "cranelift-codegen", @@ -374,9 +374,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wasmtime-jit-icache-coherence" -version = "15.0.0" +version = "16.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b73ad1395eda136baec5ece7e079e0536a82ef73488e345456cc9b89858ad0ec" +checksum = "6b6d197fcc34ad32ed440e1f9552fd57d1f377d9699d31dee1b5b457322c1f8a" dependencies = [ "cfg-if", "libc", diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml index 20fcd222732..fdac789423c 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.toml +++ b/compiler/rustc_codegen_cranelift/Cargo.toml @@ -8,12 +8,12 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.102", default-features = false, features = ["std", "unwind", "all-arch"] } -cranelift-frontend = { version = "0.102" } -cranelift-module = { version = "0.102" } -cranelift-native = { version = "0.102" } -cranelift-jit = { version = "0.102", optional = true } -cranelift-object = { version = "0.102" } +cranelift-codegen = { version = "0.103", default-features = false, features = ["std", "unwind", "all-arch"] } +cranelift-frontend = { version = "0.103" } +cranelift-module = { version = "0.103" } +cranelift-native = { version = "0.103" } +cranelift-jit = { version = "0.103", optional = true } +cranelift-object = { version = "0.103" } target-lexicon = "0.12.0" gimli = { version = "0.28", default-features = false, features = ["write"]} object = { version = "0.32", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } diff --git a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs index 1d51b499c8b..a1cdf31c68a 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs @@ -538,261 +538,38 @@ pub enum E1 { pub enum E2<X> { V1 { f: bool }, - /*_00*/ _01(X), - _02(X), - _03(X), - _04(X), - _05(X), - _06(X), - _07(X), - _08(X), - _09(X), - _0A(X), - _0B(X), - _0C(X), - _0D(X), - _0E(X), - _0F(X), - _10(X), - _11(X), - _12(X), - _13(X), - _14(X), - _15(X), - _16(X), - _17(X), - _18(X), - _19(X), - _1A(X), - _1B(X), - _1C(X), - _1D(X), - _1E(X), - _1F(X), - _20(X), - _21(X), - _22(X), - _23(X), - _24(X), - _25(X), - _26(X), - _27(X), - _28(X), - _29(X), - _2A(X), - _2B(X), - _2C(X), - _2D(X), - _2E(X), - _2F(X), - _30(X), - _31(X), - _32(X), - _33(X), - _34(X), - _35(X), - _36(X), - _37(X), - _38(X), - _39(X), - _3A(X), - _3B(X), - _3C(X), - _3D(X), - _3E(X), - _3F(X), - _40(X), - _41(X), - _42(X), - _43(X), - _44(X), - _45(X), - _46(X), - _47(X), - _48(X), - _49(X), - _4A(X), - _4B(X), - _4C(X), - _4D(X), - _4E(X), - _4F(X), - _50(X), - _51(X), - _52(X), - _53(X), - _54(X), - _55(X), - _56(X), - _57(X), - _58(X), - _59(X), - _5A(X), - _5B(X), - _5C(X), - _5D(X), - _5E(X), - _5F(X), - _60(X), - _61(X), - _62(X), - _63(X), - _64(X), - _65(X), - _66(X), - _67(X), - _68(X), - _69(X), - _6A(X), - _6B(X), - _6C(X), - _6D(X), - _6E(X), - _6F(X), - _70(X), - _71(X), - _72(X), - _73(X), - _74(X), - _75(X), - _76(X), - _77(X), - _78(X), - _79(X), - _7A(X), - _7B(X), - _7C(X), - _7D(X), - _7E(X), - _7F(X), - _80(X), - _81(X), - _82(X), - _83(X), - _84(X), - _85(X), - _86(X), - _87(X), - _88(X), - _89(X), - _8A(X), - _8B(X), - _8C(X), - _8D(X), - _8E(X), - _8F(X), - _90(X), - _91(X), - _92(X), - _93(X), - _94(X), - _95(X), - _96(X), - _97(X), - _98(X), - _99(X), - _9A(X), - _9B(X), - _9C(X), - _9D(X), - _9E(X), - _9F(X), - _A0(X), - _A1(X), - _A2(X), - _A3(X), - _A4(X), - _A5(X), - _A6(X), - _A7(X), - _A8(X), - _A9(X), - _AA(X), - _AB(X), - _AC(X), - _AD(X), - _AE(X), - _AF(X), - _B0(X), - _B1(X), - _B2(X), - _B3(X), - _B4(X), - _B5(X), - _B6(X), - _B7(X), - _B8(X), - _B9(X), - _BA(X), - _BB(X), - _BC(X), - _BD(X), - _BE(X), - _BF(X), - _C0(X), - _C1(X), - _C2(X), - _C3(X), - _C4(X), - _C5(X), - _C6(X), - _C7(X), - _C8(X), - _C9(X), - _CA(X), - _CB(X), - _CC(X), - _CD(X), - _CE(X), - _CF(X), - _D0(X), - _D1(X), - _D2(X), - _D3(X), - _D4(X), - _D5(X), - _D6(X), - _D7(X), - _D8(X), - _D9(X), - _DA(X), - _DB(X), - _DC(X), - _DD(X), - _DE(X), - _DF(X), - _E0(X), - _E1(X), - _E2(X), - _E3(X), - _E4(X), - _E5(X), - _E6(X), - _E7(X), - _E8(X), - _E9(X), - _EA(X), - _EB(X), - _EC(X), - _ED(X), - _EE(X), - _EF(X), - _F0(X), - _F1(X), - _F2(X), - _F3(X), - _F4(X), - _F5(X), - _F6(X), - _F7(X), - _F8(X), - _F9(X), - _FA(X), - _FB(X), - _FC(X), - _FD(X), - _FE(X), - _FF(X), + /*_00*/ _01(X), _02(X), _03(X), _04(X), _05(X), _06(X), _07(X), + _08(X), _09(X), _0A(X), _0B(X), _0C(X), _0D(X), _0E(X), _0F(X), + _10(X), _11(X), _12(X), _13(X), _14(X), _15(X), _16(X), _17(X), + _18(X), _19(X), _1A(X), _1B(X), _1C(X), _1D(X), _1E(X), _1F(X), + _20(X), _21(X), _22(X), _23(X), _24(X), _25(X), _26(X), _27(X), + _28(X), _29(X), _2A(X), _2B(X), _2C(X), _2D(X), _2E(X), _2F(X), + _30(X), _31(X), _32(X), _33(X), _34(X), _35(X), _36(X), _37(X), + _38(X), _39(X), _3A(X), _3B(X), _3C(X), _3D(X), _3E(X), _3F(X), + _40(X), _41(X), _42(X), _43(X), _44(X), _45(X), _46(X), _47(X), + _48(X), _49(X), _4A(X), _4B(X), _4C(X), _4D(X), _4E(X), _4F(X), + _50(X), _51(X), _52(X), _53(X), _54(X), _55(X), _56(X), _57(X), + _58(X), _59(X), _5A(X), _5B(X), _5C(X), _5D(X), _5E(X), _5F(X), + _60(X), _61(X), _62(X), _63(X), _64(X), _65(X), _66(X), _67(X), + _68(X), _69(X), _6A(X), _6B(X), _6C(X), _6D(X), _6E(X), _6F(X), + _70(X), _71(X), _72(X), _73(X), _74(X), _75(X), _76(X), _77(X), + _78(X), _79(X), _7A(X), _7B(X), _7C(X), _7D(X), _7E(X), _7F(X), + _80(X), _81(X), _82(X), _83(X), _84(X), _85(X), _86(X), _87(X), + _88(X), _89(X), _8A(X), _8B(X), _8C(X), _8D(X), _8E(X), _8F(X), + _90(X), _91(X), _92(X), _93(X), _94(X), _95(X), _96(X), _97(X), + _98(X), _99(X), _9A(X), _9B(X), _9C(X), _9D(X), _9E(X), _9F(X), + _A0(X), _A1(X), _A2(X), _A3(X), _A4(X), _A5(X), _A6(X), _A7(X), + _A8(X), _A9(X), _AA(X), _AB(X), _AC(X), _AD(X), _AE(X), _AF(X), + _B0(X), _B1(X), _B2(X), _B3(X), _B4(X), _B5(X), _B6(X), _B7(X), + _B8(X), _B9(X), _BA(X), _BB(X), _BC(X), _BD(X), _BE(X), _BF(X), + _C0(X), _C1(X), _C2(X), _C3(X), _C4(X), _C5(X), _C6(X), _C7(X), + _C8(X), _C9(X), _CA(X), _CB(X), _CC(X), _CD(X), _CE(X), _CF(X), + _D0(X), _D1(X), _D2(X), _D3(X), _D4(X), _D5(X), _D6(X), _D7(X), + _D8(X), _D9(X), _DA(X), _DB(X), _DC(X), _DD(X), _DE(X), _DF(X), + _E0(X), _E1(X), _E2(X), _E3(X), _E4(X), _E5(X), _E6(X), _E7(X), + _E8(X), _E9(X), _EA(X), _EB(X), _EC(X), _ED(X), _EE(X), _EF(X), + _F0(X), _F1(X), _F2(X), _F3(X), _F4(X), _F5(X), _F6(X), _F7(X), + _F8(X), _F9(X), _FA(X), _FB(X), _FC(X), _FD(X), _FE(X), _FF(X), V3, V4, diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain index 4ba08f1af44..e1e1760c597 100644 --- a/compiler/rustc_codegen_cranelift/rust-toolchain +++ b/compiler/rustc_codegen_cranelift/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-12-19" +channel = "nightly-2023-12-24" components = ["rust-src", "rustc-dev", "llvm-tools"] diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh index 7d7ffdadc7f..636f2875a68 100755 --- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh +++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh @@ -31,6 +31,7 @@ rm tests/ui/parser/unclosed-delimiter-in-dep.rs # submodule contains //~ERROR # FIXME add needs-unwind to these tests rm -r tests/run-make/libtest-junit rm tests/ui/asm/may_unwind.rs +rm tests/ui/stable-mir-print/basic_function.rs # extra warning about -Cpanic=abort for proc macros rm tests/ui/proc-macro/crt-static.rs @@ -44,7 +45,6 @@ rm tests/ui/proc-macro/no-mangle-in-proc-macro-issue-111888.rs # vendor intrinsics rm tests/ui/sse2.rs # CodegenBackend::target_features not yet implemented rm tests/ui/simd/array-type.rs # "Index argument for `simd_insert` is not a constant" -rm tests/ui/simd/masked-load-store.rs # exotic linkages rm tests/ui/issues/issue-33992.rs # unsupported linkages @@ -80,6 +80,7 @@ rm -r tests/run-make/codegen-options-parsing rm -r tests/run-make/lto-* rm -r tests/run-make/reproducible-build-2 rm -r tests/run-make/issue-109934-lto-debuginfo +rm -r tests/run-make/no-builtins-lto # optimization tests # ================== diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index df40a5eb475..8d3be19839e 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -179,7 +179,7 @@ pub(crate) fn compile_fn( let early_dcx = rustc_session::EarlyDiagCtxt::new( rustc_session::config::ErrorOutputType::default(), ); - early_dcx.early_error(format!( + early_dcx.early_fatal(format!( "backend implementation limit exceeded while compiling {name}", name = codegened_func.symbol_name )); diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index fe4f073f799..d06237f8d91 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -962,6 +962,37 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( } } + sym::simd_masked_store => { + intrinsic_args!(fx, args => (mask, ptr, val); intrinsic); + + let (val_lane_count, val_lane_ty) = val.layout().ty.simd_size_and_type(fx.tcx); + let (mask_lane_count, _mask_lane_ty) = mask.layout().ty.simd_size_and_type(fx.tcx); + assert_eq!(val_lane_count, mask_lane_count); + let lane_clif_ty = fx.clif_type(val_lane_ty).unwrap(); + let ptr_val = ptr.load_scalar(fx); + + for lane_idx in 0..val_lane_count { + let val_lane = val.value_lane(fx, lane_idx).load_scalar(fx); + let mask_lane = mask.value_lane(fx, lane_idx).load_scalar(fx); + + let if_enabled = fx.bcx.create_block(); + let next = fx.bcx.create_block(); + + fx.bcx.ins().brif(mask_lane, if_enabled, &[], next, &[]); + fx.bcx.seal_block(if_enabled); + + fx.bcx.switch_to_block(if_enabled); + let offset = lane_idx as i32 * lane_clif_ty.bytes() as i32; + fx.bcx.ins().store(MemFlags::trusted(), val_lane, ptr_val, Offset32::new(offset)); + fx.bcx.ins().jump(next, &[]); + + fx.bcx.seal_block(next); + fx.bcx.switch_to_block(next); + + fx.bcx.ins().nop(); + } + } + sym::simd_gather => { intrinsic_args!(fx, args => (val, ptr, mask); intrinsic); @@ -1057,7 +1088,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( } sym::simd_scatter => { - intrinsic_args!(fx, args => (mask, ptr, val); intrinsic); + intrinsic_args!(fx, args => (val, ptr, mask); intrinsic); let (val_lane_count, _val_lane_ty) = val.layout().ty.simd_size_and_type(fx.tcx); let (ptr_lane_count, _ptr_lane_ty) = ptr.layout().ty.simd_size_and_type(fx.tcx); diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 148193b5a97..d0ce209be44 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -1,6 +1,6 @@ -#![cfg_attr(all(doc, not(bootstrap)), allow(internal_features))] -#![cfg_attr(all(doc, not(bootstrap)), feature(rustdoc_internals))] -#![cfg_attr(all(doc, not(bootstrap)), doc(rust_logo))] +#![cfg_attr(doc, allow(internal_features))] +#![cfg_attr(doc, feature(rustdoc_internals))] +#![cfg_attr(doc, doc(rust_logo))] #![feature(rustc_private)] // Note: please avoid adding other feature gates where possible #![warn(rust_2018_idioms)] diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs index 766d90cf724..1b1ed0b411c 100644 --- a/compiler/rustc_codegen_gcc/src/errors.rs +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -1,6 +1,6 @@ use rustc_errors::{ - DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, - IntoDiagnosticArg, + DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, + IntoDiagnosticArg, Level, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::Span; @@ -111,9 +111,13 @@ pub(crate) struct TargetFeatureDisableOrEnable<'a> { #[help(codegen_gcc_missing_features)] pub(crate) struct MissingFeatures; -impl IntoDiagnostic<'_, ErrorGuaranteed> for TargetFeatureDisableOrEnable<'_> { - fn into_diagnostic(self, dcx: &'_ DiagCtxt) -> DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::codegen_gcc_target_feature_disable_or_enable); +impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for TargetFeatureDisableOrEnable<'_> { + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = DiagnosticBuilder::new( + dcx, + level, + fluent::codegen_gcc_target_feature_disable_or_enable + ); if let Some(span) = self.span { diag.set_span(span); }; diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 671a225259a..8db97d577ca 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -4,9 +4,7 @@ use std::path::Path; use crate::fluent_generated as fluent; use rustc_data_structures::small_c_str::SmallCStr; -use rustc_errors::{ - DiagCtxt, DiagnosticBuilder, EmissionGuarantee, ErrorGuaranteed, FatalError, IntoDiagnostic, -}; +use rustc_errors::{DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::Span; @@ -101,13 +99,14 @@ pub(crate) struct DynamicLinkingWithLTO; pub(crate) struct ParseTargetMachineConfig<'a>(pub LlvmError<'a>); -impl IntoDiagnostic<'_, FatalError> for ParseTargetMachineConfig<'_> { - fn into_diagnostic(self, dcx: &'_ DiagCtxt) -> DiagnosticBuilder<'_, FatalError> { - let diag: DiagnosticBuilder<'_, FatalError> = self.0.into_diagnostic(dcx); - let (message, _) = diag.styled_message().first().expect("`LlvmError` with no message"); +impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for ParseTargetMachineConfig<'_> { + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let diag: DiagnosticBuilder<'_, G> = self.0.into_diagnostic(dcx, level); + let (message, _) = diag.messages().first().expect("`LlvmError` with no message"); let message = dcx.eagerly_translate_to_string(message.clone(), diag.args()); - let mut diag = dcx.struct_almost_fatal(fluent::codegen_llvm_parse_target_machine_config); + let mut diag = + DiagnosticBuilder::new(dcx, level, fluent::codegen_llvm_parse_target_machine_config); diag.set_arg("error", message); diag } @@ -123,9 +122,13 @@ pub(crate) struct TargetFeatureDisableOrEnable<'a> { #[help(codegen_llvm_missing_features)] pub(crate) struct MissingFeatures; -impl IntoDiagnostic<'_, ErrorGuaranteed> for TargetFeatureDisableOrEnable<'_> { - fn into_diagnostic(self, dcx: &'_ DiagCtxt) -> DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::codegen_llvm_target_feature_disable_or_enable); +impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for TargetFeatureDisableOrEnable<'_> { + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = DiagnosticBuilder::new( + dcx, + level, + fluent::codegen_llvm_target_feature_disable_or_enable, + ); if let Some(span) = self.span { diag.set_span(span); }; @@ -184,7 +187,7 @@ pub enum LlvmError<'a> { pub(crate) struct WithLlvmError<'a>(pub LlvmError<'a>, pub String); impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for WithLlvmError<'_> { - fn into_diagnostic(self, dcx: &'_ DiagCtxt) -> DiagnosticBuilder<'_, G> { + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { use LlvmError::*; let msg_with_llvm_err = match &self.0 { WriteOutput { .. } => fluent::codegen_llvm_write_output_with_llvm_err, @@ -201,7 +204,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for WithLlvmError<'_> { PrepareThinLtoModule => fluent::codegen_llvm_prepare_thin_lto_module_with_llvm_err, ParseBitcode => fluent::codegen_llvm_parse_bitcode_with_llvm_err, }; - let mut diag = self.0.into_diagnostic(dcx); + let mut diag = self.0.into_diagnostic(dcx, level); diag.set_primary_message(msg_with_llvm_err); diag.set_arg("llvm_err", self.1); diag diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 3c42eb21d07..a81056ed3ad 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -8,7 +8,6 @@ #![feature(rustdoc_internals)] #![doc(rust_logo)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![cfg_attr(bootstrap, feature(c_str_literals))] #![feature(exact_size_is_empty)] #![feature(extern_types)] #![feature(hash_raw_entry)] diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 0442bef8a44..53ae085a721 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -15,7 +15,7 @@ use rustc_data_structures::profiling::{SelfProfilerRef, VerboseTimingGuard}; use rustc_data_structures::sync::Lrc; use rustc_errors::emitter::Emitter; use rustc_errors::{translation::Translate, DiagCtxt, DiagnosticId, FatalError, Level}; -use rustc_errors::{DiagnosticMessage, Style}; +use rustc_errors::{DiagnosticBuilder, DiagnosticMessage, Style}; use rustc_fs_util::link_or_copy; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_incremental::{ @@ -986,7 +986,7 @@ pub struct CguMessage; type DiagnosticArgName<'source> = Cow<'source, str>; struct Diagnostic { - msg: Vec<(DiagnosticMessage, Style)>, + msgs: Vec<(DiagnosticMessage, Style)>, args: FxHashMap<DiagnosticArgName<'static>, rustc_errors::DiagnosticArgValue<'static>>, code: Option<DiagnosticId>, lvl: Level, @@ -1799,14 +1799,14 @@ impl Emitter for SharedEmitter { let args: FxHashMap<Cow<'_, str>, rustc_errors::DiagnosticArgValue<'_>> = diag.args().map(|(name, arg)| (name.clone(), arg.clone())).collect(); drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic { - msg: diag.message.clone(), + msgs: diag.messages.clone(), args: args.clone(), code: diag.code.clone(), lvl: diag.level(), }))); for child in &diag.children { drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic { - msg: child.message.clone(), + msgs: child.messages.clone(), args: args.clone(), code: None, lvl: child.level, @@ -1838,7 +1838,7 @@ impl SharedEmitterMain { match message { Ok(SharedEmitterMessage::Diagnostic(diag)) => { let dcx = sess.dcx(); - let mut d = rustc_errors::Diagnostic::new_with_messages(diag.lvl, diag.msg); + let mut d = rustc_errors::Diagnostic::new_with_messages(diag.lvl, diag.msgs); if let Some(code) = diag.code { d.code(code); } @@ -1846,14 +1846,14 @@ impl SharedEmitterMain { dcx.emit_diagnostic(d); } Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => { - let msg = msg.strip_prefix("error: ").unwrap_or(&msg).to_string(); - - let mut err = match level { - Level::Error { lint: false } => sess.struct_err(msg).forget_guarantee(), - Level::Warning(_) => sess.struct_warn(msg), - Level::Note => sess.struct_note(msg), + let err_level = match level { + Level::Error { lint: false } => rustc_errors::Level::Error { lint: false }, + Level::Warning(_) => rustc_errors::Level::Warning(None), + Level::Note => rustc_errors::Level::Note, _ => bug!("Invalid inline asm diagnostic level"), }; + let msg = msg.strip_prefix("error: ").unwrap_or(&msg).to_string(); + let mut err = DiagnosticBuilder::<()>::new(sess.dcx(), err_level, msg); // If the cookie is 0 then we don't have span information. if cookie != 0 { diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index dda30046bfb..2ecc5ad4fe4 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -15,7 +15,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher}; use rustc_hir::def_id::DefId; use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData}; -use rustc_hir::{CoroutineKind, CoroutineSource, Mutability}; +use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, Mutability}; use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; use rustc_middle::ty::{self, ExistentialProjection, ParamEnv, Ty, TyCtxt}; use rustc_middle::ty::{GenericArgKind, GenericArgsRef}; @@ -560,15 +560,31 @@ pub fn push_item_name(tcx: TyCtxt<'_>, def_id: DefId, qualified: bool, output: & fn coroutine_kind_label(coroutine_kind: Option<CoroutineKind>) -> &'static str { match coroutine_kind { - Some(CoroutineKind::Gen(CoroutineSource::Block)) => "gen_block", - Some(CoroutineKind::Gen(CoroutineSource::Closure)) => "gen_closure", - Some(CoroutineKind::Gen(CoroutineSource::Fn)) => "gen_fn", - Some(CoroutineKind::Async(CoroutineSource::Block)) => "async_block", - Some(CoroutineKind::Async(CoroutineSource::Closure)) => "async_closure", - Some(CoroutineKind::Async(CoroutineSource::Fn)) => "async_fn", - Some(CoroutineKind::AsyncGen(CoroutineSource::Block)) => "async_gen_block", - Some(CoroutineKind::AsyncGen(CoroutineSource::Closure)) => "async_gen_closure", - Some(CoroutineKind::AsyncGen(CoroutineSource::Fn)) => "async_gen_fn", + Some(CoroutineKind::Desugared(CoroutineDesugaring::Gen, CoroutineSource::Block)) => { + "gen_block" + } + Some(CoroutineKind::Desugared(CoroutineDesugaring::Gen, CoroutineSource::Closure)) => { + "gen_closure" + } + Some(CoroutineKind::Desugared(CoroutineDesugaring::Gen, CoroutineSource::Fn)) => "gen_fn", + Some(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Block)) => { + "async_block" + } + Some(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Closure)) => { + "async_closure" + } + Some(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Fn)) => { + "async_fn" + } + Some(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, CoroutineSource::Block)) => { + "async_gen_block" + } + Some(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, CoroutineSource::Closure)) => { + "async_gen_closure" + } + Some(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, CoroutineSource::Fn)) => { + "async_gen_fn" + } Some(CoroutineKind::Coroutine) => "coroutine", None => "closure", } diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 668d39afbda..2b628d2aa69 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -4,8 +4,8 @@ use crate::assert_module_sources::CguReuse; use crate::back::command::Command; use crate::fluent_generated as fluent; use rustc_errors::{ - DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, - IntoDiagnosticArg, + DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, + IntoDiagnosticArg, Level, }; use rustc_macros::Diagnostic; use rustc_middle::ty::layout::LayoutError; @@ -209,192 +209,193 @@ pub enum LinkRlibError { pub struct ThorinErrorWrapper(pub thorin::Error); -impl IntoDiagnostic<'_> for ThorinErrorWrapper { - fn into_diagnostic(self, dcx: &DiagCtxt) -> DiagnosticBuilder<'_, ErrorGuaranteed> { +impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for ThorinErrorWrapper { + fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let build = |msg| DiagnosticBuilder::new(dcx, level, msg); let mut diag; match self.0 { thorin::Error::ReadInput(_) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_read_input_failure); + diag = build(fluent::codegen_ssa_thorin_read_input_failure); diag } thorin::Error::ParseFileKind(_) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_input_file_kind); + diag = build(fluent::codegen_ssa_thorin_parse_input_file_kind); diag } thorin::Error::ParseObjectFile(_) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_input_object_file); + diag = build(fluent::codegen_ssa_thorin_parse_input_object_file); diag } thorin::Error::ParseArchiveFile(_) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_input_archive_file); + diag = build(fluent::codegen_ssa_thorin_parse_input_archive_file); diag } thorin::Error::ParseArchiveMember(_) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_archive_member); + diag = build(fluent::codegen_ssa_thorin_parse_archive_member); diag } thorin::Error::InvalidInputKind => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_invalid_input_kind); + diag = build(fluent::codegen_ssa_thorin_invalid_input_kind); diag } thorin::Error::DecompressData(_) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_decompress_data); + diag = build(fluent::codegen_ssa_thorin_decompress_data); diag } thorin::Error::NamelessSection(_, offset) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_section_without_name); + diag = build(fluent::codegen_ssa_thorin_section_without_name); diag.set_arg("offset", format!("0x{offset:08x}")); diag } thorin::Error::RelocationWithInvalidSymbol(section, offset) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_relocation_with_invalid_symbol); + diag = build(fluent::codegen_ssa_thorin_relocation_with_invalid_symbol); diag.set_arg("section", section); diag.set_arg("offset", format!("0x{offset:08x}")); diag } thorin::Error::MultipleRelocations(section, offset) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_multiple_relocations); + diag = build(fluent::codegen_ssa_thorin_multiple_relocations); diag.set_arg("section", section); diag.set_arg("offset", format!("0x{offset:08x}")); diag } thorin::Error::UnsupportedRelocation(section, offset) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_unsupported_relocation); + diag = build(fluent::codegen_ssa_thorin_unsupported_relocation); diag.set_arg("section", section); diag.set_arg("offset", format!("0x{offset:08x}")); diag } thorin::Error::MissingDwoName(id) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_missing_dwo_name); + diag = build(fluent::codegen_ssa_thorin_missing_dwo_name); diag.set_arg("id", format!("0x{id:08x}")); diag } thorin::Error::NoCompilationUnits => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_no_compilation_units); + diag = build(fluent::codegen_ssa_thorin_no_compilation_units); diag } thorin::Error::NoDie => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_no_die); + diag = build(fluent::codegen_ssa_thorin_no_die); diag } thorin::Error::TopLevelDieNotUnit => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_top_level_die_not_unit); + diag = build(fluent::codegen_ssa_thorin_top_level_die_not_unit); diag } thorin::Error::MissingRequiredSection(section) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_missing_required_section); + diag = build(fluent::codegen_ssa_thorin_missing_required_section); diag.set_arg("section", section); diag } thorin::Error::ParseUnitAbbreviations(_) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_unit_abbreviations); + diag = build(fluent::codegen_ssa_thorin_parse_unit_abbreviations); diag } thorin::Error::ParseUnitAttribute(_) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_unit_attribute); + diag = build(fluent::codegen_ssa_thorin_parse_unit_attribute); diag } thorin::Error::ParseUnitHeader(_) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_unit_header); + diag = build(fluent::codegen_ssa_thorin_parse_unit_header); diag } thorin::Error::ParseUnit(_) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_unit); + diag = build(fluent::codegen_ssa_thorin_parse_unit); diag } thorin::Error::IncompatibleIndexVersion(section, format, actual) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_incompatible_index_version); + diag = build(fluent::codegen_ssa_thorin_incompatible_index_version); diag.set_arg("section", section); diag.set_arg("actual", actual); diag.set_arg("format", format); diag } thorin::Error::OffsetAtIndex(_, index) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_offset_at_index); + diag = build(fluent::codegen_ssa_thorin_offset_at_index); diag.set_arg("index", index); diag } thorin::Error::StrAtOffset(_, offset) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_str_at_offset); + diag = build(fluent::codegen_ssa_thorin_str_at_offset); diag.set_arg("offset", format!("0x{offset:08x}")); diag } thorin::Error::ParseIndex(_, section) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_index); + diag = build(fluent::codegen_ssa_thorin_parse_index); diag.set_arg("section", section); diag } thorin::Error::UnitNotInIndex(unit) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_unit_not_in_index); + diag = build(fluent::codegen_ssa_thorin_unit_not_in_index); diag.set_arg("unit", format!("0x{unit:08x}")); diag } thorin::Error::RowNotInIndex(_, row) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_row_not_in_index); + diag = build(fluent::codegen_ssa_thorin_row_not_in_index); diag.set_arg("row", row); diag } thorin::Error::SectionNotInRow => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_section_not_in_row); + diag = build(fluent::codegen_ssa_thorin_section_not_in_row); diag } thorin::Error::EmptyUnit(unit) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_empty_unit); + diag = build(fluent::codegen_ssa_thorin_empty_unit); diag.set_arg("unit", format!("0x{unit:08x}")); diag } thorin::Error::MultipleDebugInfoSection => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_multiple_debug_info_section); + diag = build(fluent::codegen_ssa_thorin_multiple_debug_info_section); diag } thorin::Error::MultipleDebugTypesSection => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_multiple_debug_types_section); + diag = build(fluent::codegen_ssa_thorin_multiple_debug_types_section); diag } thorin::Error::NotSplitUnit => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_not_split_unit); + diag = build(fluent::codegen_ssa_thorin_not_split_unit); diag } thorin::Error::DuplicateUnit(unit) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_duplicate_unit); + diag = build(fluent::codegen_ssa_thorin_duplicate_unit); diag.set_arg("unit", format!("0x{unit:08x}")); diag } thorin::Error::MissingReferencedUnit(unit) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_missing_referenced_unit); + diag = build(fluent::codegen_ssa_thorin_missing_referenced_unit); diag.set_arg("unit", format!("0x{unit:08x}")); diag } thorin::Error::NoOutputObjectCreated => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_not_output_object_created); + diag = build(fluent::codegen_ssa_thorin_not_output_object_created); diag } thorin::Error::MixedInputEncodings => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_mixed_input_encodings); + diag = build(fluent::codegen_ssa_thorin_mixed_input_encodings); diag } thorin::Error::Io(e) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_io); + diag = build(fluent::codegen_ssa_thorin_io); diag.set_arg("error", format!("{e}")); diag } thorin::Error::ObjectRead(e) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_object_read); + diag = build(fluent::codegen_ssa_thorin_object_read); diag.set_arg("error", format!("{e}")); diag } thorin::Error::ObjectWrite(e) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_object_write); + diag = build(fluent::codegen_ssa_thorin_object_write); diag.set_arg("error", format!("{e}")); diag } thorin::Error::GimliRead(e) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_gimli_read); + diag = build(fluent::codegen_ssa_thorin_gimli_read); diag.set_arg("error", format!("{e}")); diag } thorin::Error::GimliWrite(e) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_gimli_write); + diag = build(fluent::codegen_ssa_thorin_gimli_write); diag.set_arg("error", format!("{e}")); diag } @@ -410,9 +411,9 @@ pub struct LinkingFailed<'a> { pub escaped_output: String, } -impl IntoDiagnostic<'_> for LinkingFailed<'_> { - fn into_diagnostic(self, dcx: &DiagCtxt) -> DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::codegen_ssa_linking_failed); +impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for LinkingFailed<'_> { + fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = DiagnosticBuilder::new(dcx, level, fluent::codegen_ssa_linking_failed); diag.set_arg("linker_path", format!("{}", self.linker_path.display())); diag.set_arg("exit_status", format!("{}", self.exit_status)); diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index 8f18cd78d3f..2cafbb9331d 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -6,7 +6,7 @@ use rustc_middle::mir::AssertKind; use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::TyCtxt; use rustc_middle::ty::{layout::LayoutError, ConstInt}; -use rustc_span::{ErrorGuaranteed, Span, Symbol, DUMMY_SP}; +use rustc_span::{Span, Symbol, DUMMY_SP}; use super::{CompileTimeInterpreter, InterpCx}; use crate::errors::{self, FrameNote, ReportErrorExt}; @@ -133,7 +133,7 @@ pub(super) fn report<'tcx, C, F, E>( where C: FnOnce() -> (Span, Vec<FrameNote>), F: FnOnce(Span, Vec<FrameNote>) -> E, - E: IntoDiagnostic<'tcx, ErrorGuaranteed>, + E: IntoDiagnostic<'tcx>, { // Special handling for certain errors match error { diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index adce1f5430f..eb9bf52676a 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -1,6 +1,6 @@ use rustc_errors::{ DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, - IntoDiagnostic, + IntoDiagnostic, Level, }; use rustc_hir::ConstContext; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; @@ -875,7 +875,10 @@ impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> { | InvalidProgramInfo::AlreadyReported(_) | InvalidProgramInfo::ConstPropNonsense => {} InvalidProgramInfo::Layout(e) => { - let diag: DiagnosticBuilder<'_, ()> = e.into_diagnostic().into_diagnostic(dcx); + // The level doesn't matter, `diag` is consumed without it being used. + let dummy_level = Level::Bug; + let diag: DiagnosticBuilder<'_, ()> = + e.into_diagnostic().into_diagnostic(dcx, dummy_level); for (name, val) in diag.args() { builder.set_arg(name.clone(), val.clone()); } diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 3fde6ae9b8e..7ff970661d6 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -165,6 +165,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // We need to handle `extern static`. match self.tcx.try_get_global_alloc(alloc_id) { Some(GlobalAlloc::Static(def_id)) if self.tcx.is_thread_local_static(def_id) => { + // Thread-local statics do not have a constant address. They *must* be accessed via + // `ThreadLocalRef`; we can never have a pointer to them as a regular constant value. bug!("global memory cannot point to thread-local static") } Some(GlobalAlloc::Static(def_id)) if self.tcx.is_foreign_item(def_id) => { @@ -539,6 +541,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { None => throw_ub!(PointerUseAfterFree(id, CheckInAllocMsg::MemoryAccessTest)), Some(GlobalAlloc::Static(def_id)) => { assert!(self.tcx.is_static(def_id)); + // Thread-local statics do not have a constant address. They *must* be accessed via + // `ThreadLocalRef`; we can never have a pointer to them as a regular constant value. assert!(!self.tcx.is_thread_local_static(def_id)); // Notice that every static has two `AllocId` that will resolve to the same // thing here: one maps to `GlobalAlloc::Static`, this is the "lazy" ID, @@ -740,6 +744,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { match self.tcx.try_get_global_alloc(id) { Some(GlobalAlloc::Static(def_id)) => { assert!(self.tcx.is_static(def_id)); + // Thread-local statics do not have a constant address. They *must* be accessed via + // `ThreadLocalRef`; we can never have a pointer to them as a regular constant value. assert!(!self.tcx.is_thread_local_static(def_id)); // Use size and align of the type. let ty = self diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 949606ed6c9..bf7adf8f44c 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -5,17 +5,15 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_index::bit_set::BitSet; use rustc_infer::infer::TyCtxtInferExt; -use rustc_infer::traits::{ImplSource, Obligation, ObligationCause}; +use rustc_infer::traits::ObligationCause; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; -use rustc_middle::traits::BuiltinImplSource; -use rustc_middle::ty::GenericArgs; -use rustc_middle::ty::{self, adjustment::PointerCoercion, Instance, InstanceDef, Ty, TyCtxt}; -use rustc_middle::ty::{TraitRef, TypeVisitableExt}; +use rustc_middle::ty::{self, adjustment::PointerCoercion, Ty, TyCtxt}; +use rustc_middle::ty::{Instance, InstanceDef, TypeVisitableExt}; use rustc_mir_dataflow::Analysis; use rustc_span::{sym, Span, Symbol}; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; -use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt, SelectionContext}; +use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt}; use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitor}; use std::mem; @@ -464,8 +462,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { Rvalue::Aggregate(kind, ..) => { if let AggregateKind::Coroutine(def_id, ..) = kind.as_ref() - && let Some(coroutine_kind @ hir::CoroutineKind::Async(..)) = - self.tcx.coroutine_kind(def_id) + && let Some( + coroutine_kind @ hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Async, + _, + ), + ) = self.tcx.coroutine_kind(def_id) { self.check_op(ops::Coroutine(coroutine_kind)); } @@ -752,143 +754,43 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { infcx.err_ctxt().report_fulfillment_errors(errors); } + let mut is_trait = false; // Attempting to call a trait method? - // FIXME(effects) do we need this? - if let Some(trait_id) = tcx.trait_of_item(callee) { + if tcx.trait_of_item(callee).is_some() { trace!("attempting to call a trait method"); - if !self.tcx.features().const_trait_impl { + // trait method calls are only permitted when `effects` is enabled. + // we don't error, since that is handled by typeck. We try to resolve + // the trait into the concrete method, and uses that for const stability + // checks. + // FIXME(effects) we might consider moving const stability checks to typeck as well. + if tcx.features().effects { + is_trait = true; + + if let Ok(Some(instance)) = + Instance::resolve(tcx, param_env, callee, fn_args) + && let InstanceDef::Item(def) = instance.def + { + // Resolve a trait method call to its concrete implementation, which may be in a + // `const` trait impl. This is only used for the const stability check below, since + // we want to look at the concrete impl's stability. + fn_args = instance.args; + callee = def; + } + } else { self.check_op(ops::FnCallNonConst { caller, callee, args: fn_args, span: *fn_span, call_source: *call_source, - feature: Some(sym::const_trait_impl), + feature: Some(if tcx.features().const_trait_impl { + sym::effects + } else { + sym::const_trait_impl + }), }); return; } - - let trait_ref = TraitRef::from_method(tcx, trait_id, fn_args); - let obligation = - Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref); - - let implsrc = { - let infcx = tcx.infer_ctxt().build(); - let mut selcx = SelectionContext::new(&infcx); - selcx.select(&obligation) - }; - - match implsrc { - Ok(Some(ImplSource::Param(_))) if tcx.features().effects => { - debug!( - "const_trait_impl: provided {:?} via where-clause in {:?}", - trait_ref, param_env - ); - return; - } - // Closure: Fn{Once|Mut} - Ok(Some(ImplSource::Builtin(BuiltinImplSource::Misc, _))) - if trait_ref.self_ty().is_closure() - && tcx.fn_trait_kind_from_def_id(trait_id).is_some() => - { - let ty::Closure(closure_def_id, fn_args) = *trait_ref.self_ty().kind() - else { - unreachable!() - }; - if !tcx.is_const_fn_raw(closure_def_id) { - self.check_op(ops::FnCallNonConst { - caller, - callee, - args: fn_args, - span: *fn_span, - call_source: *call_source, - feature: None, - }); - - return; - } - } - Ok(Some(ImplSource::UserDefined(data))) => { - let callee_name = tcx.item_name(callee); - - if let hir::Constness::NotConst = tcx.constness(data.impl_def_id) { - self.check_op(ops::FnCallNonConst { - caller, - callee, - args: fn_args, - span: *fn_span, - call_source: *call_source, - feature: None, - }); - return; - } - - if let Some(&did) = tcx - .associated_item_def_ids(data.impl_def_id) - .iter() - .find(|did| tcx.item_name(**did) == callee_name) - { - // using internal args is ok here, since this is only - // used for the `resolve` call below - fn_args = GenericArgs::identity_for_item(tcx, did); - callee = did; - } - } - _ if !tcx.is_const_fn_raw(callee) => { - // At this point, it is only legal when the caller is in a trait - // marked with #[const_trait], and the callee is in the same trait. - let mut nonconst_call_permission = false; - if let Some(callee_trait) = tcx.trait_of_item(callee) - && tcx.has_attr(callee_trait, sym::const_trait) - && Some(callee_trait) == tcx.trait_of_item(caller.to_def_id()) - // Can only call methods when it's `<Self as TheTrait>::f`. - && tcx.types.self_param == fn_args.type_at(0) - { - nonconst_call_permission = true; - } - - if !nonconst_call_permission { - let obligation = Obligation::new( - tcx, - ObligationCause::dummy_with_span(*fn_span), - param_env, - trait_ref, - ); - - // improve diagnostics by showing what failed. Our requirements are stricter this time - // as we are going to error again anyways. - let infcx = tcx.infer_ctxt().build(); - if let Err(e) = implsrc { - infcx.err_ctxt().report_selection_error( - obligation.clone(), - &obligation, - &e, - ); - } - - self.check_op(ops::FnCallNonConst { - caller, - callee, - args: fn_args, - span: *fn_span, - call_source: *call_source, - feature: None, - }); - return; - } - } - _ => {} - } - - // Resolve a trait method call to its concrete implementation, which may be in a - // `const` trait impl. - let instance = Instance::resolve(tcx, param_env, callee, fn_args); - debug!("Resolving ({:?}) -> {:?}", callee, instance); - if let Ok(Some(func)) = instance { - if let InstanceDef::Item(def) = func.def { - callee = def; - } - } } // At this point, we are calling a function, `callee`, whose `DefId` is known... @@ -921,21 +823,16 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { return; } - if !tcx.is_const_fn_raw(callee) { - if !tcx.is_const_default_method(callee) { - // To get to here we must have already found a const impl for the - // trait, but for it to still be non-const can be that the impl is - // using default method bodies. - self.check_op(ops::FnCallNonConst { - caller, - callee, - args: fn_args, - span: *fn_span, - call_source: *call_source, - feature: None, - }); - return; - } + if !tcx.is_const_fn_raw(callee) && !is_trait { + self.check_op(ops::FnCallNonConst { + caller, + callee, + args: fn_args, + span: *fn_span, + call_source: *call_source, + feature: None, + }); + return; } // If the `const fn` we are trying to call is not const-stable, ensure that we have diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs index 2de6362b9fe..532cd9c261f 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -2,7 +2,7 @@ use hir::def_id::LocalDefId; use hir::{ConstContext, LangItem}; -use rustc_errors::{error_code, DiagnosticBuilder, ErrorGuaranteed}; +use rustc_errors::{error_code, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_infer::infer::TyCtxtInferExt; @@ -48,11 +48,7 @@ pub trait NonConstOp<'tcx>: std::fmt::Debug { DiagnosticImportance::Primary } - fn build_error( - &self, - ccx: &ConstCx<'_, 'tcx>, - span: Span, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>; + fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx>; } #[derive(Debug)] @@ -66,11 +62,7 @@ impl<'tcx> NonConstOp<'tcx> for FloatingPointOp { } } - fn build_error( - &self, - ccx: &ConstCx<'_, 'tcx>, - span: Span, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { feature_err( &ccx.tcx.sess.parse_sess, sym::const_fn_floating_point_arithmetic, @@ -84,11 +76,7 @@ impl<'tcx> NonConstOp<'tcx> for FloatingPointOp { #[derive(Debug)] pub struct FnCallIndirect; impl<'tcx> NonConstOp<'tcx> for FnCallIndirect { - fn build_error( - &self, - ccx: &ConstCx<'_, 'tcx>, - span: Span, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { ccx.tcx.sess.create_err(errors::UnallowedFnPointerCall { span, kind: ccx.const_kind() }) } } @@ -105,11 +93,7 @@ pub struct FnCallNonConst<'tcx> { } impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { - fn build_error( - &self, - ccx: &ConstCx<'_, 'tcx>, - _: Span, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> DiagnosticBuilder<'tcx> { let FnCallNonConst { caller, callee, args, span, call_source, feature } = *self; let ConstCx { tcx, param_env, .. } = *ccx; @@ -331,11 +315,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { pub struct FnCallUnstable(pub DefId, pub Option<Symbol>); impl<'tcx> NonConstOp<'tcx> for FnCallUnstable { - fn build_error( - &self, - ccx: &ConstCx<'_, 'tcx>, - span: Span, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { let FnCallUnstable(def_id, feature) = *self; let mut err = ccx @@ -359,20 +339,24 @@ impl<'tcx> NonConstOp<'tcx> for FnCallUnstable { pub struct Coroutine(pub hir::CoroutineKind); impl<'tcx> NonConstOp<'tcx> for Coroutine { fn status_in_item(&self, _: &ConstCx<'_, 'tcx>) -> Status { - if let hir::CoroutineKind::Async(hir::CoroutineSource::Block) = self.0 { + if let hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Async, + hir::CoroutineSource::Block, + ) = self.0 + { Status::Unstable(sym::const_async_blocks) } else { Status::Forbidden } } - fn build_error( - &self, - ccx: &ConstCx<'_, 'tcx>, - span: Span, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { let msg = format!("{:#}s are not allowed in {}s", self.0, ccx.const_kind()); - if let hir::CoroutineKind::Async(hir::CoroutineSource::Block) = self.0 { + if let hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Async, + hir::CoroutineSource::Block, + ) = self.0 + { ccx.tcx.sess.create_feature_err( errors::UnallowedOpInConstContext { span, msg }, sym::const_async_blocks, @@ -386,11 +370,7 @@ impl<'tcx> NonConstOp<'tcx> for Coroutine { #[derive(Debug)] pub struct HeapAllocation; impl<'tcx> NonConstOp<'tcx> for HeapAllocation { - fn build_error( - &self, - ccx: &ConstCx<'_, 'tcx>, - span: Span, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { ccx.tcx.sess.create_err(errors::UnallowedHeapAllocations { span, kind: ccx.const_kind(), @@ -402,11 +382,7 @@ impl<'tcx> NonConstOp<'tcx> for HeapAllocation { #[derive(Debug)] pub struct InlineAsm; impl<'tcx> NonConstOp<'tcx> for InlineAsm { - fn build_error( - &self, - ccx: &ConstCx<'_, 'tcx>, - span: Span, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { ccx.tcx.sess.create_err(errors::UnallowedInlineAsm { span, kind: ccx.const_kind() }) } } @@ -417,11 +393,7 @@ pub struct LiveDrop<'tcx> { pub dropped_ty: Ty<'tcx>, } impl<'tcx> NonConstOp<'tcx> for LiveDrop<'tcx> { - fn build_error( - &self, - ccx: &ConstCx<'_, 'tcx>, - span: Span, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { ccx.tcx.sess.create_err(errors::LiveDrop { span, dropped_ty: self.dropped_ty, @@ -444,11 +416,7 @@ impl<'tcx> NonConstOp<'tcx> for TransientCellBorrow { // not additionally emit a feature gate error if activating the feature gate won't work. DiagnosticImportance::Secondary } - fn build_error( - &self, - ccx: &ConstCx<'_, 'tcx>, - span: Span, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { ccx.tcx .sess .create_feature_err(errors::InteriorMutabilityBorrow { span }, sym::const_refs_to_cell) @@ -461,11 +429,7 @@ impl<'tcx> NonConstOp<'tcx> for TransientCellBorrow { /// it in the future for static items. pub struct CellBorrow; impl<'tcx> NonConstOp<'tcx> for CellBorrow { - fn build_error( - &self, - ccx: &ConstCx<'_, 'tcx>, - span: Span, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { // FIXME: Maybe a more elegant solution to this if else case if let hir::ConstContext::Static(_) = ccx.const_kind() { ccx.tcx.sess.create_err(errors::InteriorMutableDataRefer { @@ -502,11 +466,7 @@ impl<'tcx> NonConstOp<'tcx> for MutBorrow { DiagnosticImportance::Secondary } - fn build_error( - &self, - ccx: &ConstCx<'_, 'tcx>, - span: Span, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { match self.0 { hir::BorrowKind::Raw => ccx.tcx.sess.create_err(errors::UnallowedMutableRefsRaw { span, @@ -530,11 +490,7 @@ impl<'tcx> NonConstOp<'tcx> for TransientMutBorrow { Status::Unstable(sym::const_mut_refs) } - fn build_error( - &self, - ccx: &ConstCx<'_, 'tcx>, - span: Span, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { let kind = ccx.const_kind(); match self.0 { hir::BorrowKind::Raw => ccx.tcx.sess.create_feature_err( @@ -561,11 +517,7 @@ impl<'tcx> NonConstOp<'tcx> for MutDeref { DiagnosticImportance::Secondary } - fn build_error( - &self, - ccx: &ConstCx<'_, 'tcx>, - span: Span, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { ccx.tcx.sess.create_feature_err( errors::MutDerefErr { span, kind: ccx.const_kind() }, sym::const_mut_refs, @@ -577,11 +529,7 @@ impl<'tcx> NonConstOp<'tcx> for MutDeref { #[derive(Debug)] pub struct PanicNonStr; impl<'tcx> NonConstOp<'tcx> for PanicNonStr { - fn build_error( - &self, - ccx: &ConstCx<'_, 'tcx>, - span: Span, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { ccx.tcx.sess.create_err(errors::PanicNonStrErr { span }) } } @@ -592,11 +540,7 @@ impl<'tcx> NonConstOp<'tcx> for PanicNonStr { #[derive(Debug)] pub struct RawPtrComparison; impl<'tcx> NonConstOp<'tcx> for RawPtrComparison { - fn build_error( - &self, - ccx: &ConstCx<'_, 'tcx>, - span: Span, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { // FIXME(const_trait_impl): revert to span_bug? ccx.tcx.sess.create_err(errors::RawPtrComparisonErr { span }) } @@ -609,11 +553,7 @@ impl<'tcx> NonConstOp<'tcx> for RawMutPtrDeref { Status::Unstable(sym::const_mut_refs) } - fn build_error( - &self, - ccx: &ConstCx<'_, 'tcx>, - span: Span, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { feature_err( &ccx.tcx.sess.parse_sess, sym::const_mut_refs, @@ -629,11 +569,7 @@ impl<'tcx> NonConstOp<'tcx> for RawMutPtrDeref { #[derive(Debug)] pub struct RawPtrToIntCast; impl<'tcx> NonConstOp<'tcx> for RawPtrToIntCast { - fn build_error( - &self, - ccx: &ConstCx<'_, 'tcx>, - span: Span, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { ccx.tcx.sess.create_err(errors::RawPtrToIntErr { span }) } } @@ -650,11 +586,7 @@ impl<'tcx> NonConstOp<'tcx> for StaticAccess { } } - fn build_error( - &self, - ccx: &ConstCx<'_, 'tcx>, - span: Span, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { ccx.tcx.sess.create_err(errors::StaticAccessErr { span, kind: ccx.const_kind(), @@ -667,11 +599,7 @@ impl<'tcx> NonConstOp<'tcx> for StaticAccess { #[derive(Debug)] pub struct ThreadLocalAccess; impl<'tcx> NonConstOp<'tcx> for ThreadLocalAccess { - fn build_error( - &self, - ccx: &ConstCx<'_, 'tcx>, - span: Span, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { ccx.tcx.sess.create_err(errors::NonConstOpErr { span }) } } @@ -696,11 +624,7 @@ pub mod ty { } } - fn build_error( - &self, - ccx: &ConstCx<'_, 'tcx>, - span: Span, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { feature_err( &ccx.tcx.sess.parse_sess, sym::const_mut_refs, diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index cca5b90abb9..2f538cebaa6 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -8,9 +8,6 @@ use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt, Variance}; -use rustc_mir_dataflow::impls::MaybeStorageLive; -use rustc_mir_dataflow::storage::always_storage_live_locals; -use rustc_mir_dataflow::{Analysis, ResultsCursor}; use rustc_target::abi::{Size, FIRST_VARIANT}; use rustc_target::spec::abi::Abi; @@ -51,12 +48,6 @@ impl<'tcx> MirPass<'tcx> for Validator { Reveal::All => tcx.param_env_reveal_all_normalized(def_id), }; - let always_live_locals = always_storage_live_locals(body); - let storage_liveness = MaybeStorageLive::new(std::borrow::Cow::Owned(always_live_locals)) - .into_engine(tcx, body) - .iterate_to_fixpoint() - .into_results_cursor(body); - let can_unwind = if mir_phase <= MirPhase::Runtime(RuntimePhase::Initial) { // In this case `AbortUnwindingCalls` haven't yet been executed. true @@ -83,7 +74,6 @@ impl<'tcx> MirPass<'tcx> for Validator { mir_phase, unwind_edge_count: 0, reachable_blocks: traversal::reachable_as_bitset(body), - storage_liveness, place_cache: FxHashSet::default(), value_cache: FxHashSet::default(), can_unwind, @@ -116,7 +106,6 @@ struct CfgChecker<'a, 'tcx> { mir_phase: MirPhase, unwind_edge_count: usize, reachable_blocks: BitSet<BasicBlock>, - storage_liveness: ResultsCursor<'a, 'tcx, MaybeStorageLive<'static>>, place_cache: FxHashSet<PlaceRef<'tcx>>, value_cache: FxHashSet<u128>, // If `false`, then the MIR must not contain `UnwindAction::Continue` or @@ -294,28 +283,13 @@ impl<'a, 'tcx> CfgChecker<'a, 'tcx> { } impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { - fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) { + fn visit_local(&mut self, local: Local, _context: PlaceContext, location: Location) { if self.body.local_decls.get(local).is_none() { self.fail( location, format!("local {local:?} has no corresponding declaration in `body.local_decls`"), ); } - - if self.reachable_blocks.contains(location.block) && context.is_use() { - // We check that the local is live whenever it is used. Technically, violating this - // restriction is only UB and not actually indicative of not well-formed MIR. This means - // that an optimization which turns MIR that already has UB into MIR that fails this - // check is not necessarily wrong. However, we have no such optimizations at the moment, - // and so we include this check anyway to help us catch bugs. If you happen to write an - // optimization that might cause this to incorrectly fire, feel free to remove this - // check. - self.storage_liveness.seek_after_primary_effect(location); - let locals_with_storage = self.storage_liveness.get(); - if !locals_with_storage.contains(local) { - self.fail(location, format!("use of local {local:?}, which has no storage here")); - } - } } fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { @@ -367,26 +341,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { self.fail(location, format!("explicit `{kind:?}` is forbidden")); } } - StatementKind::StorageLive(local) => { - // We check that the local is not live when entering a `StorageLive` for it. - // Technically, violating this restriction is only UB and not actually indicative - // of not well-formed MIR. This means that an optimization which turns MIR that - // already has UB into MIR that fails this check is not necessarily wrong. However, - // we have no such optimizations at the moment, and so we include this check anyway - // to help us catch bugs. If you happen to write an optimization that might cause - // this to incorrectly fire, feel free to remove this check. - if self.reachable_blocks.contains(location.block) { - self.storage_liveness.seek_before_primary_effect(location); - let locals_with_storage = self.storage_liveness.get(); - if locals_with_storage.contains(*local) { - self.fail( - location, - format!("StorageLive({local:?}) which already has storage here"), - ); - } - } - } - StatementKind::StorageDead(_) + StatementKind::StorageLive(_) + | StatementKind::StorageDead(_) | StatementKind::Intrinsic(_) | StatementKind::Coverage(_) | StatementKind::ConstEvalCounter diff --git a/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs index cafa91c8b8b..f17a0bf26d7 100644 --- a/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs +++ b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs @@ -81,150 +81,6 @@ /// E::A, /// } /// ``` -#[cfg(bootstrap)] -#[macro_export] -macro_rules! impl_tag { - ( - impl Tag for $Self:ty; - $( - $($path:ident)::* $( { $( $fields:tt )* })?, - )* - ) => { - // Safety: - // `bits_for_tags` is called on the same `${index()}`-es as - // `into_usize` returns, thus `BITS` constant is correct. - unsafe impl $crate::tagged_ptr::Tag for $Self { - const BITS: u32 = $crate::tagged_ptr::bits_for_tags(&[ - $( - ${index()}, - $( ${ignore(path)} )* - )* - ]); - - #[inline] - fn into_usize(self) -> usize { - // This forbids use of repeating patterns (`Enum::V`&`Enum::V`, etc) - // (or at least it should, see <https://github.com/rust-lang/rust/issues/110613>) - #[forbid(unreachable_patterns)] - match self { - // `match` is doing heavy lifting here, by requiring exhaustiveness - $( - $($path)::* $( { $( $fields )* } )? => ${index()}, - )* - } - } - - #[inline] - unsafe fn from_usize(tag: usize) -> Self { - match tag { - $( - ${index()} => $($path)::* $( { $( $fields )* } )?, - )* - - // Safety: - // `into_usize` only returns `${index()}` of the same - // repetition as we are filtering above, thus if this is - // reached, the safety contract of this function was - // already breached. - _ => unsafe { - debug_assert!( - false, - "invalid tag: {tag}\ - (this is a bug in the caller of `from_usize`)" - ); - std::hint::unreachable_unchecked() - }, - } - } - - } - }; -} - -/// Implements [`Tag`] for a given type. -/// -/// You can use `impl_tag` on structs and enums. -/// You need to specify the type and all its possible values, -/// which can only be paths with optional fields. -/// -/// [`Tag`]: crate::tagged_ptr::Tag -/// -/// # Examples -/// -/// Basic usage: -/// -/// ``` -/// #![feature(macro_metavar_expr)] -/// use rustc_data_structures::{impl_tag, tagged_ptr::Tag}; -/// -/// #[derive(Copy, Clone, PartialEq, Debug)] -/// enum SomeTag { -/// A, -/// B, -/// X { v: bool }, -/// Y(bool, bool), -/// } -/// -/// impl_tag! { -/// // The type for which the `Tag` will be implemented -/// impl Tag for SomeTag; -/// // You need to specify all possible tag values: -/// SomeTag::A, // 0 -/// SomeTag::B, // 1 -/// // For variants with fields, you need to specify the fields: -/// SomeTag::X { v: true }, // 2 -/// SomeTag::X { v: false }, // 3 -/// // For tuple variants use named syntax: -/// SomeTag::Y { 0: true, 1: true }, // 4 -/// SomeTag::Y { 0: false, 1: true }, // 5 -/// SomeTag::Y { 0: true, 1: false }, // 6 -/// SomeTag::Y { 0: false, 1: false }, // 7 -/// } -/// -/// // Tag values are assigned in order: -/// assert_eq!(SomeTag::A.into_usize(), 0); -/// assert_eq!(SomeTag::X { v: false }.into_usize(), 3); -/// assert_eq!(SomeTag::Y(false, true).into_usize(), 5); -/// -/// assert_eq!(unsafe { SomeTag::from_usize(1) }, SomeTag::B); -/// assert_eq!(unsafe { SomeTag::from_usize(2) }, SomeTag::X { v: true }); -/// assert_eq!(unsafe { SomeTag::from_usize(7) }, SomeTag::Y(false, false)); -/// ``` -/// -/// Structs are supported: -/// -/// ``` -/// #![feature(macro_metavar_expr)] -/// # use rustc_data_structures::impl_tag; -/// #[derive(Copy, Clone)] -/// struct Flags { a: bool, b: bool } -/// -/// impl_tag! { -/// impl Tag for Flags; -/// Flags { a: true, b: true }, -/// Flags { a: false, b: true }, -/// Flags { a: true, b: false }, -/// Flags { a: false, b: false }, -/// } -/// ``` -/// -/// Not specifying all values results in a compile error: -/// -/// ```compile_fail,E0004 -/// #![feature(macro_metavar_expr)] -/// # use rustc_data_structures::impl_tag; -/// #[derive(Copy, Clone)] -/// enum E { -/// A, -/// B, -/// } -/// -/// impl_tag! { -/// impl Tag for E; -/// E::A, -/// } -/// ``` -#[cfg(not(bootstrap))] #[macro_export] macro_rules! impl_tag { ( diff --git a/compiler/rustc_driver_impl/src/args.rs b/compiler/rustc_driver_impl/src/args.rs index dc546da7342..b7407f5a508 100644 --- a/compiler/rustc_driver_impl/src/args.rs +++ b/compiler/rustc_driver_impl/src/args.rs @@ -28,7 +28,7 @@ pub fn arg_expand_all(early_dcx: &EarlyDiagCtxt, at_args: &[String]) -> Vec<Stri for arg in at_args { match arg_expand(arg.clone()) { Ok(arg) => args.extend(arg), - Err(err) => early_dcx.early_error(format!("Failed to load argument file: {err}")), + Err(err) => early_dcx.early_fatal(format!("Failed to load argument file: {err}")), } } args diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index d67fea7e9a4..c277304fb22 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -345,7 +345,7 @@ fn run_compiler( Ok(None) => match matches.free.len() { 0 => false, // no input: we will exit early 1 => panic!("make_input should have provided valid inputs"), - _ => default_early_dcx.early_error(format!( + _ => default_early_dcx.early_fatal(format!( "multiple input filenames provided (first two filenames are `{}` and `{}`)", matches.free[0], matches.free[1], )), @@ -376,7 +376,7 @@ fn run_compiler( } if !has_input { - early_dcx.early_error("no input filename given"); // this is fatal + early_dcx.early_fatal("no input filename given"); // this is fatal } if !sess.opts.unstable_opts.ls.is_empty() { @@ -505,9 +505,8 @@ fn make_input( if io::stdin().read_to_string(&mut src).is_err() { // Immediately stop compilation if there was an issue reading // the input (for example if the input stream is not UTF-8). - let reported = early_dcx.early_error_no_abort( - "couldn't read from stdin, as it did not contain valid UTF-8", - ); + let reported = early_dcx + .early_err("couldn't read from stdin, as it did not contain valid UTF-8"); return Err(reported); } if let Ok(path) = env::var("UNSTABLE_RUSTDOC_TEST_PATH") { @@ -567,7 +566,7 @@ fn handle_explain(early_dcx: &EarlyDiagCtxt, registry: Registry, code: &str, col } } Err(InvalidErrorCode) => { - early_dcx.early_error(format!("{code} is not a valid error code")); + early_dcx.early_fatal(format!("{code} is not a valid error code")); } } } @@ -685,7 +684,7 @@ fn list_metadata(early_dcx: &EarlyDiagCtxt, sess: &Session, metadata_loader: &dy safe_println!("{}", String::from_utf8(v).unwrap()); } Input::Str { .. } => { - early_dcx.early_error("cannot list metadata for stdin"); + early_dcx.early_fatal("cannot list metadata for stdin"); } } } @@ -839,7 +838,7 @@ fn print_crate_info( println_info!("deployment_target={}", format!("{major}.{minor}")) } else { early_dcx - .early_error("only Apple targets currently support deployment version info") + .early_fatal("only Apple targets currently support deployment version info") } } } @@ -1182,7 +1181,7 @@ pub fn handle_options(early_dcx: &EarlyDiagCtxt, args: &[String]) -> Option<geto .map(|(flag, _)| format!("{e}. Did you mean `-{flag} {opt}`?")), _ => None, }; - early_dcx.early_error(msg.unwrap_or_else(|| e.to_string())); + early_dcx.early_fatal(msg.unwrap_or_else(|| e.to_string())); }); // For all options we just parsed, we check a few aspects: @@ -1333,7 +1332,7 @@ pub fn install_ice_hook( { // the error code is already going to be reported when the panic unwinds up the stack let early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); - let _ = early_dcx.early_error_no_abort(msg.clone()); + let _ = early_dcx.early_err(msg.clone()); return; } }; @@ -1481,7 +1480,7 @@ pub fn init_rustc_env_logger(early_dcx: &EarlyDiagCtxt) { /// the values directly rather than having to set an environment variable. pub fn init_logger(early_dcx: &EarlyDiagCtxt, cfg: rustc_log::LoggerConfig) { if let Err(error) = rustc_log::init_logger(cfg) { - early_dcx.early_error(error.to_string()); + early_dcx.early_fatal(error.to_string()); } } @@ -1500,7 +1499,7 @@ pub fn main() -> ! { .enumerate() .map(|(i, arg)| { arg.into_string().unwrap_or_else(|arg| { - early_dcx.early_error(format!("argument {i} is not valid Unicode: {arg:?}")) + early_dcx.early_fatal(format!("argument {i} is not valid Unicode: {arg:?}")) }) }) .collect::<Vec<_>>(); diff --git a/compiler/rustc_error_codes/src/error_codes/E0640.md b/compiler/rustc_error_codes/src/error_codes/E0640.md index 7edd93e56a9..f7bbeb293ca 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0640.md +++ b/compiler/rustc_error_codes/src/error_codes/E0640.md @@ -1 +1,2 @@ #### This error code is internal to the compiler and will not be emitted with normal Rust code. +#### Note: this error code is no longer emitted by the compiler. diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index da266bf9c63..48e48f59a99 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -60,7 +60,7 @@ impl Emitter for AnnotateSnippetEmitterWriter { self.emit_messages_default( &diag.level, - &diag.message, + &diag.messages, &fluent_args, &diag.code, &primary_span, diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index be506806065..c226b2d41bd 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -103,7 +103,7 @@ pub struct Diagnostic { // outside of what methods in this crate themselves allow. pub(crate) level: Level, - pub message: Vec<(DiagnosticMessage, Style)>, + pub messages: Vec<(DiagnosticMessage, Style)>, pub code: Option<DiagnosticId>, pub span: MultiSpan, pub children: Vec<SubDiagnostic>, @@ -161,9 +161,8 @@ pub enum DiagnosticId { #[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)] pub struct SubDiagnostic { pub level: Level, - pub message: Vec<(DiagnosticMessage, Style)>, + pub messages: Vec<(DiagnosticMessage, Style)>, pub span: MultiSpan, - pub render_span: Option<MultiSpan>, } #[derive(Debug, PartialEq, Eq)] @@ -216,14 +215,14 @@ impl StringPart { impl Diagnostic { #[track_caller] pub fn new<M: Into<DiagnosticMessage>>(level: Level, message: M) -> Self { - Diagnostic::new_with_code(level, None, message) + Diagnostic::new_with_messages(level, vec![(message.into(), Style::NoStyle)]) } #[track_caller] pub fn new_with_messages(level: Level, messages: Vec<(DiagnosticMessage, Style)>) -> Self { Diagnostic { level, - message: messages, + messages, code: None, span: MultiSpan::new(), children: vec![], @@ -235,26 +234,6 @@ impl Diagnostic { } } - #[track_caller] - pub(crate) fn new_with_code<M: Into<DiagnosticMessage>>( - level: Level, - code: Option<DiagnosticId>, - message: M, - ) -> Self { - Diagnostic { - level, - message: vec![(message.into(), Style::NoStyle)], - code, - span: MultiSpan::new(), - children: vec![], - suggestions: Ok(vec![]), - args: Default::default(), - sort_span: DUMMY_SP, - is_lint: false, - emitted_at: DiagnosticLocation::caller(), - } - } - #[inline(always)] pub fn level(&self) -> Level { self.level @@ -445,7 +424,7 @@ impl Diagnostic { /// Add a note attached to this diagnostic. #[rustc_lint_diagnostics] pub fn note(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self { - self.sub(Level::Note, msg, MultiSpan::new(), None); + self.sub(Level::Note, msg, MultiSpan::new()); self } @@ -453,14 +432,14 @@ impl Diagnostic { &mut self, msg: Vec<(M, Style)>, ) -> &mut Self { - self.sub_with_highlights(Level::Note, msg, MultiSpan::new(), None); + self.sub_with_highlights(Level::Note, msg, MultiSpan::new()); self } /// Prints the span with a note above it. /// This is like [`Diagnostic::note()`], but it gets its own span. pub fn note_once(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self { - self.sub(Level::OnceNote, msg, MultiSpan::new(), None); + self.sub(Level::OnceNote, msg, MultiSpan::new()); self } @@ -472,7 +451,7 @@ impl Diagnostic { sp: S, msg: impl Into<SubdiagnosticMessage>, ) -> &mut Self { - self.sub(Level::Note, msg, sp.into(), None); + self.sub(Level::Note, msg, sp.into()); self } @@ -483,14 +462,14 @@ impl Diagnostic { sp: S, msg: impl Into<SubdiagnosticMessage>, ) -> &mut Self { - self.sub(Level::OnceNote, msg, sp.into(), None); + self.sub(Level::OnceNote, msg, sp.into()); self } /// Add a warning attached to this diagnostic. #[rustc_lint_diagnostics] pub fn warn(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self { - self.sub(Level::Warning(None), msg, MultiSpan::new(), None); + self.sub(Level::Warning(None), msg, MultiSpan::new()); self } @@ -502,27 +481,27 @@ impl Diagnostic { sp: S, msg: impl Into<SubdiagnosticMessage>, ) -> &mut Self { - self.sub(Level::Warning(None), msg, sp.into(), None); + self.sub(Level::Warning(None), msg, sp.into()); self } /// Add a help message attached to this diagnostic. #[rustc_lint_diagnostics] pub fn help(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self { - self.sub(Level::Help, msg, MultiSpan::new(), None); + self.sub(Level::Help, msg, MultiSpan::new()); self } /// Prints the span with a help above it. /// This is like [`Diagnostic::help()`], but it gets its own span. pub fn help_once(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self { - self.sub(Level::OnceHelp, msg, MultiSpan::new(), None); + self.sub(Level::OnceHelp, msg, MultiSpan::new()); self } /// Add a help message attached to this diagnostic with a customizable highlighted message. pub fn highlighted_help(&mut self, msg: Vec<(String, Style)>) -> &mut Self { - self.sub_with_highlights(Level::Help, msg, MultiSpan::new(), None); + self.sub_with_highlights(Level::Help, msg, MultiSpan::new()); self } @@ -534,7 +513,7 @@ impl Diagnostic { sp: S, msg: impl Into<SubdiagnosticMessage>, ) -> &mut Self { - self.sub(Level::Help, msg, sp.into(), None); + self.sub(Level::Help, msg, sp.into()); self } @@ -925,7 +904,7 @@ impl Diagnostic { } pub fn set_primary_message(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self { - self.message[0] = (msg.into(), Style::NoStyle); + self.messages[0] = (msg.into(), Style::NoStyle); self } @@ -952,8 +931,8 @@ impl Diagnostic { self.args = args; } - pub fn styled_message(&self) -> &[(DiagnosticMessage, Style)] { - &self.message + pub fn messages(&self) -> &[(DiagnosticMessage, Style)] { + &self.messages } /// Helper function that takes a `SubdiagnosticMessage` and returns a `DiagnosticMessage` by @@ -964,7 +943,7 @@ impl Diagnostic { attr: impl Into<SubdiagnosticMessage>, ) -> DiagnosticMessage { let msg = - self.message.iter().map(|(msg, _)| msg).next().expect("diagnostic with no messages"); + self.messages.iter().map(|(msg, _)| msg).next().expect("diagnostic with no messages"); msg.with_subdiagnostic_message(attr.into()) } @@ -972,21 +951,14 @@ impl Diagnostic { /// public methods above. /// /// Used by `proc_macro_server` for implementing `server::Diagnostic`. - pub fn sub( - &mut self, - level: Level, - message: impl Into<SubdiagnosticMessage>, - span: MultiSpan, - render_span: Option<MultiSpan>, - ) { + pub fn sub(&mut self, level: Level, message: impl Into<SubdiagnosticMessage>, span: MultiSpan) { let sub = SubDiagnostic { level, - message: vec![( + messages: vec![( self.subdiagnostic_message_to_diagnostic_message(message), Style::NoStyle, )], span, - render_span, }; self.children.push(sub); } @@ -996,15 +968,14 @@ impl Diagnostic { fn sub_with_highlights<M: Into<SubdiagnosticMessage>>( &mut self, level: Level, - message: Vec<(M, Style)>, + messages: Vec<(M, Style)>, span: MultiSpan, - render_span: Option<MultiSpan>, ) { - let message = message + let messages = messages .into_iter() .map(|m| (self.subdiagnostic_message_to_diagnostic_message(m.0), m.1)) .collect(); - let sub = SubDiagnostic { level, message, span, render_span }; + let sub = SubDiagnostic { level, messages, span }; self.children.push(sub); } @@ -1022,7 +993,7 @@ impl Diagnostic { ) { ( &self.level, - &self.message, + &self.messages, self.args().collect(), &self.code, &self.span, diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index 3f66af1fcff..4703e71523d 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -15,13 +15,13 @@ use std::ops::{Deref, DerefMut}; use std::panic; use std::thread::panicking; -/// Trait implemented by error types. This should not be implemented manually. Instead, use +/// Trait implemented by error types. This is rarely implemented manually. Instead, use /// `#[derive(Diagnostic)]` -- see [rustc_macros::Diagnostic]. #[rustc_diagnostic_item = "IntoDiagnostic"] pub trait IntoDiagnostic<'a, G: EmissionGuarantee = ErrorGuaranteed> { /// Write out as a diagnostic out of `DiagCtxt`. #[must_use] - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, G>; + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G>; } impl<'a, T, G> IntoDiagnostic<'a, G> for Spanned<T> @@ -29,8 +29,8 @@ where T: IntoDiagnostic<'a, G>, G: EmissionGuarantee, { - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, G> { - let mut diag = self.node.into_diagnostic(dcx); + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { + let mut diag = self.node.into_diagnostic(dcx, level); diag.set_span(self.span); diag } @@ -43,24 +43,7 @@ where /// extending `DiagCtxtFlags`. #[must_use] #[derive(Clone)] -pub struct DiagnosticBuilder<'a, G: EmissionGuarantee> { - inner: DiagnosticBuilderInner<'a>, - _marker: PhantomData<G>, -} - -/// This type exists only for `DiagnosticBuilder::forget_guarantee`, because it: -/// 1. lacks the `G` parameter and therefore `DiagnosticBuilder<G1>` can be -/// converted into `DiagnosticBuilder<G2>` while reusing the `inner` field -/// 2. can implement the `Drop` "bomb" instead of `DiagnosticBuilder`, as it -/// contains all of the data (`state` + `diagnostic`) of `DiagnosticBuilder` -/// -/// The `diagnostic` field is not `Copy` and can't be moved out of whichever -/// type implements the `Drop` "bomb", but because of the above two facts, that -/// never needs to happen - instead, the whole `inner: DiagnosticBuilderInner` -/// can be moved out of a `DiagnosticBuilder` and into another. -#[must_use] -#[derive(Clone)] -struct DiagnosticBuilderInner<'a> { +pub struct DiagnosticBuilder<'a, G: EmissionGuarantee = ErrorGuaranteed> { state: DiagnosticBuilderState<'a>, /// `Diagnostic` is a large type, and `DiagnosticBuilder` is often used as a @@ -68,6 +51,8 @@ struct DiagnosticBuilderInner<'a> { /// In theory, return value optimization (RVO) should avoid unnecessary /// copying. In practice, it does not (at the time of writing). diagnostic: Box<Diagnostic>, + + _marker: PhantomData<G>, } #[derive(Clone)] @@ -83,7 +68,7 @@ enum DiagnosticBuilderState<'a> { /// assumed that `.emit()` was previously called, to end up in this state. /// /// While this is also used by `.cancel()`, this state is only observed by - /// the `Drop` `impl` of `DiagnosticBuilderInner`, as `.cancel()` takes + /// the `Drop` `impl` of `DiagnosticBuilder`, because `.cancel()` takes /// `self` by-value specifically to prevent any attempts to `.emit()`. /// // FIXME(eddyb) currently this doesn't prevent extending the `Diagnostic`, @@ -101,47 +86,50 @@ rustc_data_structures::static_assert_size!( /// Trait for types that `DiagnosticBuilder::emit` can return as a "guarantee" /// (or "proof") token that the emission happened. pub trait EmissionGuarantee: Sized { + /// This exists so that bugs and fatal errors can both result in `!` (an + /// abort) when emitted, but have different aborting behaviour. + type EmitResult = Self; + /// Implementation of `DiagnosticBuilder::emit`, fully controlled by each /// `impl` of `EmissionGuarantee`, to make it impossible to create a value - /// of `Self` without actually performing the emission. + /// of `Self::EmitResult` without actually performing the emission. #[track_caller] - fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self; - - /// Creates a new `DiagnosticBuilder` that will return this type of guarantee. - #[track_caller] - fn make_diagnostic_builder( - dcx: &DiagCtxt, - msg: impl Into<DiagnosticMessage>, - ) -> DiagnosticBuilder<'_, Self>; + fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult; } -impl<'a> DiagnosticBuilder<'a, ErrorGuaranteed> { - /// Discard the guarantee `.emit()` would return, in favor of having the - /// type `DiagnosticBuilder<'a, ()>`. This may be necessary whenever there - /// is a common codepath handling both errors and warnings. - pub fn forget_guarantee(self) -> DiagnosticBuilder<'a, ()> { - DiagnosticBuilder { inner: self.inner, _marker: PhantomData } +impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { + /// Most `emit_producing_guarantee` functions use this as a starting point. + fn emit_producing_nothing(&mut self) { + match self.state { + // First `.emit()` call, the `&DiagCtxt` is still available. + DiagnosticBuilderState::Emittable(dcx) => { + self.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; + dcx.emit_diagnostic_without_consuming(&mut self.diagnostic); + } + // `.emit()` was previously called, disallowed from repeating it. + DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} + } } } // FIXME(eddyb) make `ErrorGuaranteed` impossible to create outside `.emit()`. impl EmissionGuarantee for ErrorGuaranteed { - fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { - match db.inner.state { + fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { + // Contrast this with `emit_producing_nothing`. + match db.state { // First `.emit()` call, the `&DiagCtxt` is still available. DiagnosticBuilderState::Emittable(dcx) => { - db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; - - let guar = dcx.emit_diagnostic_without_consuming(&mut db.inner.diagnostic); + db.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; + let guar = dcx.emit_diagnostic_without_consuming(&mut db.diagnostic); // Only allow a guarantee if the `level` wasn't switched to a // non-error - the field isn't `pub`, but the whole `Diagnostic` // can be overwritten with a new one, thanks to `DerefMut`. assert!( - db.inner.diagnostic.is_error(), + db.diagnostic.is_error(), "emitted non-error ({:?}) diagnostic \ from `DiagnosticBuilder<ErrorGuaranteed>`", - db.inner.diagnostic.level, + db.diagnostic.level, ); guar.unwrap() } @@ -153,152 +141,58 @@ impl EmissionGuarantee for ErrorGuaranteed { // non-error - the field isn't `pub`, but the whole `Diagnostic` // can be overwritten with a new one, thanks to `DerefMut`. assert!( - db.inner.diagnostic.is_error(), + db.diagnostic.is_error(), "`DiagnosticBuilder<ErrorGuaranteed>`'s diagnostic \ became non-error ({:?}), after original `.emit()`", - db.inner.diagnostic.level, + db.diagnostic.level, ); #[allow(deprecated)] ErrorGuaranteed::unchecked_claim_error_was_emitted() } } } - - #[track_caller] - fn make_diagnostic_builder( - dcx: &DiagCtxt, - msg: impl Into<DiagnosticMessage>, - ) -> DiagnosticBuilder<'_, Self> { - DiagnosticBuilder::new(dcx, Level::Error { lint: false }, msg) - } } // FIXME(eddyb) should there be a `Option<ErrorGuaranteed>` impl as well? impl EmissionGuarantee for () { - fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { - match db.inner.state { - // First `.emit()` call, the `&DiagCtxt` is still available. - DiagnosticBuilderState::Emittable(dcx) => { - db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; - - dcx.emit_diagnostic_without_consuming(&mut db.inner.diagnostic); - } - // `.emit()` was previously called, disallowed from repeating it. - DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} - } - } - - fn make_diagnostic_builder( - dcx: &DiagCtxt, - msg: impl Into<DiagnosticMessage>, - ) -> DiagnosticBuilder<'_, Self> { - DiagnosticBuilder::new(dcx, Level::Warning(None), msg) - } -} - -/// Marker type which enables implementation of `create_note` and `emit_note` functions for -/// note-without-error struct diagnostics. -#[derive(Copy, Clone)] -pub struct Noted; - -impl EmissionGuarantee for Noted { - fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { - match db.inner.state { - // First `.emit()` call, the `&DiagCtxt` is still available. - DiagnosticBuilderState::Emittable(dcx) => { - db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; - dcx.emit_diagnostic_without_consuming(&mut db.inner.diagnostic); - } - // `.emit()` was previously called, disallowed from repeating it. - DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} - } - - Noted - } - - fn make_diagnostic_builder( - dcx: &DiagCtxt, - msg: impl Into<DiagnosticMessage>, - ) -> DiagnosticBuilder<'_, Self> { - DiagnosticBuilder::new(dcx, Level::Note, msg) + fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { + db.emit_producing_nothing(); } } /// Marker type which enables implementation of `create_bug` and `emit_bug` functions for -/// bug struct diagnostics. +/// bug diagnostics. #[derive(Copy, Clone)] -pub struct Bug; +pub struct BugAbort; -impl EmissionGuarantee for Bug { - fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { - match db.inner.state { - // First `.emit()` call, the `&DiagCtxt` is still available. - DiagnosticBuilderState::Emittable(dcx) => { - db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; +impl EmissionGuarantee for BugAbort { + type EmitResult = !; - dcx.emit_diagnostic_without_consuming(&mut db.inner.diagnostic); - } - // `.emit()` was previously called, disallowed from repeating it. - DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} - } - // Then panic. No need to return the marker type. + fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { + db.emit_producing_nothing(); panic::panic_any(ExplicitBug); } - - fn make_diagnostic_builder( - dcx: &DiagCtxt, - msg: impl Into<DiagnosticMessage>, - ) -> DiagnosticBuilder<'_, Self> { - DiagnosticBuilder::new(dcx, Level::Bug, msg) - } } -impl EmissionGuarantee for ! { - fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { - match db.inner.state { - // First `.emit()` call, the `&DiagCtxt` is still available. - DiagnosticBuilderState::Emittable(dcx) => { - db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; +/// Marker type which enables implementation of `create_fatal` and `emit_fatal` functions for +/// fatal diagnostics. +#[derive(Copy, Clone)] +pub struct FatalAbort; - dcx.emit_diagnostic_without_consuming(&mut db.inner.diagnostic); - } - // `.emit()` was previously called, disallowed from repeating it. - DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} - } - // Then fatally error, returning `!` - crate::FatalError.raise() - } +impl EmissionGuarantee for FatalAbort { + type EmitResult = !; - fn make_diagnostic_builder( - dcx: &DiagCtxt, - msg: impl Into<DiagnosticMessage>, - ) -> DiagnosticBuilder<'_, Self> { - DiagnosticBuilder::new(dcx, Level::Fatal, msg) + fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { + db.emit_producing_nothing(); + crate::FatalError.raise() } } impl EmissionGuarantee for rustc_span::fatal_error::FatalError { - fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { - match db.inner.state { - // First `.emit()` call, the `&DiagCtxt` is still available. - DiagnosticBuilderState::Emittable(dcx) => { - db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; - - dcx.emit_diagnostic_without_consuming(&mut db.inner.diagnostic); - } - // `.emit()` was previously called, disallowed from repeating it. - DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} - } - // Then fatally error.. + fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { + db.emit_producing_nothing(); rustc_span::fatal_error::FatalError } - - fn make_diagnostic_builder( - dcx: &DiagCtxt, - msg: impl Into<DiagnosticMessage>, - ) -> DiagnosticBuilder<'_, Self> { - DiagnosticBuilder::new(dcx, Level::Fatal, msg) - } } /// In general, the `DiagnosticBuilder` uses deref to allow access to @@ -318,7 +212,7 @@ macro_rules! forward { $(#[$attrs])* #[doc = concat!("See [`Diagnostic::", stringify!($n), "()`].")] pub fn $n(&mut self, $($name: $ty),*) -> &mut Self { - self.inner.diagnostic.$n($($name),*); + self.diagnostic.$n($($name),*); self } }; @@ -328,27 +222,21 @@ impl<G: EmissionGuarantee> Deref for DiagnosticBuilder<'_, G> { type Target = Diagnostic; fn deref(&self) -> &Diagnostic { - &self.inner.diagnostic + &self.diagnostic } } impl<G: EmissionGuarantee> DerefMut for DiagnosticBuilder<'_, G> { fn deref_mut(&mut self) -> &mut Diagnostic { - &mut self.inner.diagnostic + &mut self.diagnostic } } impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { - /// Convenience function for internal use, clients should use one of the - /// `struct_*` methods on [`DiagCtxt`]. + #[rustc_lint_diagnostics] #[track_caller] - pub(crate) fn new<M: Into<DiagnosticMessage>>( - dcx: &'a DiagCtxt, - level: Level, - message: M, - ) -> Self { - let diagnostic = Diagnostic::new(level, message); - Self::new_diagnostic(dcx, diagnostic) + pub fn new<M: Into<DiagnosticMessage>>(dcx: &'a DiagCtxt, level: Level, message: M) -> Self { + Self::new_diagnostic(dcx, Diagnostic::new(level, message)) } /// Creates a new `DiagnosticBuilder` with an already constructed @@ -357,10 +245,8 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { pub(crate) fn new_diagnostic(dcx: &'a DiagCtxt, diagnostic: Diagnostic) -> Self { debug!("Created new diagnostic"); Self { - inner: DiagnosticBuilderInner { - state: DiagnosticBuilderState::Emittable(dcx), - diagnostic: Box::new(diagnostic), - }, + state: DiagnosticBuilderState::Emittable(dcx), + diagnostic: Box::new(diagnostic), _marker: PhantomData, } } @@ -369,8 +255,8 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// but there are various places that rely on continuing to use `self` /// after calling `emit`. #[track_caller] - pub fn emit(&mut self) -> G { - G::diagnostic_builder_emit_producing_guarantee(self) + pub fn emit(&mut self) -> G::EmitResult { + G::emit_producing_guarantee(self) } /// Emit the diagnostic unless `delay` is true, @@ -378,7 +264,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// /// See `emit` and `delay_as_bug` for details. #[track_caller] - pub fn emit_unless(&mut self, delay: bool) -> G { + pub fn emit_unless(&mut self, delay: bool) -> G::EmitResult { if delay { self.downgrade_to_delayed_bug(); } @@ -392,7 +278,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// which may be expected to *guarantee* the emission of an error, either /// at the time of the call, or through a prior `.emit()` call. pub fn cancel(mut self) { - self.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; + self.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; drop(self); } @@ -400,17 +286,17 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// later stage of the compiler. The diagnostic can be accessed with /// the provided `span` and `key` through [`DiagCtxt::steal_diagnostic()`]. /// - /// As with `buffer`, this is unless the handler has disabled such buffering. + /// As with `buffer`, this is unless the dcx has disabled such buffering. pub fn stash(self, span: Span, key: StashKey) { - if let Some((diag, handler)) = self.into_diagnostic() { - handler.stash_diagnostic(span, key, diag); + if let Some((diag, dcx)) = self.into_diagnostic() { + dcx.stash_diagnostic(span, key, diag); } } /// Converts the builder to a `Diagnostic` for later emission, - /// unless handler has disabled such buffering, or `.emit()` was called. + /// unless dcx has disabled such buffering, or `.emit()` was called. pub fn into_diagnostic(mut self) -> Option<(Diagnostic, &'a DiagCtxt)> { - let dcx = match self.inner.state { + let dcx = match self.state { // No `.emit()` calls, the `&DiagCtxt` is still available. DiagnosticBuilderState::Emittable(dcx) => dcx, // `.emit()` was previously called, nothing we can do. @@ -428,7 +314,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { // Take the `Diagnostic` by replacing it with a dummy. let dummy = Diagnostic::new(Level::Allow, DiagnosticMessage::from("")); - let diagnostic = std::mem::replace(&mut *self.inner.diagnostic, dummy); + let diagnostic = std::mem::replace(&mut *self.diagnostic, dummy); // Disable the ICE on `Drop`. self.cancel(); @@ -442,14 +328,14 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// Retrieves the [`DiagCtxt`] if available pub fn dcx(&self) -> Option<&DiagCtxt> { - match self.inner.state { + match self.state { DiagnosticBuilderState::Emittable(dcx) => Some(dcx), DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => None, } } /// Buffers the diagnostic for later emission, - /// unless handler has disabled such buffering. + /// unless dcx has disabled such buffering. pub fn buffer(self, buffered_diagnostics: &mut Vec<Diagnostic>) { buffered_diagnostics.extend(self.into_diagnostic().map(|(diag, _)| diag)); } @@ -465,7 +351,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// In the meantime, though, callsites are required to deal with the "bug" /// locally in whichever way makes the most sense. #[track_caller] - pub fn delay_as_bug(&mut self) -> G { + pub fn delay_as_bug(&mut self) -> G::EmitResult { self.downgrade_to_delayed_bug(); self.emit() } @@ -630,13 +516,13 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { impl<G: EmissionGuarantee> Debug for DiagnosticBuilder<'_, G> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.inner.diagnostic.fmt(f) + self.diagnostic.fmt(f) } } /// Destructor bomb - a `DiagnosticBuilder` must be either emitted or cancelled /// or we emit a bug. -impl Drop for DiagnosticBuilderInner<'_> { +impl<G: EmissionGuarantee> Drop for DiagnosticBuilder<'_, G> { fn drop(&mut self) { match self.state { // No `.emit()` or `.cancel()` calls. diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 3e4b3ee758a..29cb304e8b5 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -1,10 +1,12 @@ use crate::diagnostic::DiagnosticLocation; use crate::{fluent_generated as fluent, AddToDiagnostic}; -use crate::{DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, IntoDiagnostic, IntoDiagnosticArg}; +use crate::{ + DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, + IntoDiagnosticArg, Level, +}; use rustc_ast as ast; use rustc_ast_pretty::pprust; use rustc_hir as hir; -use rustc_lint_defs::Level; use rustc_span::edition::Edition; use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol}; use rustc_span::Span; @@ -216,7 +218,7 @@ impl IntoDiagnosticArg for ast::Visibility { } } -impl IntoDiagnosticArg for Level { +impl IntoDiagnosticArg for rustc_lint_defs::Level { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { DiagnosticArgValue::Str(Cow::Borrowed(self.to_cmd_flag())) } @@ -245,19 +247,20 @@ impl<Id> IntoDiagnosticArg for hir::def::Res<Id> { } } -impl IntoDiagnostic<'_, !> for TargetDataLayoutErrors<'_> { - fn into_diagnostic(self, dcx: &DiagCtxt) -> DiagnosticBuilder<'_, !> { +impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for TargetDataLayoutErrors<'_> { + fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { let mut diag; match self { TargetDataLayoutErrors::InvalidAddressSpace { addr_space, err, cause } => { - diag = dcx.struct_fatal(fluent::errors_target_invalid_address_space); + diag = + DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_address_space); diag.set_arg("addr_space", addr_space); diag.set_arg("cause", cause); diag.set_arg("err", err); diag } TargetDataLayoutErrors::InvalidBits { kind, bit, cause, err } => { - diag = dcx.struct_fatal(fluent::errors_target_invalid_bits); + diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_bits); diag.set_arg("kind", kind); diag.set_arg("bit", bit); diag.set_arg("cause", cause); @@ -265,31 +268,39 @@ impl IntoDiagnostic<'_, !> for TargetDataLayoutErrors<'_> { diag } TargetDataLayoutErrors::MissingAlignment { cause } => { - diag = dcx.struct_fatal(fluent::errors_target_missing_alignment); + diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_missing_alignment); diag.set_arg("cause", cause); diag } TargetDataLayoutErrors::InvalidAlignment { cause, err } => { - diag = dcx.struct_fatal(fluent::errors_target_invalid_alignment); + diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_alignment); diag.set_arg("cause", cause); diag.set_arg("err_kind", err.diag_ident()); diag.set_arg("align", err.align()); diag } TargetDataLayoutErrors::InconsistentTargetArchitecture { dl, target } => { - diag = dcx.struct_fatal(fluent::errors_target_inconsistent_architecture); + diag = DiagnosticBuilder::new( + dcx, + level, + fluent::errors_target_inconsistent_architecture, + ); diag.set_arg("dl", dl); diag.set_arg("target", target); diag } TargetDataLayoutErrors::InconsistentTargetPointerWidth { pointer_size, target } => { - diag = dcx.struct_fatal(fluent::errors_target_inconsistent_pointer_width); + diag = DiagnosticBuilder::new( + dcx, + level, + fluent::errors_target_inconsistent_pointer_width, + ); diag.set_arg("pointer_size", pointer_size); diag.set_arg("target", target); diag } TargetDataLayoutErrors::InvalidBitsSize { err } => { - diag = dcx.struct_fatal(fluent::errors_target_invalid_bits_size); + diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_bits_size); diag.set_arg("err", err); diag } @@ -301,25 +312,13 @@ impl IntoDiagnostic<'_, !> for TargetDataLayoutErrors<'_> { pub struct SingleLabelManySpans { pub spans: Vec<Span>, pub label: &'static str, - pub kind: LabelKind, } impl AddToDiagnostic for SingleLabelManySpans { fn add_to_diagnostic_with<F>(self, diag: &mut crate::Diagnostic, _: F) { - match self.kind { - LabelKind::Note => diag.span_note(self.spans, self.label), - LabelKind::Label => diag.span_labels(self.spans, self.label), - LabelKind::Help => diag.span_help(self.spans, self.label), - }; + diag.span_labels(self.spans, self.label); } } -/// The kind of label to attach when using [`SingleLabelManySpans`] -pub enum LabelKind { - Note, - Label, - Help, -} - #[derive(Subdiagnostic)] #[label(errors_expected_lifetime_parameter)] pub struct ExpectedLifetimeParameter { @@ -362,9 +361,9 @@ impl IntoDiagnosticArg for Backtrace { pub struct InvalidFlushedDelayedDiagnosticLevel { #[primary_span] pub span: Span, - pub level: rustc_errors::Level, + pub level: Level, } -impl IntoDiagnosticArg for rustc_errors::Level { +impl IntoDiagnosticArg for Level { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { DiagnosticArgValue::Str(Cow::from(self.to_string())) } diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 3fb993c3651..546159c9d13 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -350,9 +350,8 @@ pub trait Emitter: Translate { children.push(SubDiagnostic { level: Level::Note, - message: vec![(DiagnosticMessage::from(msg), Style::NoStyle)], + messages: vec![(DiagnosticMessage::from(msg), Style::NoStyle)], span: MultiSpan::new(), - render_span: None, }); } } @@ -533,7 +532,7 @@ impl Emitter for EmitterWriter { self.emit_messages_default( &diag.level, - &diag.message, + &diag.messages, &fluent_args, &diag.code, &primary_span, @@ -1228,10 +1227,10 @@ impl EmitterWriter { /// Adds a left margin to every line but the first, given a padding length and the label being /// displayed, keeping the provided highlighting. - fn msg_to_buffer( + fn msgs_to_buffer( &self, buffer: &mut StyledBuffer, - msg: &[(DiagnosticMessage, Style)], + msgs: &[(DiagnosticMessage, Style)], args: &FluentArgs<'_>, padding: usize, label: &str, @@ -1267,7 +1266,7 @@ impl EmitterWriter { // Provided the following diagnostic message: // - // let msg = vec![ + // let msgs = vec![ // (" // ("highlighted multiline\nstring to\nsee how it ", Style::NoStyle), // ("looks", Style::Highlight), @@ -1284,7 +1283,7 @@ impl EmitterWriter { // see how it *looks* with // very *weird* formats // see? - for (text, style) in msg.iter() { + for (text, style) in msgs.iter() { let text = self.translate_message(text, args).map_err(Report::new).unwrap(); let text = &normalize_whitespace(&text); let lines = text.split('\n').collect::<Vec<_>>(); @@ -1303,10 +1302,10 @@ impl EmitterWriter { } #[instrument(level = "trace", skip(self, args), ret)] - fn emit_message_default( + fn emit_messages_default_inner( &mut self, msp: &MultiSpan, - msg: &[(DiagnosticMessage, Style)], + msgs: &[(DiagnosticMessage, Style)], args: &FluentArgs<'_>, code: &Option<DiagnosticId>, level: &Level, @@ -1327,7 +1326,7 @@ impl EmitterWriter { buffer.append(0, level.to_str(), Style::MainHeaderMsg); buffer.append(0, ": ", Style::NoStyle); } - self.msg_to_buffer(&mut buffer, msg, args, max_line_num_len, "note", None); + self.msgs_to_buffer(&mut buffer, msgs, args, max_line_num_len, "note", None); } else { let mut label_width = 0; // The failure note level itself does not provide any useful diagnostic information @@ -1360,7 +1359,7 @@ impl EmitterWriter { buffer.append(0, ": ", header_style); label_width += 2; } - for (text, _) in msg.iter() { + for (text, _) in msgs.iter() { let text = self.translate_message(text, args).map_err(Report::new).unwrap(); // Account for newlines to align output to its label. for (line, text) in normalize_whitespace(&text).lines().enumerate() { @@ -1747,7 +1746,7 @@ impl EmitterWriter { buffer.append(0, level.to_str(), Style::Level(*level)); buffer.append(0, ": ", Style::HeaderMsg); - self.msg_to_buffer( + self.msgs_to_buffer( &mut buffer, &[(suggestion.msg.to_owned(), Style::NoStyle)], args, @@ -2074,7 +2073,7 @@ impl EmitterWriter { fn emit_messages_default( &mut self, level: &Level, - message: &[(DiagnosticMessage, Style)], + messages: &[(DiagnosticMessage, Style)], args: &FluentArgs<'_>, code: &Option<DiagnosticId>, span: &MultiSpan, @@ -2089,9 +2088,9 @@ impl EmitterWriter { num_decimal_digits(n) }; - match self.emit_message_default( + match self.emit_messages_default_inner( span, - message, + messages, args, code, level, @@ -2118,10 +2117,10 @@ impl EmitterWriter { } if !self.short_message { for child in children { - let span = child.render_span.as_ref().unwrap_or(&child.span); - if let Err(err) = self.emit_message_default( + let span = &child.span; + if let Err(err) = self.emit_messages_default_inner( span, - &child.message, + &child.messages, args, &None, &child.level, @@ -2138,7 +2137,7 @@ impl EmitterWriter { // do not display this suggestion, it is meant only for tools } SuggestionStyle::HideCodeAlways => { - if let Err(e) = self.emit_message_default( + if let Err(e) = self.emit_messages_default_inner( &MultiSpan::new(), &[(sugg.msg.to_owned(), Style::HeaderMsg)], args, diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index aa3749334d9..52fcb50e9fb 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -398,7 +398,7 @@ impl Diagnostic { let output = Arc::try_unwrap(output.0).unwrap().into_inner().unwrap(); let output = String::from_utf8(output).unwrap(); - let translated_message = je.translate_messages(&diag.message, &args); + let translated_message = je.translate_messages(&diag.messages, &args); Diagnostic { message: translated_message.to_string(), code: DiagnosticCode::map_opt_string(diag.code.clone(), je), @@ -419,16 +419,12 @@ impl Diagnostic { args: &FluentArgs<'_>, je: &JsonEmitter, ) -> Diagnostic { - let translated_message = je.translate_messages(&diag.message, args); + let translated_message = je.translate_messages(&diag.messages, args); Diagnostic { message: translated_message.to_string(), code: None, level: diag.level.to_str(), - spans: diag - .render_span - .as_ref() - .map(|sp| DiagnosticSpan::from_multispan(sp, args, je)) - .unwrap_or_else(|| DiagnosticSpan::from_multispan(&diag.span, args, je)), + spans: DiagnosticSpan::from_multispan(&diag.span, args, je), children: vec![], rendered: None, } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 959e26fec70..7a1faac04d3 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -6,6 +6,7 @@ #![doc(rust_logo)] #![feature(rustdoc_internals)] #![feature(array_windows)] +#![feature(associated_type_defaults)] #![feature(extract_if)] #![feature(if_let_guard)] #![feature(let_chains)] @@ -26,26 +27,42 @@ extern crate tracing; extern crate self as rustc_errors; +pub use diagnostic::{ + AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticId, + DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic, +}; +pub use diagnostic_builder::{ + BugAbort, DiagnosticBuilder, EmissionGuarantee, FatalAbort, IntoDiagnostic, +}; +pub use diagnostic_impls::{ + DiagnosticArgFromDisplay, DiagnosticSymbolList, ExpectedLifetimeParameter, + IndicateAnonymousLifetime, InvalidFlushedDelayedDiagnosticLevel, SingleLabelManySpans, +}; pub use emitter::ColorConfig; +pub use rustc_error_messages::{ + fallback_fluent_bundle, fluent_bundle, DelayDm, DiagnosticMessage, FluentBundle, + LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagnosticMessage, +}; +pub use rustc_lint_defs::{pluralize, Applicability}; +pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker}; +pub use rustc_span::ErrorGuaranteed; +pub use snippet::Style; -use rustc_lint_defs::LintExpectationId; -use Level::*; +// Used by external projects such as `rust-gpu`. +// See https://github.com/rust-lang/rust/pull/115393. +pub use termcolor::{Color, ColorSpec, WriteColor}; +use crate::diagnostic_impls::{DelayedAtWithNewline, DelayedAtWithoutNewline}; use emitter::{is_case_difference, DynEmitter, Emitter, EmitterWriter}; use registry::Registry; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::stable_hasher::{Hash128, StableHasher}; use rustc_data_structures::sync::{Lock, Lrc}; use rustc_data_structures::AtomicRef; -pub use rustc_error_messages::{ - fallback_fluent_bundle, fluent_bundle, DelayDm, DiagnosticMessage, FluentBundle, - LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagnosticMessage, -}; -pub use rustc_lint_defs::{pluralize, Applicability}; +use rustc_lint_defs::LintExpectationId; use rustc_span::source_map::SourceMap; -pub use rustc_span::ErrorGuaranteed; use rustc_span::{Loc, Span, DUMMY_SP}; - +use std::backtrace::{Backtrace, BacktraceStatus}; use std::borrow::Cow; use std::error::Report; use std::fmt; @@ -55,9 +72,7 @@ use std::num::NonZeroUsize; use std::panic; use std::path::{Path, PathBuf}; -// Used by external projects such as `rust-gpu`. -// See https://github.com/rust-lang/rust/pull/115393. -pub use termcolor::{Color, ColorSpec, WriteColor}; +use Level::*; pub mod annotate_snippet_emitter_writer; mod diagnostic; @@ -75,10 +90,7 @@ mod styled_buffer; mod tests; pub mod translation; -pub use diagnostic_builder::IntoDiagnostic; -pub use snippet::Style; - -pub type PErr<'a> = DiagnosticBuilder<'a, ErrorGuaranteed>; +pub type PErr<'a> = DiagnosticBuilder<'a>; pub type PResult<'a, T> = Result<T, PErr<'a>>; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } @@ -162,7 +174,7 @@ pub struct SubstitutionPart { /// Used to translate between `Span`s and byte positions within a single output line in highlighted /// code of structured suggestions. #[derive(Debug, Clone, Copy)] -pub struct SubstitutionHighlight { +pub(crate) struct SubstitutionHighlight { start: usize, end: usize, } @@ -189,7 +201,7 @@ impl SubstitutionPart { impl CodeSuggestion { /// Returns the assembled code suggestions, whether they should be shown with an underline /// and whether the substitution only differs in capitalization. - pub fn splice_lines( + pub(crate) fn splice_lines( &self, sm: &SourceMap, ) -> Vec<(String, Vec<SubstitutionPart>, Vec<Vec<SubstitutionHighlight>>, bool)> { @@ -386,8 +398,6 @@ impl CodeSuggestion { } } -pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker}; - /// Signifies that the compiler died with an explicit call to `.bug` /// or `.span_bug` rather than a failed assertion, etc. pub struct ExplicitBug; @@ -396,20 +406,7 @@ pub struct ExplicitBug; /// rather than a failed assertion, etc. pub struct DelayedBugPanic; -use crate::diagnostic_impls::{DelayedAtWithNewline, DelayedAtWithoutNewline}; -pub use diagnostic::{ - AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticId, - DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic, -}; -pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee, Noted}; -pub use diagnostic_impls::{ - DiagnosticArgFromDisplay, DiagnosticSymbolList, ExpectedLifetimeParameter, - IndicateAnonymousLifetime, InvalidFlushedDelayedDiagnosticLevel, LabelKind, - SingleLabelManySpans, -}; -use std::backtrace::{Backtrace, BacktraceStatus}; - -/// A handler deals with errors and other compiler output. +/// A `DiagCtxt` deals with errors and other compiler output. /// Certain errors (fatal, bug, unimpl) may cause immediate exit, /// others log errors for later reporting. pub struct DiagCtxt { @@ -446,7 +443,7 @@ struct DiagCtxtInner { emitted_diagnostic_codes: FxIndexSet<DiagnosticId>, /// This set contains a hash of every diagnostic that has been emitted by - /// this handler. These hashes is used to avoid emitting the same error + /// this `DiagCtxt`. These hashes is used to avoid emitting the same error /// twice. emitted_diagnostics: FxHashSet<Hash128>, @@ -676,7 +673,7 @@ impl DiagCtxt { let key = (span.with_parent(None), key); if diag.is_error() { - if matches!(diag.level, Level::Error { lint: true }) { + if matches!(diag.level, Error { lint: true }) { inner.lint_err_count += 1; } else { inner.err_count += 1; @@ -700,7 +697,7 @@ impl DiagCtxt { let key = (span.with_parent(None), key); let diag = inner.stashed_diagnostics.remove(&key)?; if diag.is_error() { - if matches!(diag.level, Level::Error { lint: true }) { + if matches!(diag.level, Error { lint: true }) { inner.lint_err_count -= 1; } else { inner.err_count -= 1; @@ -722,21 +719,6 @@ impl DiagCtxt { self.inner.borrow_mut().emit_stashed_diagnostics() } - /// Construct a builder with the `msg` at the level appropriate for the - /// specific `EmissionGuarantee`. - /// - /// Note: this is necessary for `derive(Diagnostic)`, but shouldn't be used - /// outside of that. Instead use `struct_err`, `struct_warn`, etc., which - /// make the diagnostic kind clearer. - #[rustc_lint_diagnostics] - #[track_caller] - pub fn struct_diagnostic<G: EmissionGuarantee>( - &self, - msg: impl Into<DiagnosticMessage>, - ) -> DiagnosticBuilder<'_, G> { - G::make_diagnostic_builder(self, msg) - } - /// Construct a builder at the `Warning` level at the given `span` and with the `msg`. /// /// Attempting to `.emit()` the builder will only emit if either: @@ -755,37 +737,6 @@ impl DiagCtxt { } /// Construct a builder at the `Warning` level at the given `span` and with the `msg`. - /// The `id` is used for lint emissions which should also fulfill a lint expectation. - /// - /// Attempting to `.emit()` the builder will only emit if either: - /// * `can_emit_warnings` is `true` - /// * `is_force_warn` was set in `DiagnosticId::Lint` - #[track_caller] - pub fn struct_span_warn_with_expectation( - &self, - span: impl Into<MultiSpan>, - msg: impl Into<DiagnosticMessage>, - id: LintExpectationId, - ) -> DiagnosticBuilder<'_, ()> { - let mut result = self.struct_warn_with_expectation(msg, id); - result.set_span(span); - result - } - - /// Construct a builder at the `Allow` level at the given `span` and with the `msg`. - #[rustc_lint_diagnostics] - #[track_caller] - pub fn struct_span_allow( - &self, - span: impl Into<MultiSpan>, - msg: impl Into<DiagnosticMessage>, - ) -> DiagnosticBuilder<'_, ()> { - let mut result = self.struct_allow(msg); - result.set_span(span); - result - } - - /// Construct a builder at the `Warning` level at the given `span` and with the `msg`. /// Also include a code. #[rustc_lint_diagnostics] #[track_caller] @@ -808,29 +759,14 @@ impl DiagCtxt { #[rustc_lint_diagnostics] #[track_caller] pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> { - DiagnosticBuilder::new(self, Level::Warning(None), msg) - } - - /// Construct a builder at the `Warning` level with the `msg`. The `id` is used for - /// lint emissions which should also fulfill a lint expectation. - /// - /// Attempting to `.emit()` the builder will only emit if either: - /// * `can_emit_warnings` is `true` - /// * `is_force_warn` was set in `DiagnosticId::Lint` - #[track_caller] - pub fn struct_warn_with_expectation( - &self, - msg: impl Into<DiagnosticMessage>, - id: LintExpectationId, - ) -> DiagnosticBuilder<'_, ()> { - DiagnosticBuilder::new(self, Level::Warning(Some(id)), msg) + DiagnosticBuilder::new(self, Warning(None), msg) } /// Construct a builder at the `Allow` level with the `msg`. #[rustc_lint_diagnostics] #[track_caller] pub fn struct_allow(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> { - DiagnosticBuilder::new(self, Level::Allow, msg) + DiagnosticBuilder::new(self, Allow, msg) } /// Construct a builder at the `Expect` level with the `msg`. @@ -841,7 +777,7 @@ impl DiagCtxt { msg: impl Into<DiagnosticMessage>, id: LintExpectationId, ) -> DiagnosticBuilder<'_, ()> { - DiagnosticBuilder::new(self, Level::Expect(id), msg) + DiagnosticBuilder::new(self, Expect(id), msg) } /// Construct a builder at the `Error` level at the given `span` and with the `msg`. @@ -851,7 +787,7 @@ impl DiagCtxt { &self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>, - ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'_> { let mut result = self.struct_err(msg); result.set_span(span); result @@ -865,7 +801,7 @@ impl DiagCtxt { span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>, code: DiagnosticId, - ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'_> { let mut result = self.struct_span_err(span, msg); result.code(code); result @@ -875,18 +811,8 @@ impl DiagCtxt { // FIXME: This method should be removed (every error should have an associated error code). #[rustc_lint_diagnostics] #[track_caller] - pub fn struct_err( - &self, - msg: impl Into<DiagnosticMessage>, - ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { - DiagnosticBuilder::new(self, Level::Error { lint: false }, msg) - } - - /// This should only be used by `rustc_middle::lint::struct_lint_level`. Do not use it for hard errors. - #[doc(hidden)] - #[track_caller] - pub fn struct_err_lint(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> { - DiagnosticBuilder::new(self, Level::Error { lint: true }, msg) + pub fn struct_err(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_> { + DiagnosticBuilder::new(self, Error { lint: false }, msg) } /// Construct a builder at the `Error` level with the `msg` and the `code`. @@ -896,7 +822,7 @@ impl DiagCtxt { &self, msg: impl Into<DiagnosticMessage>, code: DiagnosticId, - ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'_> { let mut result = self.struct_err(msg); result.code(code); result @@ -922,7 +848,7 @@ impl DiagCtxt { &self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>, - ) -> DiagnosticBuilder<'_, !> { + ) -> DiagnosticBuilder<'_, FatalAbort> { let mut result = self.struct_fatal(msg); result.set_span(span); result @@ -936,7 +862,7 @@ impl DiagCtxt { span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>, code: DiagnosticId, - ) -> DiagnosticBuilder<'_, !> { + ) -> DiagnosticBuilder<'_, FatalAbort> { let mut result = self.struct_span_fatal(span, msg); result.code(code); result @@ -945,8 +871,11 @@ impl DiagCtxt { /// Construct a builder at the `Fatal` level with the `msg`. #[rustc_lint_diagnostics] #[track_caller] - pub fn struct_fatal(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, !> { - DiagnosticBuilder::new(self, Level::Fatal, msg) + pub fn struct_fatal( + &self, + msg: impl Into<DiagnosticMessage>, + ) -> DiagnosticBuilder<'_, FatalAbort> { + DiagnosticBuilder::new(self, Fatal, msg) } /// Construct a builder at the `Fatal` level with the `msg`, that doesn't abort. @@ -956,20 +885,40 @@ impl DiagCtxt { &self, msg: impl Into<DiagnosticMessage>, ) -> DiagnosticBuilder<'_, FatalError> { - DiagnosticBuilder::new(self, Level::Fatal, msg) + DiagnosticBuilder::new(self, Fatal, msg) } /// Construct a builder at the `Help` level with the `msg`. #[rustc_lint_diagnostics] pub fn struct_help(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> { - DiagnosticBuilder::new(self, Level::Help, msg) + DiagnosticBuilder::new(self, Help, msg) } /// Construct a builder at the `Note` level with the `msg`. #[rustc_lint_diagnostics] #[track_caller] pub fn struct_note(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> { - DiagnosticBuilder::new(self, Level::Note, msg) + DiagnosticBuilder::new(self, Note, msg) + } + + /// Construct a builder at the `Bug` level with the `msg`. + #[rustc_lint_diagnostics] + #[track_caller] + pub fn struct_bug(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, BugAbort> { + DiagnosticBuilder::new(self, Bug, msg) + } + + /// Construct a builder at the `Bug` level at the given `span` with the `msg`. + #[rustc_lint_diagnostics] + #[track_caller] + pub fn struct_span_bug( + &self, + span: impl Into<MultiSpan>, + msg: impl Into<DiagnosticMessage>, + ) -> DiagnosticBuilder<'_, BugAbort> { + let mut result = self.struct_bug(msg); + result.set_span(span); + result } #[rustc_lint_diagnostics] @@ -1028,7 +977,7 @@ impl DiagCtxt { } pub fn span_bug(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) -> ! { - self.inner.borrow_mut().span_bug(span, msg) + self.struct_span_bug(span, msg).emit() } /// For documentation on this, see `Session::span_delayed_bug`. @@ -1041,20 +990,14 @@ impl DiagCtxt { sp: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>, ) -> ErrorGuaranteed { - let mut inner = self.inner.borrow_mut(); - - // This is technically `self.treat_err_as_bug()` but `span_delayed_bug` is called before - // incrementing `err_count` by one, so we need to +1 the comparing. - // FIXME: Would be nice to increment err_count in a more coherent way. - if inner.flags.treat_err_as_bug.is_some_and(|c| { - inner.err_count + inner.lint_err_count + inner.delayed_bug_count() + 1 >= c.get() - }) { + let treat_next_err_as_bug = self.inner.borrow().treat_next_err_as_bug(); + if treat_next_err_as_bug { // FIXME: don't abort here if report_delayed_bugs is off - inner.span_bug(sp, msg); + self.span_bug(sp, msg); } - let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg); + let mut diagnostic = Diagnostic::new(DelayedBug, msg); diagnostic.set_span(sp); - inner.emit_diagnostic(diagnostic).unwrap() + self.emit_diagnostic(diagnostic).unwrap() } // FIXME(eddyb) note the comment inside `impl Drop for DiagCtxtInner`, that's @@ -1062,7 +1005,7 @@ impl DiagCtxt { pub fn good_path_delayed_bug(&self, msg: impl Into<DiagnosticMessage>) { let mut inner = self.inner.borrow_mut(); - let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg); + let mut diagnostic = Diagnostic::new(DelayedBug, msg); if inner.flags.report_delayed_bugs { inner.emit_diagnostic_without_consuming(&mut diagnostic); } @@ -1071,13 +1014,6 @@ impl DiagCtxt { } #[track_caller] - pub fn span_bug_no_panic(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) { - let mut diag = Diagnostic::new(Bug, msg); - diag.set_span(span); - self.emit_diagnostic(diag); - } - - #[track_caller] #[rustc_lint_diagnostics] pub fn span_note(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) { self.struct_span_note(span, msg).emit() @@ -1115,9 +1051,9 @@ impl DiagCtxt { self.struct_note(msg).emit() } + #[rustc_lint_diagnostics] pub fn bug(&self, msg: impl Into<DiagnosticMessage>) -> ! { - DiagnosticBuilder::<diagnostic_builder::Bug>::new(self, Bug, msg).emit(); - panic::panic_any(ExplicitBug); + self.struct_bug(msg).emit() } #[inline] @@ -1182,10 +1118,9 @@ impl DiagCtxt { match (errors.len(), warnings.len()) { (0, 0) => return, - (0, _) => inner.emitter.emit_diagnostic(&Diagnostic::new( - Level::Warning(None), - DiagnosticMessage::Str(warnings), - )), + (0, _) => inner + .emitter + .emit_diagnostic(&Diagnostic::new(Warning(None), DiagnosticMessage::Str(warnings))), (_, 0) => { inner.emit_diagnostic(Diagnostic::new(Fatal, errors)); } @@ -1217,14 +1152,12 @@ impl DiagCtxt { if error_codes.len() > 9 { "..." } else { "." } )); inner.failure_note(format!( - "For more information about an error, try \ - `rustc --explain {}`.", + "For more information about an error, try `rustc --explain {}`.", &error_codes[0] )); } else { inner.failure_note(format!( - "For more information about this error, try \ - `rustc --explain {}`.", + "For more information about this error, try `rustc --explain {}`.", &error_codes[0] )); } @@ -1274,18 +1207,16 @@ impl DiagCtxt { self.create_err(err).emit() } - pub fn create_err<'a>( - &'a self, - err: impl IntoDiagnostic<'a>, - ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - err.into_diagnostic(self) + #[track_caller] + pub fn create_err<'a>(&'a self, err: impl IntoDiagnostic<'a>) -> DiagnosticBuilder<'a> { + err.into_diagnostic(self, Error { lint: false }) } pub fn create_warning<'a>( &'a self, warning: impl IntoDiagnostic<'a, ()>, ) -> DiagnosticBuilder<'a, ()> { - warning.into_diagnostic(self) + warning.into_diagnostic(self, Warning(None)) } pub fn emit_warning<'a>(&'a self, warning: impl IntoDiagnostic<'a, ()>) { @@ -1296,7 +1227,7 @@ impl DiagCtxt { &'a self, fatal: impl IntoDiagnostic<'a, FatalError>, ) -> DiagnosticBuilder<'a, FatalError> { - fatal.into_diagnostic(self) + fatal.into_diagnostic(self, Fatal) } pub fn emit_almost_fatal<'a>( @@ -1308,38 +1239,35 @@ impl DiagCtxt { pub fn create_fatal<'a>( &'a self, - fatal: impl IntoDiagnostic<'a, !>, - ) -> DiagnosticBuilder<'a, !> { - fatal.into_diagnostic(self) + fatal: impl IntoDiagnostic<'a, FatalAbort>, + ) -> DiagnosticBuilder<'a, FatalAbort> { + fatal.into_diagnostic(self, Fatal) } - pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, !>) -> ! { + pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, FatalAbort>) -> ! { self.create_fatal(fatal).emit() } pub fn create_bug<'a>( &'a self, - bug: impl IntoDiagnostic<'a, diagnostic_builder::Bug>, - ) -> DiagnosticBuilder<'a, diagnostic_builder::Bug> { - bug.into_diagnostic(self) + bug: impl IntoDiagnostic<'a, BugAbort>, + ) -> DiagnosticBuilder<'a, BugAbort> { + bug.into_diagnostic(self, Bug) } - pub fn emit_bug<'a>( - &'a self, - bug: impl IntoDiagnostic<'a, diagnostic_builder::Bug>, - ) -> diagnostic_builder::Bug { + pub fn emit_bug<'a>(&'a self, bug: impl IntoDiagnostic<'a, BugAbort>) -> ! { self.create_bug(bug).emit() } - pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, Noted>) -> Noted { + pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, ()>) { self.create_note(note).emit() } pub fn create_note<'a>( &'a self, - note: impl IntoDiagnostic<'a, Noted>, - ) -> DiagnosticBuilder<'a, Noted> { - note.into_diagnostic(self) + note: impl IntoDiagnostic<'a, ()>, + ) -> DiagnosticBuilder<'a, ()> { + note.into_diagnostic(self, Note) } pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) { @@ -1426,7 +1354,7 @@ impl DiagCtxtInner { for diag in diags { // Decrement the count tracking the stash; emitting will increment it. if diag.is_error() { - if matches!(diag.level, Level::Error { lint: true }) { + if matches!(diag.level, Error { lint: true }) { self.lint_err_count -= 1; } else { self.err_count -= 1; @@ -1457,9 +1385,8 @@ impl DiagCtxtInner { &mut self, diagnostic: &mut Diagnostic, ) -> Option<ErrorGuaranteed> { - if matches!(diagnostic.level, Level::Error { .. } | Level::Fatal) && self.treat_err_as_bug() - { - diagnostic.level = Level::Bug; + if matches!(diagnostic.level, Error { .. } | Fatal) && self.treat_err_as_bug() { + diagnostic.level = Bug; } // The `LintExpectationId` can be stable or unstable depending on when it was created. @@ -1471,7 +1398,7 @@ impl DiagCtxtInner { return None; } - if diagnostic.level == Level::DelayedBug { + if diagnostic.level == DelayedBug { // FIXME(eddyb) this should check for `has_errors` and stop pushing // once *any* errors were emitted (and truncate `span_delayed_bugs` // when an error is first emitted, also), but maybe there's a case @@ -1487,7 +1414,7 @@ impl DiagCtxtInner { } if diagnostic.has_future_breakage() { - // Future breakages aren't emitted if they're Level::Allowed, + // Future breakages aren't emitted if they're Level::Allow, // but they still need to be constructed and stashed below, // so they'll trigger the good-path bug check. self.suppressed_expected_diag = true; @@ -1509,7 +1436,7 @@ impl DiagCtxtInner { return None; } - if matches!(diagnostic.level, Level::Expect(_) | Level::Allow) { + if matches!(diagnostic.level, Expect(_) | Allow) { (*TRACK_DIAGNOSTICS)(diagnostic, &mut |_| {}); return None; } @@ -1534,7 +1461,7 @@ impl DiagCtxtInner { debug!(?self.emitted_diagnostics); let already_emitted_sub = |sub: &mut SubDiagnostic| { debug!(?sub); - if sub.level != Level::OnceNote && sub.level != Level::OnceHelp { + if sub.level != OnceNote && sub.level != OnceHelp { return false; } let mut hasher = StableHasher::new(); @@ -1559,7 +1486,7 @@ impl DiagCtxtInner { } } if diagnostic.is_error() { - if matches!(diagnostic.level, Level::Error { lint: true }) { + if matches!(diagnostic.level, Error { lint: true }) { self.bump_lint_err_count(); } else { self.bump_err_count(); @@ -1583,6 +1510,13 @@ impl DiagCtxtInner { }) } + // Use this one before incrementing `err_count`. + fn treat_next_err_as_bug(&self) -> bool { + self.flags.treat_err_as_bug.is_some_and(|c| { + self.err_count + self.lint_err_count + self.delayed_bug_count() + 1 >= c.get() + }) + } + fn delayed_bug_count(&self) -> usize { self.span_delayed_bugs.len() + self.good_path_delayed_bugs.len() } @@ -1591,27 +1525,22 @@ impl DiagCtxtInner { self.err_count > 0 } - #[track_caller] - fn span_bug(&mut self, sp: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) -> ! { - let mut diag = Diagnostic::new(Bug, msg); - diag.set_span(sp); - self.emit_diagnostic(diag); - panic::panic_any(ExplicitBug); - } - fn failure_note(&mut self, msg: impl Into<DiagnosticMessage>) { self.emit_diagnostic(Diagnostic::new(FailureNote, msg)); } fn flush_delayed( &mut self, - bugs: impl IntoIterator<Item = DelayedDiagnostic>, + bugs: Vec<DelayedDiagnostic>, explanation: impl Into<DiagnosticMessage> + Copy, ) { - let mut no_bugs = true; + if bugs.is_empty() { + return; + } + // If backtraces are enabled, also print the query stack let backtrace = std::env::var_os("RUST_BACKTRACE").map_or(true, |x| &x != "0"); - for bug in bugs { + for (i, bug) in bugs.into_iter().enumerate() { if let Some(file) = self.ice_file.as_ref() && let Ok(mut out) = std::fs::File::options().create(true).append(true).open(file) { @@ -1619,25 +1548,25 @@ impl DiagCtxtInner { &mut out, "delayed span bug: {}\n{}\n", bug.inner - .styled_message() + .messages() .iter() .filter_map(|(msg, _)| msg.as_str()) .collect::<String>(), &bug.note ); } - let mut bug = - if backtrace || self.ice_file.is_none() { bug.decorate() } else { bug.inner }; - if no_bugs { + if i == 0 { // Put the overall explanation before the `DelayedBug`s, to // frame them better (e.g. separate warnings from them). self.emit_diagnostic(Diagnostic::new(Bug, explanation)); - no_bugs = false; } + let mut bug = + if backtrace || self.ice_file.is_none() { bug.decorate() } else { bug.inner }; + // "Undelay" the `DelayedBug`s (into plain `Bug`s). - if bug.level != Level::DelayedBug { + if bug.level != DelayedBug { // NOTE(eddyb) not panicking here because we're already producing // an ICE, and the more information the merrier. bug.subdiagnostic(InvalidFlushedDelayedDiagnosticLevel { @@ -1645,15 +1574,13 @@ impl DiagCtxtInner { level: bug.level, }); } - bug.level = Level::Bug; + bug.level = Bug; self.emit_diagnostic(bug); } // Panic with `DelayedBugPanic` to avoid "unexpected panic" messages. - if !no_bugs { - panic::panic_any(DelayedBugPanic); - } + panic::panic_any(DelayedBugPanic); } fn bump_lint_err_count(&mut self) { @@ -1731,25 +1658,80 @@ impl DelayedDiagnostic { #[derive(Copy, PartialEq, Eq, Clone, Hash, Debug, Encodable, Decodable)] pub enum Level { + /// For bugs in the compiler. Manifests as an ICE (internal compiler error) panic. + /// + /// Its `EmissionGuarantee` is `BugAbort`. Bug, + + /// This is a strange one: lets you register an error without emitting it. If compilation ends + /// without any other errors occurring, this will be emitted as a bug. Otherwise, it will be + /// silently dropped. I.e. "expect other errors are emitted" semantics. Useful on code paths + /// that should only be reached when compiling erroneous code. + /// + /// Its `EmissionGuarantee` is `ErrorGuaranteed`. DelayedBug, + + /// An error that causes an immediate abort. Used for things like configuration errors, + /// internal overflows, some file operation errors. + /// + /// Its `EmissionGuarantee` is `FatalAbort`, except in the non-aborting "almost fatal" case + /// that is occasionaly used, where it is `FatalError`. Fatal, + + /// An error in the code being compiled, which prevents compilation from finishing. This is the + /// most common case. + /// + /// Its `EmissionGuarantee` is `ErrorGuaranteed`. Error { - /// If this error comes from a lint, don't abort compilation even when abort_if_errors() is called. + /// If this error comes from a lint, don't abort compilation even when abort_if_errors() is + /// called. lint: bool, }, + + /// A warning about the code being compiled. Does not prevent compilation from finishing. + /// /// This [`LintExpectationId`] is used for expected lint diagnostics, which should /// also emit a warning due to the `force-warn` flag. In all other cases this should /// be `None`. + /// + /// Its `EmissionGuarantee` is `()`. Warning(Option<LintExpectationId>), + + /// A message giving additional context. Rare, because notes are more commonly attached to other + /// diagnostics such as errors. + /// + /// Its `EmissionGuarantee` is `()`. Note, - /// A note that is only emitted once. + + /// A note that is only emitted once. Rare, mostly used in circumstances relating to lints. + /// + /// Its `EmissionGuarantee` is `()`. OnceNote, + + /// A message suggesting how to fix something. Rare, because help messages are more commonly + /// attached to other diagnostics such as errors. + /// + /// Its `EmissionGuarantee` is `()`. Help, - /// A help that is only emitted once. + + /// A help that is only emitted once. Rare. + /// + /// Its `EmissionGuarantee` is `()`. OnceHelp, + + /// Similar to `Note`, but used in cases where compilation has failed. Rare. + /// + /// Its `EmissionGuarantee` is `()`. FailureNote, + + /// Only used for lints. + /// + /// Its `EmissionGuarantee` is `()`. Allow, + + /// Only used for lints. + /// + /// Its `EmissionGuarantee` is `()`. Expect(LintExpectationId), } @@ -1789,8 +1771,7 @@ impl Level { Note | OnceNote => "note", Help | OnceHelp => "help", FailureNote => "failure-note", - Allow => panic!("Shouldn't call on allowed error"), - Expect(_) => panic!("Shouldn't call on expected error"), + Allow | Expect(_) => unreachable!(), } } @@ -1800,7 +1781,7 @@ impl Level { pub fn get_expectation_id(&self) -> Option<LintExpectationId> { match self { - Level::Expect(id) | Level::Warning(Some(id)) => Some(*id), + Expect(id) | Warning(Some(id)) => Some(*id), _ => None, } } diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index b63609c48e9..1fd4d2d55dd 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1118,15 +1118,12 @@ impl<'a> ExtCtxt<'a> { &self, sp: S, msg: impl Into<DiagnosticMessage>, - ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'a> { self.sess.dcx().struct_span_err(sp, msg) } #[track_caller] - pub fn create_err( - &self, - err: impl IntoDiagnostic<'a>, - ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + pub fn create_err(&self, err: impl IntoDiagnostic<'a>) -> DiagnosticBuilder<'a> { self.sess.create_err(err) } @@ -1159,6 +1156,7 @@ impl<'a> ExtCtxt<'a> { // Fixme: does this result in errors? self.expansions.clear(); } + #[rustc_lint_diagnostics] pub fn bug(&self, msg: &'static str) -> ! { self.sess.dcx().bug(msg); } @@ -1204,11 +1202,10 @@ pub fn resolve_path( .expect("attempting to resolve a file path in an external file"), FileName::DocTest(path, _) => path, other => { - return Err(errors::ResolveRelativePath { + return Err(parse_sess.dcx.create_err(errors::ResolveRelativePath { span, path: parse_sess.source_map().filename_for_diagnostics(&other).to_string(), - } - .into_diagnostic(&parse_sess.dcx)); + })); } }; result.pop(); @@ -1230,7 +1227,7 @@ pub fn expr_to_spanned_string<'a>( cx: &'a mut ExtCtxt<'_>, expr: P<ast::Expr>, err_msg: &'static str, -) -> Result<(Symbol, ast::StrStyle, Span), Option<(DiagnosticBuilder<'a, ErrorGuaranteed>, bool)>> { +) -> Result<(Symbol, ast::StrStyle, Span), Option<(DiagnosticBuilder<'a>, bool)>> { // Perform eager expansion on the expression. // We want to be able to handle e.g., `concat!("foo", "bar")`. let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr(); diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 86f555fa08b..f9bfebee12e 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -134,10 +134,13 @@ impl<'a> ExtCtxt<'a> { pub fn trait_bound(&self, path: ast::Path, is_const: bool) -> ast::GenericBound { ast::GenericBound::Trait( self.poly_trait_ref(path.span, path), - if is_const { - ast::TraitBoundModifier::MaybeConst(DUMMY_SP) - } else { - ast::TraitBoundModifier::None + ast::TraitBoundModifiers { + polarity: ast::BoundPolarity::Positive, + constness: if is_const { + ast::BoundConstness::Maybe(DUMMY_SP) + } else { + ast::BoundConstness::Never + }, }, ) } @@ -488,7 +491,7 @@ impl<'a> ExtCtxt<'a> { path: ast::Path, field_pats: ThinVec<ast::PatField>, ) -> P<ast::Pat> { - self.pat(span, PatKind::Struct(None, path, field_pats, false)) + self.pat(span, PatKind::Struct(None, path, field_pats, ast::PatFieldsRest::None)) } pub fn pat_tuple(&self, span: Span, pats: ThinVec<P<ast::Pat>>) -> P<ast::Pat> { self.pat(span, PatKind::Tuple(pats)) diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 89caf8aa231..da727ddb208 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -41,132 +41,6 @@ use std::path::PathBuf; use std::rc::Rc; use std::{iter, mem}; -#[cfg(bootstrap)] -macro_rules! ast_fragments { - ( - $($Kind:ident($AstTy:ty) { - $kind_name:expr; - $(one fn $mut_visit_ast:ident; fn $visit_ast:ident;)? - $(many fn $flat_map_ast_elt:ident; fn $visit_ast_elt:ident($($args:tt)*);)? - fn $make_ast:ident; - })* - ) => { - /// A fragment of AST that can be produced by a single macro expansion. - /// Can also serve as an input and intermediate result for macro expansion operations. - pub enum AstFragment { - OptExpr(Option<P<ast::Expr>>), - MethodReceiverExpr(P<ast::Expr>), - $($Kind($AstTy),)* - } - - /// "Discriminant" of an AST fragment. - #[derive(Copy, Clone, PartialEq, Eq)] - pub enum AstFragmentKind { - OptExpr, - MethodReceiverExpr, - $($Kind,)* - } - - impl AstFragmentKind { - pub fn name(self) -> &'static str { - match self { - AstFragmentKind::OptExpr => "expression", - AstFragmentKind::MethodReceiverExpr => "expression", - $(AstFragmentKind::$Kind => $kind_name,)* - } - } - - fn make_from<'a>(self, result: Box<dyn MacResult + 'a>) -> Option<AstFragment> { - match self { - AstFragmentKind::OptExpr => - result.make_expr().map(Some).map(AstFragment::OptExpr), - AstFragmentKind::MethodReceiverExpr => - result.make_expr().map(AstFragment::MethodReceiverExpr), - $(AstFragmentKind::$Kind => result.$make_ast().map(AstFragment::$Kind),)* - } - } - } - - impl AstFragment { - pub fn add_placeholders(&mut self, placeholders: &[NodeId]) { - if placeholders.is_empty() { - return; - } - match self { - $($(AstFragment::$Kind(ast) => ast.extend(placeholders.iter().flat_map(|id| { - ${ignore(flat_map_ast_elt)} - placeholder(AstFragmentKind::$Kind, *id, None).$make_ast() - })),)?)* - _ => panic!("unexpected AST fragment kind") - } - } - - pub fn make_opt_expr(self) -> Option<P<ast::Expr>> { - match self { - AstFragment::OptExpr(expr) => expr, - _ => panic!("AstFragment::make_* called on the wrong kind of fragment"), - } - } - - pub fn make_method_receiver_expr(self) -> P<ast::Expr> { - match self { - AstFragment::MethodReceiverExpr(expr) => expr, - _ => panic!("AstFragment::make_* called on the wrong kind of fragment"), - } - } - - $(pub fn $make_ast(self) -> $AstTy { - match self { - AstFragment::$Kind(ast) => ast, - _ => panic!("AstFragment::make_* called on the wrong kind of fragment"), - } - })* - - fn make_ast<T: InvocationCollectorNode>(self) -> T::OutputTy { - T::fragment_to_output(self) - } - - pub fn mut_visit_with<F: MutVisitor>(&mut self, vis: &mut F) { - match self { - AstFragment::OptExpr(opt_expr) => { - visit_clobber(opt_expr, |opt_expr| { - if let Some(expr) = opt_expr { - vis.filter_map_expr(expr) - } else { - None - } - }); - } - AstFragment::MethodReceiverExpr(expr) => vis.visit_method_receiver_expr(expr), - $($(AstFragment::$Kind(ast) => vis.$mut_visit_ast(ast),)?)* - $($(AstFragment::$Kind(ast) => - ast.flat_map_in_place(|ast| vis.$flat_map_ast_elt(ast)),)?)* - } - } - - pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) { - match self { - AstFragment::OptExpr(Some(expr)) => visitor.visit_expr(expr), - AstFragment::OptExpr(None) => {} - AstFragment::MethodReceiverExpr(expr) => visitor.visit_method_receiver_expr(expr), - $($(AstFragment::$Kind(ast) => visitor.$visit_ast(ast),)?)* - $($(AstFragment::$Kind(ast) => for ast_elt in &ast[..] { - visitor.$visit_ast_elt(ast_elt, $($args)*); - })?)* - } - } - } - - impl<'a> MacResult for crate::mbe::macro_rules::ParserAnyMacro<'a> { - $(fn $make_ast(self: Box<crate::mbe::macro_rules::ParserAnyMacro<'a>>) - -> Option<$AstTy> { - Some(self.make(AstFragmentKind::$Kind).$make_ast()) - })* - } - } -} - -#[cfg(not(bootstrap))] macro_rules! ast_fragments { ( $($Kind:ident($AstTy:ty) { diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index 8f80e6e2927..b6718ec8c41 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -215,7 +215,7 @@ impl<'matcher> Tracker<'matcher> for FailureForwarder { } pub(super) fn emit_frag_parse_err( - mut e: DiagnosticBuilder<'_, rustc_errors::ErrorGuaranteed>, + mut e: DiagnosticBuilder<'_>, parser: &Parser<'_>, orig_parser: &mut Parser<'_>, site_span: Span, @@ -224,11 +224,11 @@ pub(super) fn emit_frag_parse_err( ) { // FIXME(davidtwco): avoid depending on the error message text if parser.token == token::Eof - && let DiagnosticMessage::Str(message) = &e.message[0].0 + && let DiagnosticMessage::Str(message) = &e.messages[0].0 && message.ends_with(", found `<eof>`") { - let msg = &e.message[0]; - e.message[0] = ( + let msg = &e.messages[0]; + e.messages[0] = ( DiagnosticMessage::from(format!( "macro expansion ends with an incomplete expression: {}", message.replace(", found `<eof>`", ""), diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 80fd82e0302..ac5f3fb325d 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -9,8 +9,8 @@ use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree}; use rustc_data_structures::fx::FxHashMap; +use rustc_errors::DiagnosticBuilder; use rustc_errors::{pluralize, PResult}; -use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; use rustc_span::hygiene::{LocalExpnId, Transparency}; use rustc_span::symbol::{sym, Ident, MacroRulesNormalizedIdent}; use rustc_span::Span; @@ -528,7 +528,7 @@ fn out_of_bounds_err<'a>( max: usize, span: Span, ty: &str, -) -> DiagnosticBuilder<'a, ErrorGuaranteed> { +) -> DiagnosticBuilder<'a> { let msg = if max == 0 { format!( "meta-variable expression `{ty}` with depth parameter \ diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index a0dec89d631..cd59ea9092c 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -43,7 +43,7 @@ pub enum ModError<'a> { ModInBlock(Option<Ident>), FileNotFound(Ident, PathBuf, PathBuf), MultipleCandidates(Ident, PathBuf, PathBuf), - ParserError(DiagnosticBuilder<'a, ErrorGuaranteed>), + ParserError(DiagnosticBuilder<'a>), } pub(crate) fn parse_external_mod( diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index c412b064ce9..5eb6aed7253 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -499,12 +499,7 @@ impl server::FreeFunctions for Rustc<'_, '_> { rustc_errors::Diagnostic::new(diagnostic.level.to_internal(), diagnostic.message); diag.set_span(MultiSpan::from_spans(diagnostic.spans)); for child in diagnostic.children { - diag.sub( - child.level.to_internal(), - child.message, - MultiSpan::from_spans(child.spans), - None, - ); + diag.sub(child.level.to_internal(), child.message, MultiSpan::from_spans(child.spans)); } self.sess().dcx.emit_diagnostic(diag); } diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 4993112089a..aa0db9891a5 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -77,7 +77,7 @@ declare_features! ( /// Allows empty structs and enum variants with braces. (accepted, braced_empty_structs, "1.8.0", Some(29720)), /// Allows `c"foo"` literals. - (accepted, c_str_literals, "CURRENT_RUSTC_VERSION", Some(105723)), + (accepted, c_str_literals, "1.76.0", Some(105723)), /// Allows `#[cfg_attr(predicate, multiple, attributes, here)]`. (accepted, cfg_attr_multi, "1.33.0", Some(54881)), /// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests. @@ -341,7 +341,7 @@ declare_features! ( (accepted, track_caller, "1.46.0", Some(47809)), /// Allows dyn upcasting trait objects via supertraits. /// Dyn upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`. - (accepted, trait_upcasting, "CURRENT_RUSTC_VERSION", Some(65991)), + (accepted, trait_upcasting, "1.76.0", Some(65991)), /// Allows #[repr(transparent)] on univariant enums (RFC 2645). (accepted, transparent_enums, "1.42.0", Some(60405)), /// Allows indexing tuples. diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 0d9b8b344cf..67ee53d8ae5 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -177,7 +177,7 @@ declare_features! ( /// Allows using the `#[register_attr]` attribute. (removed, register_attr, "1.65.0", Some(66080), Some("removed in favor of `#![register_tool]`")), - (removed, rust_2018_preview, "CURRENT_RUSTC_VERSION", None, + (removed, rust_2018_preview, "1.76.0", None, Some("2018 Edition preview is no longer relevant")), /// Allows using the macros: /// + `__diagnostic_used` diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index bbf5e031175..60586f54fd5 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -204,7 +204,7 @@ declare_features! ( /// Allows using `#[lang = ".."]` attribute for linking items to special compiler logic. (internal, lang_items, "1.0.0", None), /// Changes `impl Trait` to capture all lifetimes in scope. - (unstable, lifetime_capture_rules_2024, "CURRENT_RUSTC_VERSION", None), + (unstable, lifetime_capture_rules_2024, "1.76.0", None), /// Allows `#[link(..., cfg(..))]`; perma-unstable per #37406 (unstable, link_cfg, "1.14.0", None), /// Allows the `multiple_supertrait_upcastable` lint. @@ -357,6 +357,8 @@ declare_features! ( (unstable, async_closure, "1.37.0", Some(62290)), /// Allows `#[track_caller]` on async functions. (unstable, async_fn_track_caller, "1.73.0", Some(110011)), + /// Allows `for await` loops. + (unstable, async_for_loop, "CURRENT_RUSTC_VERSION", Some(118898)), /// Allows builtin # foo() syntax (unstable, builtin_syntax, "1.71.0", Some(110680)), /// Treat `extern "C"` function as nounwind. @@ -468,7 +470,7 @@ declare_features! ( /// Allows using `#[repr(align(...))]` on function items (unstable, fn_align, "1.53.0", Some(82232)), /// Support delegating implementation of functions to other already implemented functions. - (incomplete, fn_delegation, "CURRENT_RUSTC_VERSION", Some(118212)), + (incomplete, fn_delegation, "1.76.0", Some(118212)), /// Allows defining gen blocks and `gen fn`. (unstable, gen_blocks, "1.75.0", Some(117078)), /// Infer generic args for both consts and types. @@ -505,7 +507,7 @@ declare_features! ( (unstable, let_chains, "1.37.0", Some(53667)), /// Allows using `#[link(kind = "link-arg", name = "...")]` /// to pass custom arguments to the linker. - (unstable, link_arg_attribute, "CURRENT_RUSTC_VERSION", Some(99427)), + (unstable, link_arg_attribute, "1.76.0", Some(99427)), /// Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check. (unstable, lint_reasons, "1.31.0", Some(54503)), /// Give access to additional metadata about declarative macro meta-variables. @@ -527,7 +529,7 @@ declare_features! ( /// Allow negative trait implementations. (unstable, negative_impls, "1.44.0", Some(68318)), /// Allows the `!` pattern. - (incomplete, never_patterns, "CURRENT_RUSTC_VERSION", Some(118155)), + (incomplete, never_patterns, "1.76.0", Some(118155)), /// Allows the `!` type. Does not imply 'exhaustive_patterns' (below) any more. (unstable, never_type, "1.13.0", Some(35121)), /// Allows diverging expressions to fall back to `!` rather than `()`. diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 3179fd73604..452f5d0b7ac 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -417,8 +417,7 @@ pub enum GenericArgsParentheses { ParenSugar, } -/// A modifier on a bound, currently this is only used for `?Sized`, where the -/// modifier is `Maybe`. Negative bounds should also be handled here. +/// A modifier on a trait bound. #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub enum TraitBoundModifier { None, @@ -1352,15 +1351,8 @@ impl<'hir> Body<'hir> { /// The type of source expression that caused this coroutine to be created. #[derive(Clone, PartialEq, Eq, Debug, Copy, Hash, HashStable_Generic, Encodable, Decodable)] pub enum CoroutineKind { - /// An explicit `async` block or the body of an `async` function. - Async(CoroutineSource), - - /// An explicit `gen` block or the body of a `gen` function. - Gen(CoroutineSource), - - /// An explicit `async gen` block or the body of an `async gen` function, - /// which is able to both `yield` and `.await`. - AsyncGen(CoroutineSource), + /// A coroutine that comes from a desugaring. + Desugared(CoroutineDesugaring, CoroutineSource), /// A coroutine literal created via a `yield` inside a closure. Coroutine, @@ -1369,31 +1361,11 @@ pub enum CoroutineKind { impl fmt::Display for CoroutineKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - CoroutineKind::Async(k) => { - if f.alternate() { - f.write_str("`async` ")?; - } else { - f.write_str("async ")? - } + CoroutineKind::Desugared(d, k) => { + d.fmt(f)?; k.fmt(f) } CoroutineKind::Coroutine => f.write_str("coroutine"), - CoroutineKind::Gen(k) => { - if f.alternate() { - f.write_str("`gen` ")?; - } else { - f.write_str("gen ")? - } - k.fmt(f) - } - CoroutineKind::AsyncGen(k) => { - if f.alternate() { - f.write_str("`async gen` ")?; - } else { - f.write_str("async gen ")? - } - k.fmt(f) - } } } } @@ -1426,6 +1398,49 @@ impl fmt::Display for CoroutineSource { } } +#[derive(Clone, PartialEq, Eq, Debug, Copy, Hash, HashStable_Generic, Encodable, Decodable)] +pub enum CoroutineDesugaring { + /// An explicit `async` block or the body of an `async` function. + Async, + + /// An explicit `gen` block or the body of a `gen` function. + Gen, + + /// An explicit `async gen` block or the body of an `async gen` function, + /// which is able to both `yield` and `.await`. + AsyncGen, +} + +impl fmt::Display for CoroutineDesugaring { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + CoroutineDesugaring::Async => { + if f.alternate() { + f.write_str("`async` ")?; + } else { + f.write_str("async ")? + } + } + CoroutineDesugaring::Gen => { + if f.alternate() { + f.write_str("`gen` ")?; + } else { + f.write_str("gen ")? + } + } + CoroutineDesugaring::AsyncGen => { + if f.alternate() { + f.write_str("`async gen` ")?; + } else { + f.write_str("async gen ")? + } + } + } + + Ok(()) + } +} + #[derive(Copy, Clone, Debug)] pub enum BodyOwnerKind { /// Functions and methods. diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index b0b53bb7478..3f3b57ba94f 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -307,6 +307,9 @@ language_item_table! { Context, sym::Context, context, Target::Struct, GenericRequirement::None; FuturePoll, sym::poll, future_poll_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None; + AsyncIteratorPollNext, sym::async_iterator_poll_next, async_iterator_poll_next, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::Exact(0); + IntoAsyncIterIntoIter, sym::into_async_iter_into_iter, into_async_iter_into_iter, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::Exact(0); + Option, sym::Option, option_type, Target::Enum, GenericRequirement::None; OptionSome, sym::Some, option_some_variant, Target::Variant, GenericRequirement::None; OptionNone, sym::None, option_none_variant, Target::Variant, GenericRequirement::None; diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 6f8e80172dd..ab281ef929d 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -378,7 +378,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { assert!(self_ty.is_none()); } - let arg_count = check_generic_arg_count( + let mut arg_count = check_generic_arg_count( tcx, span, def_id, @@ -560,6 +560,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { inferred_params: vec![], infer_args, }; + if let ty::BoundConstness::ConstIfConst = constness + && generics.has_self + && !tcx.has_attr(def_id, sym::const_trait) + { + let e = tcx.sess.emit_err(crate::errors::ConstBoundForNonConstTrait { span }); + arg_count.correct = + Err(GenericArgCountMismatch { reported: Some(e), invalid_args: vec![] }); + } let args = create_args_for_parent_generic_args( tcx, def_id, @@ -570,13 +578,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &mut args_ctx, ); - if let ty::BoundConstness::ConstIfConst = constness - && generics.has_self - && !tcx.has_attr(def_id, sym::const_trait) - { - tcx.sess.emit_err(crate::errors::ConstBoundForNonConstTrait { span }); - } - (args, arg_count) } @@ -2686,7 +2687,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &self, constrained_regions: FxHashSet<ty::BoundRegionKind>, referenced_regions: FxHashSet<ty::BoundRegionKind>, - generate_err: impl Fn(&str) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>, + generate_err: impl Fn(&str) -> DiagnosticBuilder<'tcx>, ) { for br in referenced_regions.difference(&constrained_regions) { let br_name = match *br { diff --git a/compiler/rustc_hir_analysis/src/check/entry.rs b/compiler/rustc_hir_analysis/src/check/entry.rs index 1d737e17e82..a82853a1303 100644 --- a/compiler/rustc_hir_analysis/src/check/entry.rs +++ b/compiler/rustc_hir_analysis/src/check/entry.rs @@ -124,7 +124,10 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { if let Some(term_did) = tcx.lang_items().termination() { let return_ty = main_fnsig.output(); let return_ty_span = main_fn_return_type_span(tcx, main_def_id).unwrap_or(main_span); - let return_ty = return_ty.skip_binder(); + let Some(return_ty) = return_ty.no_bound_vars() else { + tcx.sess.emit_err(errors::MainFunctionReturnTypeGeneric { span: return_ty_span }); + return; + }; let infcx = tcx.infer_ctxt().build(); let cause = traits::ObligationCause::new( return_ty_span, diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index b2ff7959106..cc34dbfd9b9 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1912,11 +1912,7 @@ fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalModDefId) -> Result<(), Error res.and(items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.owner_id))) } -fn error_392( - tcx: TyCtxt<'_>, - span: Span, - param_name: Symbol, -) -> DiagnosticBuilder<'_, ErrorGuaranteed> { +fn error_392(tcx: TyCtxt<'_>, span: Span, param_name: Symbol) -> DiagnosticBuilder<'_> { let mut err = struct_span_err!(tcx.sess, span, E0392, "parameter `{param_name}` is never used"); err.span_label(span, "unused parameter"); err diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index d48535c82f5..d43b4adfe39 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -181,7 +181,7 @@ pub(crate) fn placeholder_type_error_diag<'tcx>( suggest: bool, hir_ty: Option<&hir::Ty<'_>>, kind: &'static str, -) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { +) -> DiagnosticBuilder<'tcx> { if placeholder_types.is_empty() { return bad_placeholder(tcx, additional_spans, kind); } @@ -333,7 +333,7 @@ fn bad_placeholder<'tcx>( tcx: TyCtxt<'tcx>, mut spans: Vec<Span>, kind: &'static str, -) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { +) -> DiagnosticBuilder<'tcx> { let kind = if kind.ends_with('s') { format!("{kind}es") } else { format!("{kind}s") }; spans.sort(); diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index f461b6a94ec..41f30057902 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -2,8 +2,8 @@ use crate::fluent_generated as fluent; use rustc_errors::{ - error_code, Applicability, DiagCtxt, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, - MultiSpan, + error_code, Applicability, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, + Level, MultiSpan, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::Ty; @@ -315,14 +315,12 @@ pub struct MissingTypeParams { } // Manual implementation of `IntoDiagnostic` to be able to call `span_to_snippet`. -impl<'a> IntoDiagnostic<'a> for MissingTypeParams { +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for MissingTypeParams { #[track_caller] - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - let mut err = dcx.struct_span_err_with_code( - self.span, - fluent::hir_analysis_missing_type_params, - error_code!(E0393), - ); + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { + let mut err = DiagnosticBuilder::new(dcx, level, fluent::hir_analysis_missing_type_params); + err.set_span(self.span); + err.code(error_code!(E0393)); err.set_arg("parameterCount", self.missing_type_params.len()); err.set_arg( "parameters", diff --git a/compiler/rustc_hir_analysis/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs index 9541e510702..5d2aea7441b 100644 --- a/compiler/rustc_hir_analysis/src/outlives/mod.rs +++ b/compiler/rustc_hir_analysis/src/outlives/mod.rs @@ -4,7 +4,6 @@ use rustc_hir::def_id::LocalDefId; use rustc_middle::query::Providers; use rustc_middle::ty::GenericArgKind; use rustc_middle::ty::{self, CratePredicatesMap, ToPredicate, TyCtxt}; -use rustc_span::symbol::sym; use rustc_span::Span; mod explicit; @@ -49,25 +48,6 @@ fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clau let predicates = crate_map.predicates.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]); - if tcx.has_attr(item_def_id, sym::rustc_outlives) { - let mut pred: Vec<String> = predicates - .iter() - .map(|(out_pred, _)| match out_pred.kind().skip_binder() { - ty::ClauseKind::RegionOutlives(p) => p.to_string(), - ty::ClauseKind::TypeOutlives(p) => p.to_string(), - err => bug!("unexpected clause {:?}", err), - }) - .collect(); - pred.sort(); - - let span = tcx.def_span(item_def_id); - let mut err = tcx.sess.struct_span_err(span, "rustc_outlives"); - for p in pred { - err.note(p); - } - err.emit(); - } - debug!("inferred_outlives_of({:?}) = {:?}", item_def_id, predicates); predicates diff --git a/compiler/rustc_hir_analysis/src/outlives/test.rs b/compiler/rustc_hir_analysis/src/outlives/test.rs index 60f8e246ad6..b3cbc312721 100644 --- a/compiler/rustc_hir_analysis/src/outlives/test.rs +++ b/compiler/rustc_hir_analysis/src/outlives/test.rs @@ -1,5 +1,4 @@ -use rustc_errors::struct_span_err; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{self, TyCtxt}; use rustc_span::symbol::sym; pub fn test_inferred_outlives(tcx: TyCtxt<'_>) { @@ -7,15 +6,23 @@ pub fn test_inferred_outlives(tcx: TyCtxt<'_>) { // For unit testing: check for a special "rustc_outlives" // attribute and report an error with various results if found. if tcx.has_attr(id.owner_id, sym::rustc_outlives) { - let inferred_outlives_of = tcx.inferred_outlives_of(id.owner_id); - struct_span_err!( - tcx.sess, - tcx.def_span(id.owner_id), - E0640, - "{:?}", - inferred_outlives_of - ) - .emit(); + let predicates = tcx.inferred_outlives_of(id.owner_id); + let mut pred: Vec<String> = predicates + .iter() + .map(|(out_pred, _)| match out_pred.kind().skip_binder() { + ty::ClauseKind::RegionOutlives(p) => p.to_string(), + ty::ClauseKind::TypeOutlives(p) => p.to_string(), + err => bug!("unexpected clause {:?}", err), + }) + .collect(); + pred.sort(); + + let span = tcx.def_span(id.owner_id); + let mut err = tcx.sess.struct_span_err(span, "rustc_outlives"); + for p in pred { + err.note(p); + } + err.emit(); } } } diff --git a/compiler/rustc_hir_analysis/src/structured_errors.rs b/compiler/rustc_hir_analysis/src/structured_errors.rs index 0b46fce1735..04d04304e70 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors.rs @@ -6,7 +6,7 @@ pub use self::{ missing_cast_for_variadic_arg::*, sized_unsized_cast::*, wrong_number_of_generic_args::*, }; -use rustc_errors::{DiagnosticBuilder, DiagnosticId, ErrorGuaranteed}; +use rustc_errors::{DiagnosticBuilder, DiagnosticId}; use rustc_session::Session; pub trait StructuredDiagnostic<'tcx> { @@ -14,7 +14,7 @@ pub trait StructuredDiagnostic<'tcx> { fn code(&self) -> DiagnosticId; - fn diagnostic(&self) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn diagnostic(&self) -> DiagnosticBuilder<'tcx> { let err = self.diagnostic_common(); if self.session().teach(&self.code()) { @@ -24,19 +24,13 @@ pub trait StructuredDiagnostic<'tcx> { } } - fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>; + fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx>; - fn diagnostic_regular( - &self, - err: DiagnosticBuilder<'tcx, ErrorGuaranteed>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn diagnostic_regular(&self, err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> { err } - fn diagnostic_extended( - &self, - err: DiagnosticBuilder<'tcx, ErrorGuaranteed>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn diagnostic_extended(&self, err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> { err } } diff --git a/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs b/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs index c37dff61b72..7cc4982820b 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs @@ -1,5 +1,5 @@ use crate::{errors, structured_errors::StructuredDiagnostic}; -use rustc_errors::{DiagnosticBuilder, DiagnosticId, ErrorGuaranteed}; +use rustc_errors::{DiagnosticBuilder, DiagnosticId}; use rustc_middle::ty::{Ty, TypeVisitableExt}; use rustc_session::Session; use rustc_span::Span; @@ -20,7 +20,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for MissingCastForVariadicArg<'tcx, '_> { rustc_errors::error_code!(E0617) } - fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx> { let (sugg_span, replace, help) = if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.span) { (Some(self.span), format!("{} as {}", snippet, self.cast_ty), None) @@ -44,10 +44,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for MissingCastForVariadicArg<'tcx, '_> { err } - fn diagnostic_extended( - &self, - mut err: DiagnosticBuilder<'tcx, ErrorGuaranteed>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn diagnostic_extended(&self, mut err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> { err.note(format!( "certain types, like `{}`, must be casted before passing them to a \ variadic function, because of arcane ABI rules dictated by the C \ diff --git a/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs b/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs index 910417abe6e..6ba27f49744 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs @@ -1,5 +1,5 @@ use crate::{errors, structured_errors::StructuredDiagnostic}; -use rustc_errors::{DiagnosticBuilder, DiagnosticId, ErrorGuaranteed}; +use rustc_errors::{DiagnosticBuilder, DiagnosticId}; use rustc_middle::ty::{Ty, TypeVisitableExt}; use rustc_session::Session; use rustc_span::Span; @@ -20,7 +20,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCast<'tcx> { rustc_errors::error_code!(E0607) } - fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx> { let mut err = self.sess.create_err(errors::CastThinPointerToFatPointer { span: self.span, expr_ty: self.expr_ty, @@ -34,10 +34,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCast<'tcx> { err } - fn diagnostic_extended( - &self, - mut err: DiagnosticBuilder<'tcx, ErrorGuaranteed>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn diagnostic_extended(&self, mut err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> { err.help( "Thin pointers are \"simple\" pointers: they are purely a reference to a memory address. diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs index fab841e3679..c7818d80dbf 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs @@ -1,7 +1,6 @@ use crate::structured_errors::StructuredDiagnostic; use rustc_errors::{ - pluralize, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId, ErrorGuaranteed, - MultiSpan, + pluralize, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId, MultiSpan, }; use rustc_hir as hir; use rustc_middle::ty::{self as ty, AssocItems, AssocKind, TyCtxt}; @@ -521,7 +520,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { } } - fn start_diagnostics(&self) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn start_diagnostics(&self) -> DiagnosticBuilder<'tcx> { let span = self.path_segment.ident.span; let msg = self.create_error_message(); @@ -1113,7 +1112,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for WrongNumberOfGenericArgs<'_, 'tcx> { rustc_errors::error_code!(E0107) } - fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx> { let mut err = self.start_diagnostics(); self.notify(&mut err); diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 6715d01c9e0..feaec5ac620 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -553,17 +553,7 @@ impl<'a> State<'a> { } hir::ItemKind::OpaqueTy(opaque_ty) => { self.print_item_type(item, opaque_ty.generics, |state| { - let mut real_bounds = Vec::with_capacity(opaque_ty.bounds.len()); - for b in opaque_ty.bounds { - if let GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = b { - state.space(); - state.word_space("for ?"); - state.print_trait_ref(&ptr.trait_ref); - } else { - real_bounds.push(b); - } - } - state.print_bounds("= impl", real_bounds); + state.print_bounds("= impl", opaque_ty.bounds) }); } hir::ItemKind::Enum(ref enum_definition, params) => { @@ -625,17 +615,7 @@ impl<'a> State<'a> { self.word_nbsp("trait"); self.print_ident(item.ident); self.print_generic_params(generics.params); - let mut real_bounds = Vec::with_capacity(bounds.len()); - for b in bounds { - if let GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = b { - self.space(); - self.word_space("for ?"); - self.print_trait_ref(&ptr.trait_ref); - } else { - real_bounds.push(b); - } - } - self.print_bounds(":", real_bounds); + self.print_bounds(":", bounds); self.print_where_clause(generics); self.word(" "); self.bopen(); diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 5e6b54950b3..2146effd84f 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -305,8 +305,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) = (parent_node, callee_node) { let fn_decl_span = if hir.body(body).coroutine_kind - == Some(hir::CoroutineKind::Async(hir::CoroutineSource::Closure)) - { + == Some(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Async, + hir::CoroutineSource::Closure, + )) { // Actually need to unwrap one more layer of HIR to get to // the _real_ closure... let async_closure = hir.parent_id(parent_hir_id); diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 0de0365364c..9783fe79a90 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -187,7 +187,7 @@ fn make_invalid_casting_error<'a, 'tcx>( expr_ty: Ty<'tcx>, cast_ty: Ty<'tcx>, fcx: &FnCtxt<'a, 'tcx>, -) -> DiagnosticBuilder<'a, ErrorGuaranteed> { +) -> DiagnosticBuilder<'a> { type_error_struct!( sess, span, diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 2855cea80b2..8e2af402918 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -59,7 +59,8 @@ pub(super) fn check_fn<'a, 'tcx>( && can_be_coroutine.is_some() { let yield_ty = match kind { - hir::CoroutineKind::Gen(..) | hir::CoroutineKind::Coroutine => { + hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _) + | hir::CoroutineKind::Coroutine => { let yield_ty = fcx.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span, @@ -71,7 +72,7 @@ pub(super) fn check_fn<'a, 'tcx>( // guide inference on the yield type so that we can handle `AsyncIterator` // in this block in projection correctly. In the new trait solver, it is // not a problem. - hir::CoroutineKind::AsyncGen(..) => { + hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _) => { let yield_ty = fcx.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span, @@ -89,7 +90,7 @@ pub(super) fn check_fn<'a, 'tcx>( .into()]), ) } - hir::CoroutineKind::Async(..) => Ty::new_unit(tcx), + hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _) => Ty::new_unit(tcx), }; // Resume type defaults to `()` if the coroutine has no argument. diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index d19d304128a..cd42be28e6f 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -634,7 +634,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // In the case of the async block that we create for a function body, // we expect the return type of the block to match that of the enclosing // function. - Some(hir::CoroutineKind::Async(hir::CoroutineSource::Fn)) => { + Some(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Async, + hir::CoroutineSource::Fn, + )) => { debug!("closure is async fn body"); let def_id = self.tcx.hir().body_owner_def_id(body.id()); self.deduce_future_output_from_obligations(expr_def_id, def_id).unwrap_or_else( @@ -651,9 +654,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) } // All `gen {}` and `async gen {}` must return unit. - Some(hir::CoroutineKind::Gen(_) | hir::CoroutineKind::AsyncGen(_)) => { - self.tcx.types.unit - } + Some( + hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _) + | hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _), + ) => self.tcx.types.unit, _ => astconv.ty_infer(None, decl.output.span()), }, diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 61236c07135..aed2dbb4505 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -36,9 +36,7 @@ //! ``` use crate::FnCtxt; -use rustc_errors::{ - struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, -}; +use rustc_errors::{struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, Visitor}; @@ -1772,7 +1770,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { id: hir::HirId, expression: Option<&'tcx hir::Expr<'tcx>>, blk_id: Option<hir::HirId>, - ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'a> { let mut err = fcx.err_ctxt().report_mismatched_types(cause, expected, found, ty_err); let parent_id = fcx.tcx.hir().parent_id(id); diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 8b666c63425..6e5bd740b2e 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -1,6 +1,6 @@ use crate::FnCtxt; use rustc_errors::MultiSpan; -use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed}; +use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::intravisit::Visitor; @@ -168,7 +168,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>, - ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { + ) -> Option<DiagnosticBuilder<'tcx>> { self.demand_suptype_with_origin(&self.misc(sp), expected, actual) } @@ -178,7 +178,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { cause: &ObligationCause<'tcx>, expected: Ty<'tcx>, actual: Ty<'tcx>, - ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { + ) -> Option<DiagnosticBuilder<'tcx>> { match self.at(cause, self.param_env).sup(DefineOpaqueTypes::Yes, expected, actual) { Ok(InferOk { obligations, value: () }) => { self.register_predicates(obligations); @@ -199,7 +199,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>, - ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { + ) -> Option<DiagnosticBuilder<'tcx>> { self.demand_eqtype_with_origin(&self.misc(sp), expected, actual) } @@ -208,7 +208,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { cause: &ObligationCause<'tcx>, expected: Ty<'tcx>, actual: Ty<'tcx>, - ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { + ) -> Option<DiagnosticBuilder<'tcx>> { match self.at(cause, self.param_env).eq(DefineOpaqueTypes::Yes, expected, actual) { Ok(InferOk { obligations, value: () }) => { self.register_predicates(obligations); @@ -246,7 +246,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, mut expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>, allow_two_phase: AllowTwoPhase, - ) -> (Ty<'tcx>, Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>>) { + ) -> (Ty<'tcx>, Option<DiagnosticBuilder<'tcx>>) { let expected = self.resolve_vars_with_obligations(expected); let e = match self.coerce(expr, checked_ty, expected, allow_two_phase, None) { diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 7bd2c3f8b6b..c4755b852bd 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -722,7 +722,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let [segment] = path.segments && segment.ident.name == sym::rust { - fatally_break_rust(self.tcx); + fatally_break_rust(self.tcx, expr.span); } } } @@ -966,7 +966,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn check_for_missing_semi( &self, expr: &'tcx hir::Expr<'tcx>, - err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>, + err: &mut DiagnosticBuilder<'_>, ) -> bool { if let hir::ExprKind::Binary(binop, lhs, rhs) = expr.kind && let hir::BinOpKind::Mul = binop.node @@ -2738,7 +2738,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { field: Ident, expr_t: Ty<'tcx>, id: HirId, - ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'_> { let span = field.span; debug!("no_such_field_err(span: {:?}, field: {:?}, expr_t: {:?})", span, field, expr_t); @@ -2821,11 +2821,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err } - fn private_field_err( - &self, - field: Ident, - base_did: DefId, - ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + fn private_field_err(&self, field: Ident, base_did: DefId) -> DiagnosticBuilder<'_> { let struct_path = self.tcx().def_path_str(base_did); let kind_name = self.tcx().def_descr(base_did); let mut err = struct_span_err!( diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 4caa0df58b6..752401845cd 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1258,7 +1258,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected_ty: Ty<'tcx>, provided_ty: Ty<'tcx>, arg: &hir::Expr<'tcx>, - err: &mut rustc_errors::DiagnosticBuilder<'tcx, ErrorGuaranteed>, + err: &mut rustc_errors::DiagnosticBuilder<'tcx>, ) { if let ty::RawPtr(ty::TypeAndMut { mutbl: hir::Mutability::Mut, .. }) = expected_ty.kind() && let ty::RawPtr(ty::TypeAndMut { mutbl: hir::Mutability::Not, .. }) = diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 668e547571f..d2917b25c54 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -17,8 +17,8 @@ use rustc_hir::def::Res; use rustc_hir::def::{CtorKind, CtorOf, DefKind}; use rustc_hir::lang_items::LangItem; use rustc_hir::{ - CoroutineKind, CoroutineSource, Expr, ExprKind, GenericBound, HirId, Node, Path, QPath, Stmt, - StmtKind, TyKind, WherePredicate, + CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, GenericBound, HirId, Node, + Path, QPath, Stmt, StmtKind, TyKind, WherePredicate, }; use rustc_hir_analysis::astconv::AstConv; use rustc_infer::traits::{self, StatementAsExpression}; @@ -549,7 +549,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Coroutine(def_id, ..) if matches!( self.tcx.coroutine_kind(def_id), - Some(CoroutineKind::Async(CoroutineSource::Closure)) + Some(CoroutineKind::Desugared( + CoroutineDesugaring::Async, + CoroutineSource::Closure + )) ) => { errors::SuggestBoxing::AsyncBody diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 13a24948611..c6d7650f745 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -52,7 +52,7 @@ use crate::expectation::Expectation; use crate::fn_ctxt::RawTy; use crate::gather_locals::GatherLocalsVisitor; use rustc_data_structures::unord::UnordSet; -use rustc_errors::{struct_span_err, DiagnosticId, ErrorGuaranteed, MultiSpan}; +use rustc_errors::{struct_span_err, DiagnosticId, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::Visitor; @@ -412,24 +412,25 @@ enum TupleArgumentsFlag { TupleArguments, } -fn fatally_break_rust(tcx: TyCtxt<'_>) { +fn fatally_break_rust(tcx: TyCtxt<'_>, span: Span) -> ! { let dcx = tcx.sess.dcx(); - dcx.span_bug_no_panic( - MultiSpan::new(), + let mut diag = dcx.struct_span_bug( + span, "It looks like you're trying to break rust; would you like some ICE?", ); - dcx.note("the compiler expectedly panicked. this is a feature."); - dcx.note( + diag.note("the compiler expectedly panicked. this is a feature."); + diag.note( "we would appreciate a joke overview: \ https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675", ); - dcx.note(format!("rustc {} running on {}", tcx.sess.cfg_version, config::host_triple(),)); + diag.note(format!("rustc {} running on {}", tcx.sess.cfg_version, config::host_triple(),)); if let Some((flags, excluded_cargo_defaults)) = rustc_session::utils::extra_compiler_flags() { - dcx.note(format!("compiler flags: {}", flags.join(" "))); + diag.note(format!("compiler flags: {}", flags.join(" "))); if excluded_cargo_defaults { - dcx.note("some of the compiler flags provided by cargo are hidden"); + diag.note("some of the compiler flags provided by cargo are hidden"); } } + diag.emit() } /// `expected` here is the expected number of explicit generic arguments on the trait. diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 7595f21d9f1..9327161eccb 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -13,8 +13,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::unord::UnordSet; use rustc_errors::StashKey; use rustc_errors::{ - pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, - MultiSpan, + pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan, }; use rustc_hir as hir; use rustc_hir::def::DefKind; @@ -120,7 +119,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { args: Option<&'tcx [hir::Expr<'tcx>]>, expected: Expectation<'tcx>, trait_missing_method: bool, - ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> { + ) -> Option<DiagnosticBuilder<'_>> { // Avoid suggestions when we don't know what's going on. if rcvr_ty.references_error() { return None; @@ -261,7 +260,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, rcvr_ty: Ty<'tcx>, rcvr_expr: &hir::Expr<'tcx>, - ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'_> { let mut file = None; let ty_str = self.tcx.short_ty_string(rcvr_ty, &mut file); let mut err = struct_span_err!( @@ -299,7 +298,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { no_match_data: &mut NoMatchData<'tcx>, expected: Expectation<'tcx>, trait_missing_method: bool, - ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> { + ) -> Option<DiagnosticBuilder<'_>> { let mode = no_match_data.mode; let tcx = self.tcx; let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty); diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 56a420fab4f..0c0af51cb0d 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -99,7 +99,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { expected: Ty<'tcx>, actual: Ty<'tcx>, ti: TopInfo<'tcx>, - ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { + ) -> Option<DiagnosticBuilder<'tcx>> { let mut diag = self.demand_eqtype_with_origin(&self.pattern_cause(ti, cause_span), expected, actual)?; if let Some(expr) = ti.origin_expr { @@ -967,7 +967,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn emit_bad_pat_path( &self, - mut e: DiagnosticBuilder<'_, ErrorGuaranteed>, + mut e: DiagnosticBuilder<'_>, pat: &hir::Pat<'tcx>, res: Res, pat_res: Res, @@ -1508,7 +1508,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { variant: &VariantDef, pat: &'_ Pat<'_>, fields: &[hir::PatField<'_>], - ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> { + ) -> Option<DiagnosticBuilder<'_>> { // if this is a tuple struct, then all field names will be numbers // so if any fields in a struct pattern use shorthand syntax, they will // be invalid identifiers (for example, Foo { 0, 1 }). @@ -1584,7 +1584,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat: &'tcx Pat<'tcx>, variant: &ty::VariantDef, args: &'tcx ty::List<ty::GenericArg<'tcx>>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { let tcx = self.tcx; let (field_names, t, plural) = if let [field] = inexistent_fields { (format!("a field named `{}`", field.ident), "this", "") @@ -1689,7 +1689,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat: &Pat<'_>, fields: &'tcx [hir::PatField<'tcx>], variant: &ty::VariantDef, - ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { + ) -> Option<DiagnosticBuilder<'tcx>> { if let (Some(CtorKind::Fn), PatKind::Struct(qpath, pattern_fields, ..)) = (variant.ctor_kind(), &pat.kind) { @@ -1775,7 +1775,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, pat: &Pat<'_>, fields: &'tcx [hir::PatField<'tcx>], - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { let mut err = self .tcx .sess @@ -1867,7 +1867,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { unmentioned_fields: &[(&ty::FieldDef, Ident)], have_inaccessible_fields: bool, fields: &'tcx [hir::PatField<'tcx>], - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { let inaccessible = if have_inaccessible_fields { " and inaccessible fields" } else { "" }; let field_names = if let [(_, field)] = unmentioned_fields { format!("field `{field}`{inaccessible}") diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index 3ea1a52ae28..d730ef58deb 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -502,6 +502,7 @@ impl<T: Idx> ChunkedBitSet<T> { }; #[cfg(not(feature = "nightly"))] let mut words = { + // FIXME: unconditionally use `Rc::new_zeroed` once it is stable (#63291). let words = mem::MaybeUninit::<[Word; CHUNK_WORDS]>::zeroed(); // SAFETY: `words` can safely be all zeroes. let words = unsafe { words.assume_init() }; @@ -567,6 +568,7 @@ impl<T: Idx> ChunkedBitSet<T> { }; #[cfg(not(feature = "nightly"))] let mut words = { + // FIXME: unconditionally use `Rc::new_zeroed` once it is stable (#63291). let words = mem::MaybeUninit::<[Word; CHUNK_WORDS]>::zeroed(); // SAFETY: `words` can safely be all zeroes. let words = unsafe { words.assume_init() }; diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index d396c41007b..d77c224f3c8 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -306,7 +306,7 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>( hidden_ty: Ty<'tcx>, hidden_region: ty::Region<'tcx>, opaque_ty_key: ty::OpaqueTypeKey<'tcx>, -) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { +) -> DiagnosticBuilder<'tcx> { let mut err = tcx.sess.create_err(errors::OpaqueCapturesLifetime { span, opaque_ty: Ty::new_opaque(tcx, opaque_ty_key.def_id.to_def_id(), opaque_ty_key.args), @@ -2171,7 +2171,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { &self, trace: TypeTrace<'tcx>, terr: TypeError<'tcx>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { debug!("report_and_explain_type_error(trace={:?}, terr={:?})", trace, terr); let span = trace.cause.span(); @@ -2319,7 +2319,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { origin: Option<SubregionOrigin<'tcx>>, bound_kind: GenericKind<'tcx>, sub: Region<'tcx>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { if let Some(SubregionOrigin::CompareImplItemObligation { span, impl_item_def_id, @@ -2732,7 +2732,7 @@ impl<'tcx> InferCtxt<'tcx> { fn report_inference_failure( &self, var_origin: RegionVariableOrigin, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { let br_string = |br: ty::BoundRegionKind| { let mut s = match br { ty::BrNamed(_, name) => name.to_string(), diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 817a4451dd1..fd38e52cfde 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -5,8 +5,7 @@ use crate::errors::{ use crate::infer::error_reporting::TypeErrCtxt; use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::infer::InferCtxt; -use rustc_errors::IntoDiagnostic; -use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, IntoDiagnosticArg}; +use rustc_errors::{DiagnosticBuilder, IntoDiagnosticArg}; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::def::{CtorOf, DefKind, Namespace}; @@ -359,7 +358,7 @@ impl<'tcx> InferCtxt<'tcx> { span: Span, arg_data: InferenceDiagnosticsData, error_code: TypeAnnotationNeeded, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { let source_kind = "other"; let source_name = ""; let failure_span = None; @@ -367,7 +366,7 @@ impl<'tcx> InferCtxt<'tcx> { let multi_suggestions = Vec::new(); let bad_label = Some(arg_data.make_bad_error(span)); match error_code { - TypeAnnotationNeeded::E0282 => AnnotationRequired { + TypeAnnotationNeeded::E0282 => self.tcx.sess.dcx().create_err(AnnotationRequired { span, source_kind, source_name, @@ -375,9 +374,8 @@ impl<'tcx> InferCtxt<'tcx> { infer_subdiags, multi_suggestions, bad_label, - } - .into_diagnostic(self.tcx.sess.dcx()), - TypeAnnotationNeeded::E0283 => AmbiguousImpl { + }), + TypeAnnotationNeeded::E0283 => self.tcx.sess.dcx().create_err(AmbiguousImpl { span, source_kind, source_name, @@ -385,9 +383,8 @@ impl<'tcx> InferCtxt<'tcx> { infer_subdiags, multi_suggestions, bad_label, - } - .into_diagnostic(self.tcx.sess.dcx()), - TypeAnnotationNeeded::E0284 => AmbiguousReturn { + }), + TypeAnnotationNeeded::E0284 => self.tcx.sess.dcx().create_err(AmbiguousReturn { span, source_kind, source_name, @@ -395,8 +392,7 @@ impl<'tcx> InferCtxt<'tcx> { infer_subdiags, multi_suggestions, bad_label, - } - .into_diagnostic(self.tcx.sess.dcx()), + }), } } } @@ -410,7 +406,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { arg: GenericArg<'tcx>, error_code: TypeAnnotationNeeded, should_label_span: bool, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { let arg = self.resolve_vars_if_possible(arg); let arg_data = self.extract_inference_diagnostics_data(arg, None); @@ -574,7 +570,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } } match error_code { - TypeAnnotationNeeded::E0282 => AnnotationRequired { + TypeAnnotationNeeded::E0282 => self.tcx.sess.dcx().create_err(AnnotationRequired { span, source_kind, source_name: &name, @@ -582,9 +578,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { infer_subdiags, multi_suggestions, bad_label: None, - } - .into_diagnostic(self.tcx.sess.dcx()), - TypeAnnotationNeeded::E0283 => AmbiguousImpl { + }), + TypeAnnotationNeeded::E0283 => self.tcx.sess.dcx().create_err(AmbiguousImpl { span, source_kind, source_name: &name, @@ -592,9 +587,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { infer_subdiags, multi_suggestions, bad_label: None, - } - .into_diagnostic(self.tcx.sess.dcx()), - TypeAnnotationNeeded::E0284 => AmbiguousReturn { + }), + TypeAnnotationNeeded::E0284 => self.tcx.sess.dcx().create_err(AmbiguousReturn { span, source_kind, source_name: &name, @@ -602,8 +596,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { infer_subdiags, multi_suggestions, bad_label: None, - } - .into_diagnostic(self.tcx.sess.dcx()), + }), } } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs index 2a70c4673b0..e13d1d38a89 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs @@ -50,7 +50,7 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> { self.cx.tcx } - pub fn try_report_from_nll(&self) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { + pub fn try_report_from_nll(&self) -> Option<DiagnosticBuilder<'tcx>> { // Due to the improved diagnostics returned by the MIR borrow checker, only a subset of // the nice region errors are required when running under the MIR borrow checker. self.try_report_named_anon_conflict() diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs index 1b43022f8f7..a5a69b77a05 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs @@ -5,16 +5,14 @@ use crate::{ errors::ExplicitLifetimeRequired, infer::error_reporting::nice_region_error::find_anon_type::find_anon_type, }; -use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; +use rustc_errors::DiagnosticBuilder; use rustc_middle::ty; use rustc_span::symbol::kw; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { /// When given a `ConcreteFailure` for a function with parameters containing a named region and /// an anonymous region, emit an descriptive diagnostic error. - pub(super) fn try_report_named_anon_conflict( - &self, - ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { + pub(super) fn try_report_named_anon_conflict(&self) -> Option<DiagnosticBuilder<'tcx>> { let (span, sub, sup) = self.regions()?; debug!( diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index d98ca995d71..45affb538a3 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -8,7 +8,7 @@ use crate::infer::ValuePairs; use crate::infer::{SubregionOrigin, TypeTrace}; use crate::traits::{ObligationCause, ObligationCauseCode}; use rustc_data_structures::intern::Interned; -use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, IntoDiagnosticArg}; +use rustc_errors::{DiagnosticBuilder, IntoDiagnosticArg}; use rustc_hir::def::Namespace; use rustc_hir::def_id::DefId; use rustc_middle::ty::error::ExpectedFound; @@ -57,9 +57,7 @@ where impl<'tcx> NiceRegionError<'_, 'tcx> { /// When given a `ConcreteFailure` for a function with arguments containing a named region and /// an anonymous region, emit a descriptive diagnostic error. - pub(super) fn try_report_placeholder_conflict( - &self, - ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { + pub(super) fn try_report_placeholder_conflict(&self) -> Option<DiagnosticBuilder<'tcx>> { match &self.error { /////////////////////////////////////////////////////////////////////////// // NB. The ordering of cases in this match is very @@ -195,7 +193,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { sub_placeholder: Option<Region<'tcx>>, sup_placeholder: Option<Region<'tcx>>, value_pairs: &ValuePairs<'tcx>, - ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { + ) -> Option<DiagnosticBuilder<'tcx>> { let (expected_args, found_args, trait_def_id) = match value_pairs { ValuePairs::PolyTraitRefs(ExpectedFound { expected, found }) if expected.def_id() == found.def_id() => @@ -238,7 +236,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { trait_def_id: DefId, expected_args: GenericArgsRef<'tcx>, actual_args: GenericArgsRef<'tcx>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { let span = cause.span(); let (leading_ellipsis, satisfy_span, where_span, dup_span, def_id) = diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs index f5b8912532b..51b65a9dd2d 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs @@ -5,14 +5,12 @@ use crate::{ }, }; use rustc_data_structures::intern::Interned; -use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; +use rustc_errors::DiagnosticBuilder; use rustc_middle::ty::{self, RePlaceholder, Region}; impl<'tcx> NiceRegionError<'_, 'tcx> { /// Emitted wwhen given a `ConcreteFailure` when relating two placeholders. - pub(super) fn try_report_placeholder_relation( - &self, - ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { + pub(super) fn try_report_placeholder_relation(&self) -> Option<DiagnosticBuilder<'tcx>> { match &self.error { Some(RegionResolutionError::ConcreteFailure( SubregionOrigin::RelateRegionParamBound(span), diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index 859c10ef142..73139d8e720 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -5,9 +5,7 @@ use crate::errors::{ use crate::fluent_generated as fluent; use crate::infer::error_reporting::{note_and_explain_region, TypeErrCtxt}; use crate::infer::{self, SubregionOrigin}; -use rustc_errors::{ - AddToDiagnostic, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, -}; +use rustc_errors::{AddToDiagnostic, Diagnostic, DiagnosticBuilder}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::error::TypeError; @@ -80,7 +78,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { origin: SubregionOrigin<'tcx>, sub: Region<'tcx>, sup: Region<'tcx>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { let mut err = match origin { infer::Subtype(box trace) => { let terr = TypeError::RegionsDoesNotOutlive(sup, sub); @@ -136,11 +134,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { note_and_explain::PrefixKind::ContentValidFor, note_and_explain::SuffixKind::Empty, ); - OutlivesContent { + self.tcx.sess.dcx().create_err(OutlivesContent { span, notes: reference_valid.into_iter().chain(content_valid).collect(), - } - .into_diagnostic(self.tcx.sess.dcx()) + }) } infer::RelateObjectBound(span) => { let object_valid = note_and_explain::RegionExplanation::new( @@ -157,11 +154,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { note_and_explain::PrefixKind::SourcePointerValidFor, note_and_explain::SuffixKind::Empty, ); - OutlivesBound { + self.tcx.sess.dcx().create_err(OutlivesBound { span, notes: object_valid.into_iter().chain(pointer_valid).collect(), - } - .into_diagnostic(self.tcx.sess.dcx()) + }) } infer::RelateParamBound(span, ty, opt_span) => { let prefix = match *sub { @@ -176,8 +172,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let note = note_and_explain::RegionExplanation::new( self.tcx, sub, opt_span, prefix, suffix, ); - FulfillReqLifetime { span, ty: self.resolve_vars_if_possible(ty), note } - .into_diagnostic(self.tcx.sess.dcx()) + self.tcx.sess.dcx().create_err(FulfillReqLifetime { + span, + ty: self.resolve_vars_if_possible(ty), + note, + }) } infer::RelateRegionParamBound(span) => { let param_instantiated = note_and_explain::RegionExplanation::new( @@ -194,11 +193,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { note_and_explain::PrefixKind::LfParamMustOutlive, note_and_explain::SuffixKind::Empty, ); - LfBoundNotSatisfied { + self.tcx.sess.dcx().create_err(LfBoundNotSatisfied { span, notes: param_instantiated.into_iter().chain(param_must_outlive).collect(), - } - .into_diagnostic(self.tcx.sess.dcx()) + }) } infer::ReferenceOutlivesReferent(ty, span) => { let pointer_valid = note_and_explain::RegionExplanation::new( @@ -215,12 +213,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { note_and_explain::PrefixKind::DataValidFor, note_and_explain::SuffixKind::Empty, ); - RefLongerThanData { + self.tcx.sess.dcx().create_err(RefLongerThanData { span, ty: self.resolve_vars_if_possible(ty), notes: pointer_valid.into_iter().chain(data_valid).collect(), - } - .into_diagnostic(self.tcx.sess.dcx()) + }) } infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => { let mut err = self.report_extra_impl_obligation( @@ -277,11 +274,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { note_and_explain::PrefixKind::LfMustOutlive, note_and_explain::SuffixKind::Empty, ); - LfBoundNotSatisfied { + self.tcx.sess.dcx().create_err(LfBoundNotSatisfied { span, notes: instantiated.into_iter().chain(must_outlive).collect(), - } - .into_diagnostic(self.tcx.sess.dcx()) + }) } }; if sub.is_error() || sup.is_error() { @@ -354,7 +350,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { placeholder_origin: SubregionOrigin<'tcx>, sub: Region<'tcx>, sup: Region<'tcx>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { // I can't think how to do better than this right now. -nikomatsakis debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure"); match placeholder_origin { diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index 0fbc4a0ce50..76d4dc24dce 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -135,6 +135,10 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { ) -> LexicalRegionResolutions<'tcx> { let mut var_data = self.construct_var_data(); + // Deduplicating constraints is shown to have a positive perf impact. + self.data.constraints.sort_by_key(|(constraint, _)| *constraint); + self.data.constraints.dedup_by_key(|(constraint, _)| *constraint); + if cfg!(debug_assertions) { self.dump_constraints(); } @@ -181,7 +185,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { let mut constraints = IndexVec::from_elem(Vec::new(), &var_values.values); // Tracks the changed region vids. let mut changes = Vec::new(); - for constraint in self.data.constraints.keys() { + for (constraint, _) in &self.data.constraints { match *constraint { Constraint::RegSubVar(a_region, b_vid) => { let b_data = var_values.value_mut(b_vid); @@ -676,7 +680,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { let dummy_source = graph.add_node(()); let dummy_sink = graph.add_node(()); - for constraint in self.data.constraints.keys() { + for (constraint, _) in &self.data.constraints { match *constraint { Constraint::VarSubVar(a_id, b_id) => { graph.add_edge(NodeIndex(a_id.index()), NodeIndex(b_id.index()), *constraint); @@ -883,9 +887,11 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { } Constraint::RegSubVar(region, _) | Constraint::VarSubReg(_, region) => { + let constraint_idx = + this.constraints.binary_search_by(|(c, _)| c.cmp(&edge.data)).unwrap(); state.result.push(RegionAndOrigin { region, - origin: this.constraints.get(&edge.data).unwrap().clone(), + origin: this.constraints[constraint_idx].1.clone(), }); } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index e092bbbfdd6..a36735b7600 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1740,9 +1740,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { sp: Span, mk_diag: M, actual_ty: Ty<'tcx>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> + ) -> DiagnosticBuilder<'tcx> where - M: FnOnce(String) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>, + M: FnOnce(String) -> DiagnosticBuilder<'tcx>, { let actual_ty = self.resolve_vars_if_possible(actual_ty); debug!("type_error_struct_with_diag({:?}, {:?})", sp, actual_ty); @@ -1763,7 +1763,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { expected: Ty<'tcx>, actual: Ty<'tcx>, err: TypeError<'tcx>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { self.report_and_explain_type_error(TypeTrace::types(cause, true, expected, actual), err) } @@ -1773,7 +1773,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { expected: ty::Const<'tcx>, actual: ty::Const<'tcx>, err: TypeError<'tcx>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { self.report_and_explain_type_error(TypeTrace::consts(cause, true, expected, actual), err) } } diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs index e06596df7b9..b2bcbbf2e53 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs @@ -416,8 +416,8 @@ impl<'tcx> MiniGraph<'tcx> { region_constraints.undo_log.region_constraints_in_snapshot(&snapshot.undo_snapshot) { match undo_entry { - AddConstraint(constraint) => { - each_constraint(constraint); + &AddConstraint(i) => { + each_constraint(®ion_constraints.data().constraints[i].0); } &AddVerify(i) => span_bug!( region_constraints.data().verifys[i].origin.span(), @@ -430,8 +430,8 @@ impl<'tcx> MiniGraph<'tcx> { region_constraints .data() .constraints - .keys() - .for_each(|constraint| each_constraint(constraint)); + .iter() + .for_each(|(constraint, _)| each_constraint(constraint)); } } diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index cbd8040c9f1..71adf526097 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -20,7 +20,6 @@ use rustc_middle::ty::{ReBound, ReVar}; use rustc_middle::ty::{Region, RegionVid}; use rustc_span::Span; -use std::collections::BTreeMap; use std::ops::Range; use std::{cmp, fmt, mem}; @@ -90,7 +89,7 @@ pub type VarInfos = IndexVec<RegionVid, RegionVariableInfo>; pub struct RegionConstraintData<'tcx> { /// Constraints of the form `A <= B`, where either `A` or `B` can /// be a region variable (or neither, as it happens). - pub constraints: BTreeMap<Constraint<'tcx>, SubregionOrigin<'tcx>>, + pub constraints: Vec<(Constraint<'tcx>, SubregionOrigin<'tcx>)>, /// Constraints of the form `R0 member of [R1, ..., Rn]`, meaning that /// `R0` must be equal to one of the regions `R1..Rn`. These occur @@ -273,7 +272,7 @@ pub(crate) enum UndoLog<'tcx> { AddVar(RegionVid), /// We added the given `constraint`. - AddConstraint(Constraint<'tcx>), + AddConstraint(usize), /// We added the given `verify`. AddVerify(usize), @@ -319,8 +318,9 @@ impl<'tcx> RegionConstraintStorage<'tcx> { self.var_infos.pop().unwrap(); assert_eq!(self.var_infos.len(), vid.index()); } - AddConstraint(ref constraint) => { - self.data.constraints.remove(constraint); + AddConstraint(index) => { + self.data.constraints.pop().unwrap(); + assert_eq!(self.data.constraints.len(), index); } AddVerify(index) => { self.data.verifys.pop(); @@ -443,14 +443,9 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { // cannot add constraints once regions are resolved debug!("RegionConstraintCollector: add_constraint({:?})", constraint); - // never overwrite an existing (constraint, origin) - only insert one if it isn't - // present in the map yet. This prevents origins from outside the snapshot being - // replaced with "less informative" origins e.g., during calls to `can_eq` - let undo_log = &mut self.undo_log; - self.storage.data.constraints.entry(constraint).or_insert_with(|| { - undo_log.push(AddConstraint(constraint)); - origin - }); + let index = self.storage.data.constraints.len(); + self.storage.data.constraints.push((constraint, origin)); + self.undo_log.push(AddConstraint(index)); } fn add_verify(&mut self, verify: Verify<'tcx>) { diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs index b3cfd843ace..99fb4b33f24 100644 --- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs @@ -2,7 +2,7 @@ use super::ObjectSafetyViolation; use crate::infer::InferCtxt; use rustc_data_structures::fx::FxIndexSet; -use rustc_errors::{struct_span_err, DiagnosticBuilder, ErrorGuaranteed, MultiSpan}; +use rustc_errors::{struct_span_err, DiagnosticBuilder, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::ty::print::with_no_trimmed_paths; @@ -18,7 +18,7 @@ impl<'tcx> InferCtxt<'tcx> { impl_item_def_id: LocalDefId, trait_item_def_id: DefId, requirement: &dyn fmt::Display, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { let mut err = struct_span_err!( self.tcx.sess, error_span, @@ -44,7 +44,7 @@ pub fn report_object_safety_error<'tcx>( span: Span, trait_def_id: DefId, violations: &[ObjectSafetyViolation], -) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { +) -> DiagnosticBuilder<'tcx> { let trait_str = tcx.def_path_str(trait_def_id); let trait_span = tcx.hir().get_if_local(trait_def_id).and_then(|node| match node { hir::Node::Item(item) => Some(item.ident.span), diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index d58d60fc8be..6c000380e71 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -347,7 +347,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se ) { Ok(bundle) => bundle, Err(e) => { - early_dcx.early_error(format!("failed to load fluent bundle: {e}")); + early_dcx.early_fatal(format!("failed to load fluent bundle: {e}")); } }; diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index bffa743218f..f230c5b172c 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -164,13 +164,13 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>( fn load_backend_from_dylib(early_dcx: &EarlyDiagCtxt, path: &Path) -> MakeBackendFn { let lib = unsafe { Library::new(path) }.unwrap_or_else(|err| { let err = format!("couldn't load codegen backend {path:?}: {err}"); - early_dcx.early_error(err); + early_dcx.early_fatal(err); }); let backend_sym = unsafe { lib.get::<MakeBackendFn>(b"__rustc_codegen_backend") } .unwrap_or_else(|e| { let err = format!("couldn't load codegen backend: {e}"); - early_dcx.early_error(err); + early_dcx.early_fatal(err); }); // Intentionally leak the dynamic library. We can't ever unload it @@ -271,7 +271,7 @@ fn get_codegen_sysroot( "failed to find a `codegen-backends` folder \ in the sysroot candidates:\n* {candidates}" ); - early_dcx.early_error(err); + early_dcx.early_fatal(err); }); info!("probing {} for a codegen backend", sysroot.display()); @@ -282,7 +282,7 @@ fn get_codegen_sysroot( sysroot.display(), e ); - early_dcx.early_error(err); + early_dcx.early_fatal(err); }); let mut file: Option<PathBuf> = None; @@ -310,7 +310,7 @@ fn get_codegen_sysroot( prev.display(), path.display() ); - early_dcx.early_error(err); + early_dcx.early_fatal(err); } file = Some(path.clone()); } @@ -319,7 +319,7 @@ fn get_codegen_sysroot( Some(ref s) => load_backend_from_dylib(early_dcx, s), None => { let err = format!("unsupported builtin codegen backend `{backend_name}`"); - early_dcx.early_error(err); + early_dcx.early_fatal(err); } } } diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index a4ab5527e3f..0fc24e88b3b 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -39,7 +39,6 @@ #![feature(min_specialization)] #![feature(never_type)] #![feature(rustc_attrs)] -#![cfg_attr(bootstrap, feature(trait_upcasting))] #![recursion_limit = "256"] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 34cdee4ec5c..0386f2ec56c 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -852,8 +852,8 @@ trait UnusedDelimLint { (cond, UnusedDelimsCtx::WhileCond, true, Some(left), Some(right), true) } - ForLoop(_, ref cond, ref block, ..) => { - (cond, UnusedDelimsCtx::ForIterExpr, true, None, Some(block.span.lo()), true) + ForLoop { ref iter, ref body, .. } => { + (iter, UnusedDelimsCtx::ForIterExpr, true, None, Some(body.span.lo()), true) } Match(ref head, _) if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => { @@ -1085,7 +1085,7 @@ impl EarlyLintPass for UnusedParens { } match e.kind { - ExprKind::Let(ref pat, _, _, _) | ExprKind::ForLoop(ref pat, ..) => { + ExprKind::Let(ref pat, _, _, _) | ExprKind::ForLoop { ref pat, .. } => { self.check_unused_parens_pat(cx, pat, false, false, (true, true)); } // We ignore parens in cases like `if (((let Some(0) = Some(1))))` because we already diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs index 5de0203fc1d..027c97330b1 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs @@ -2,7 +2,7 @@ use std::cell::RefCell; -use crate::diagnostics::diagnostic_builder::{DiagnosticDeriveBuilder, DiagnosticDeriveKind}; +use crate::diagnostics::diagnostic_builder::DiagnosticDeriveKind; use crate::diagnostics::error::{span_err, DiagnosticDeriveError}; use crate::diagnostics::utils::SetOnce; use proc_macro2::TokenStream; @@ -13,32 +13,21 @@ use synstructure::Structure; /// The central struct for constructing the `into_diagnostic` method from an annotated struct. pub(crate) struct DiagnosticDerive<'a> { structure: Structure<'a>, - builder: DiagnosticDeriveBuilder, } impl<'a> DiagnosticDerive<'a> { - pub(crate) fn new(diag: syn::Ident, dcx: syn::Ident, structure: Structure<'a>) -> Self { - Self { - builder: DiagnosticDeriveBuilder { - diag, - kind: DiagnosticDeriveKind::Diagnostic { dcx }, - }, - structure, - } + pub(crate) fn new(structure: Structure<'a>) -> Self { + Self { structure } } pub(crate) fn into_tokens(self) -> TokenStream { - let DiagnosticDerive { mut structure, mut builder } = self; - + let DiagnosticDerive { mut structure } = self; + let kind = DiagnosticDeriveKind::Diagnostic; let slugs = RefCell::new(Vec::new()); - let implementation = builder.each_variant(&mut structure, |mut builder, variant| { + let implementation = kind.each_variant(&mut structure, |mut builder, variant| { let preamble = builder.preamble(variant); let body = builder.body(variant); - let diag = &builder.parent.diag; - let DiagnosticDeriveKind::Diagnostic { dcx } = &builder.parent.kind else { - unreachable!() - }; let init = match builder.slug.value_ref() { None => { span_err(builder.span, "diagnostic slug not specified") @@ -62,7 +51,11 @@ impl<'a> DiagnosticDerive<'a> { Some(slug) => { slugs.borrow_mut().push(slug.clone()); quote! { - let mut #diag = #dcx.struct_diagnostic(crate::fluent_generated::#slug); + let mut diag = rustc_errors::DiagnosticBuilder::new( + dcx, + level, + crate::fluent_generated::#slug + ); } } }; @@ -73,12 +66,10 @@ impl<'a> DiagnosticDerive<'a> { #formatting_init #preamble #body - #diag + diag } }); - let DiagnosticDeriveKind::Diagnostic { dcx } = &builder.kind else { unreachable!() }; - // A lifetime of `'a` causes conflicts, but `_sess` is fine. let mut imp = structure.gen_impl(quote! { gen impl<'_sess, G> @@ -90,9 +81,9 @@ impl<'a> DiagnosticDerive<'a> { #[track_caller] fn into_diagnostic( self, - #dcx: &'_sess rustc_errors::DiagCtxt + dcx: &'_sess rustc_errors::DiagCtxt, + level: rustc_errors::Level ) -> rustc_errors::DiagnosticBuilder<'_sess, G> { - use rustc_errors::IntoDiagnosticArg; #implementation } } @@ -107,36 +98,31 @@ impl<'a> DiagnosticDerive<'a> { /// The central struct for constructing the `decorate_lint` method from an annotated struct. pub(crate) struct LintDiagnosticDerive<'a> { structure: Structure<'a>, - builder: DiagnosticDeriveBuilder, } impl<'a> LintDiagnosticDerive<'a> { - pub(crate) fn new(diag: syn::Ident, structure: Structure<'a>) -> Self { - Self { - builder: DiagnosticDeriveBuilder { diag, kind: DiagnosticDeriveKind::LintDiagnostic }, - structure, - } + pub(crate) fn new(structure: Structure<'a>) -> Self { + Self { structure } } pub(crate) fn into_tokens(self) -> TokenStream { - let LintDiagnosticDerive { mut structure, mut builder } = self; - - let implementation = builder.each_variant(&mut structure, |mut builder, variant| { + let LintDiagnosticDerive { mut structure } = self; + let kind = DiagnosticDeriveKind::LintDiagnostic; + let implementation = kind.each_variant(&mut structure, |mut builder, variant| { let preamble = builder.preamble(variant); let body = builder.body(variant); - let diag = &builder.parent.diag; let formatting_init = &builder.formatting_init; quote! { #preamble #formatting_init #body - #diag + diag } }); let slugs = RefCell::new(Vec::new()); - let msg = builder.each_variant(&mut structure, |mut builder, variant| { + let msg = kind.each_variant(&mut structure, |mut builder, variant| { // Collect the slug by generating the preamble. let _ = builder.preamble(variant); @@ -169,15 +155,13 @@ impl<'a> LintDiagnosticDerive<'a> { } }); - let diag = &builder.diag; let mut imp = structure.gen_impl(quote! { gen impl<'__a> rustc_errors::DecorateLint<'__a, ()> for @Self { #[track_caller] fn decorate_lint<'__b>( self, - #diag: &'__b mut rustc_errors::DiagnosticBuilder<'__a, ()> + diag: &'__b mut rustc_errors::DiagnosticBuilder<'__a, ()> ) { - use rustc_errors::IntoDiagnosticArg; #implementation; } diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index 511654d9949..f3e98d68b60 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -17,28 +17,18 @@ use synstructure::{BindingInfo, Structure, VariantInfo}; use super::utils::SubdiagnosticVariant; /// What kind of diagnostic is being derived - a fatal/error/warning or a lint? -#[derive(Clone, PartialEq, Eq)] +#[derive(Clone, Copy, PartialEq, Eq)] pub(crate) enum DiagnosticDeriveKind { - Diagnostic { dcx: syn::Ident }, + Diagnostic, LintDiagnostic, } -/// Tracks persistent information required for the entire type when building up individual calls to -/// diagnostic methods for generated diagnostic derives - both `Diagnostic` for -/// fatal/errors/warnings and `LintDiagnostic` for lints. -pub(crate) struct DiagnosticDeriveBuilder { - /// The identifier to use for the generated `DiagnosticBuilder` instance. - pub diag: syn::Ident, - /// Kind of diagnostic that should be derived. - pub kind: DiagnosticDeriveKind, -} - /// Tracks persistent information required for a specific variant when building up individual calls /// to diagnostic methods for generated diagnostic derives - both `Diagnostic` for /// fatal/errors/warnings and `LintDiagnostic` for lints. -pub(crate) struct DiagnosticDeriveVariantBuilder<'parent> { - /// The parent builder for the entire type. - pub parent: &'parent DiagnosticDeriveBuilder, +pub(crate) struct DiagnosticDeriveVariantBuilder { + /// The kind for the entire type. + pub kind: DiagnosticDeriveKind, /// Initialization of format strings for code suggestions. pub formatting_init: TokenStream, @@ -59,19 +49,19 @@ pub(crate) struct DiagnosticDeriveVariantBuilder<'parent> { pub code: SpannedOption<()>, } -impl<'a> HasFieldMap for DiagnosticDeriveVariantBuilder<'a> { +impl HasFieldMap for DiagnosticDeriveVariantBuilder { fn get_field_binding(&self, field: &String) -> Option<&TokenStream> { self.field_map.get(field) } } -impl DiagnosticDeriveBuilder { +impl DiagnosticDeriveKind { /// Call `f` for the struct or for each variant of the enum, returning a `TokenStream` with the /// tokens from `f` wrapped in an `match` expression. Emits errors for use of derive on unions /// or attributes on the type itself when input is an enum. - pub(crate) fn each_variant<'s, F>(&mut self, structure: &mut Structure<'s>, f: F) -> TokenStream + pub(crate) fn each_variant<'s, F>(self, structure: &mut Structure<'s>, f: F) -> TokenStream where - F: for<'a, 'v> Fn(DiagnosticDeriveVariantBuilder<'a>, &VariantInfo<'v>) -> TokenStream, + F: for<'v> Fn(DiagnosticDeriveVariantBuilder, &VariantInfo<'v>) -> TokenStream, { let ast = structure.ast(); let span = ast.span().unwrap(); @@ -101,7 +91,7 @@ impl DiagnosticDeriveBuilder { _ => variant.ast().ident.span().unwrap(), }; let builder = DiagnosticDeriveVariantBuilder { - parent: self, + kind: self, span, field_map: build_field_mapping(variant), formatting_init: TokenStream::new(), @@ -119,7 +109,7 @@ impl DiagnosticDeriveBuilder { } } -impl<'a> DiagnosticDeriveVariantBuilder<'a> { +impl DiagnosticDeriveVariantBuilder { /// Generates calls to `code` and similar functions based on the attributes on the type or /// variant. pub(crate) fn preamble(&mut self, variant: &VariantInfo<'_>) -> TokenStream { @@ -184,8 +174,6 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { &mut self, attr: &Attribute, ) -> Result<TokenStream, DiagnosticDeriveError> { - let diag = &self.parent.diag; - // Always allow documentation comments. if is_doc_comment(attr) { return Ok(quote! {}); @@ -223,7 +211,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { let code = nested.parse::<syn::LitStr>()?; tokens.extend(quote! { - #diag.code(rustc_errors::DiagnosticId::Error(#code.to_string())); + diag.code(rustc_errors::DiagnosticId::Error(#code.to_string())); }); } else { span_err(path.span().unwrap(), "unknown argument") @@ -257,8 +245,6 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { } fn generate_field_code(&mut self, binding_info: &BindingInfo<'_>) -> TokenStream { - let diag = &self.parent.diag; - let field = binding_info.ast(); let mut field_binding = binding_info.binding.clone(); field_binding.set_span(field.ty.span()); @@ -267,7 +253,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { let ident = format_ident!("{}", ident); // strip `r#` prefix, if present quote! { - #diag.set_arg( + diag.set_arg( stringify!(#ident), #field_binding ); @@ -322,8 +308,6 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { info: FieldInfo<'_>, binding: TokenStream, ) -> Result<TokenStream, DiagnosticDeriveError> { - let diag = &self.parent.diag; - let ident = &attr.path().segments.last().unwrap().ident; let name = ident.to_string(); match (&attr.meta, name.as_str()) { @@ -331,12 +315,12 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { // `set_arg` call will not be generated. (Meta::Path(_), "skip_arg") => return Ok(quote! {}), (Meta::Path(_), "primary_span") => { - match self.parent.kind { - DiagnosticDeriveKind::Diagnostic { .. } => { + match self.kind { + DiagnosticDeriveKind::Diagnostic => { report_error_if_not_applied_to_span(attr, &info)?; return Ok(quote! { - #diag.set_span(#binding); + diag.set_span(#binding); }); } DiagnosticDeriveKind::LintDiagnostic => { @@ -348,13 +332,13 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { } (Meta::Path(_), "subdiagnostic") => { if FieldInnerTy::from_type(&info.binding.ast().ty).will_iterate() { - let DiagnosticDeriveKind::Diagnostic { dcx } = &self.parent.kind else { + let DiagnosticDeriveKind::Diagnostic = self.kind else { // No eager translation for lints. - return Ok(quote! { #diag.subdiagnostic(#binding); }); + return Ok(quote! { diag.subdiagnostic(#binding); }); }; - return Ok(quote! { #diag.eager_subdiagnostic(#dcx, #binding); }); + return Ok(quote! { diag.eager_subdiagnostic(dcx, #binding); }); } else { - return Ok(quote! { #diag.subdiagnostic(#binding); }); + return Ok(quote! { diag.subdiagnostic(#binding); }); } } (Meta::List(meta_list), "subdiagnostic") => { @@ -376,15 +360,15 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { return Ok(quote! {}); } - let dcx = match &self.parent.kind { - DiagnosticDeriveKind::Diagnostic { dcx } => dcx, + match &self.kind { + DiagnosticDeriveKind::Diagnostic => {} DiagnosticDeriveKind::LintDiagnostic => { throw_invalid_attr!(attr, |diag| { diag.help("eager subdiagnostics are not supported on lints") }) } }; - return Ok(quote! { #diag.eager_subdiagnostic(#dcx, #binding); }); + return Ok(quote! { diag.eager_subdiagnostic(dcx, #binding); }); } _ => (), } @@ -442,7 +426,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { self.formatting_init.extend(code_init); Ok(quote! { - #diag.span_suggestions_with_style( + diag.span_suggestions_with_style( #span_field, crate::fluent_generated::#slug, #code_field, @@ -463,10 +447,9 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { kind: &Ident, fluent_attr_identifier: Path, ) -> TokenStream { - let diag = &self.parent.diag; let fn_name = format_ident!("span_{}", kind); quote! { - #diag.#fn_name( + diag.#fn_name( #field_binding, crate::fluent_generated::#fluent_attr_identifier ); @@ -476,9 +459,8 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { /// Adds a subdiagnostic by generating a `diag.span_$kind` call with the current slug /// and `fluent_attr_identifier`. fn add_subdiagnostic(&self, kind: &Ident, fluent_attr_identifier: Path) -> TokenStream { - let diag = &self.parent.diag; quote! { - #diag.#kind(crate::fluent_generated::#fluent_attr_identifier); + diag.#kind(crate::fluent_generated::#fluent_attr_identifier); } } diff --git a/compiler/rustc_macros/src/diagnostics/mod.rs b/compiler/rustc_macros/src/diagnostics/mod.rs index a536eb3b04e..d3a4e7ba7d1 100644 --- a/compiler/rustc_macros/src/diagnostics/mod.rs +++ b/compiler/rustc_macros/src/diagnostics/mod.rs @@ -6,7 +6,6 @@ mod utils; use diagnostic::{DiagnosticDerive, LintDiagnosticDerive}; use proc_macro2::TokenStream; -use quote::format_ident; use subdiagnostic::SubdiagnosticDeriveBuilder; use synstructure::Structure; @@ -57,7 +56,7 @@ use synstructure::Structure; /// See rustc dev guide for more examples on using the `#[derive(Diagnostic)]`: /// <https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html> pub fn session_diagnostic_derive(s: Structure<'_>) -> TokenStream { - DiagnosticDerive::new(format_ident!("diag"), format_ident!("handler"), s).into_tokens() + DiagnosticDerive::new(s).into_tokens() } /// Implements `#[derive(LintDiagnostic)]`, which allows for lints to be specified as a struct, @@ -103,7 +102,7 @@ pub fn session_diagnostic_derive(s: Structure<'_>) -> TokenStream { /// See rustc dev guide for more examples on using the `#[derive(LintDiagnostic)]`: /// <https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html#reference> pub fn lint_diagnostic_derive(s: Structure<'_>) -> TokenStream { - LintDiagnosticDerive::new(format_ident!("diag"), s).into_tokens() + LintDiagnosticDerive::new(s).into_tokens() } /// Implements `#[derive(Subdiagnostic)]`, which allows for labels, notes, helps and diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 0f9e68cdc50..663abecb67c 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -94,7 +94,6 @@ impl SubdiagnosticDeriveBuilder { rustc_errors::SubdiagnosticMessage ) -> rustc_errors::SubdiagnosticMessage, { - use rustc_errors::{Applicability, IntoDiagnosticArg}; #implementation } } diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index 206c15edd78..e13068cb6f9 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -3,7 +3,9 @@ use std::{ path::{Path, PathBuf}, }; -use rustc_errors::{error_code, ErrorGuaranteed, IntoDiagnostic}; +use rustc_errors::{ + error_code, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level, +}; use rustc_macros::Diagnostic; use rustc_session::config; use rustc_span::{sym, Span, Symbol}; @@ -495,12 +497,9 @@ pub(crate) struct MultipleCandidates { pub candidates: Vec<PathBuf>, } -impl IntoDiagnostic<'_> for MultipleCandidates { - fn into_diagnostic( - self, - dcx: &'_ rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::metadata_multiple_candidates); +impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for MultipleCandidates { + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = DiagnosticBuilder::new(dcx, level, fluent::metadata_multiple_candidates); diag.set_arg("crate_name", self.crate_name); diag.set_arg("flavor", self.flavor); diag.code(error_code!(E0464)); @@ -593,13 +592,10 @@ pub struct InvalidMetadataFiles { pub crate_rejections: Vec<String>, } -impl IntoDiagnostic<'_> for InvalidMetadataFiles { +impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for InvalidMetadataFiles { #[track_caller] - fn into_diagnostic( - self, - dcx: &'_ rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::metadata_invalid_meta_files); + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = DiagnosticBuilder::new(dcx, level, fluent::metadata_invalid_meta_files); diag.set_arg("crate_name", self.crate_name); diag.set_arg("add_info", self.add_info); diag.code(error_code!(E0786)); @@ -623,13 +619,10 @@ pub struct CannotFindCrate { pub is_ui_testing: bool, } -impl IntoDiagnostic<'_> for CannotFindCrate { +impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for CannotFindCrate { #[track_caller] - fn into_diagnostic( - self, - dcx: &'_ rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::metadata_cannot_find_crate); + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = DiagnosticBuilder::new(dcx, level, fluent::metadata_cannot_find_crate); diag.set_arg("crate_name", self.crate_name); diag.set_arg("current_crate", self.current_crate); diag.set_arg("add_info", self.add_info); diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 281a0eafee1..aa1ee96fae2 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -6,6 +6,7 @@ use crate::rmeta::*; use rustc_ast as ast; use rustc_data_structures::captures::Captures; +use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::owned_slice::OwnedSlice; use rustc_data_structures::sync::{AppendOnlyVec, AtomicBool, Lock, Lrc, OnceLock}; use rustc_data_structures::unhash::UnhashMap; @@ -87,8 +88,6 @@ pub(crate) struct CrateMetadata { alloc_decoding_state: AllocDecodingState, /// Caches decoded `DefKey`s. def_key_cache: Lock<FxHashMap<DefIndex, DefKey>>, - /// Caches decoded `DefPathHash`es. - def_path_hash_cache: Lock<FxHashMap<DefIndex, DefPathHash>>, // --- Other significant crate properties --- /// ID of this crate, from the current compilation session's point of view. @@ -1266,7 +1265,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } fn cross_crate_inlinable(self, id: DefIndex) -> bool { - self.root.tables.cross_crate_inlinable.get(self, id).unwrap_or(false) + self.root.tables.cross_crate_inlinable.get(self, id) } fn get_fn_has_self_parameter(self, id: DefIndex, sess: &'a Session) -> bool { @@ -1484,20 +1483,16 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { DefPath::make(self.cnum, id, |parent| self.def_key(parent)) } - fn def_path_hash_unlocked( - self, - index: DefIndex, - def_path_hashes: &mut FxHashMap<DefIndex, DefPathHash>, - ) -> DefPathHash { - *def_path_hashes - .entry(index) - .or_insert_with(|| self.root.tables.def_path_hashes.get(self, index)) - } - #[inline] fn def_path_hash(self, index: DefIndex) -> DefPathHash { - let mut def_path_hashes = self.def_path_hash_cache.lock(); - self.def_path_hash_unlocked(index, &mut def_path_hashes) + // This is a hack to workaround the fact that we can't easily encode/decode a Hash64 + // into the FixedSizeEncoding, as Hash64 lacks a Default impl. A future refactor to + // relax the Default restriction will likely fix this. + let fingerprint = Fingerprint::new( + self.root.stable_crate_id.as_u64(), + self.root.tables.def_path_hashes.get(self, index), + ); + DefPathHash::new(self.root.stable_crate_id, fingerprint.split().1) } #[inline] @@ -1824,7 +1819,6 @@ impl CrateMetadata { extern_crate: Lock::new(None), hygiene_context: Default::default(), def_key_cache: Default::default(), - def_path_hash_cache: Default::default(), }; // Need `CrateMetadataRef` to decode `DefId`s in simplified types. diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index f6cd013d2ef..bb8f4af8e97 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -241,7 +241,7 @@ provide! { tcx, def_id, other, cdata, rendered_const => { table } asyncness => { table_direct } fn_arg_names => { table } - coroutine_kind => { table } + coroutine_kind => { table_direct } trait_def => { table } deduced_param_attrs => { table } is_type_alias_impl_trait => { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index ad3fea65e82..16906fa6989 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -467,13 +467,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let def_key = self.lazy(table.def_key(def_index)); let def_path_hash = table.def_path_hash(def_index); self.tables.def_keys.set_some(def_index, def_key); - self.tables.def_path_hashes.set(def_index, def_path_hash); + self.tables.def_path_hashes.set(def_index, def_path_hash.local_hash().as_u64()); } } else { for (def_index, def_key, def_path_hash) in table.enumerated_keys_and_path_hashes() { let def_key = self.lazy(def_key); self.tables.def_keys.set_some(def_index, def_key); - self.tables.def_path_hashes.set(def_index, *def_path_hash); + self.tables.def_path_hashes.set(def_index, def_path_hash.local_hash().as_u64()); } } } @@ -1428,9 +1428,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } if def_kind == DefKind::Closure - && let Some(data) = self.tcx.coroutine_kind(def_id) + && let Some(coroutine_kind) = self.tcx.coroutine_kind(def_id) { - record!(self.tables.coroutine_kind[def_id] <- data); + self.tables.coroutine_kind.set(def_id.index, Some(coroutine_kind)); } if let DefKind::Enum | DefKind::Struct | DefKind::Union = def_kind { self.encode_info_for_adt(local_id); @@ -1607,7 +1607,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.optimized_mir[def_id.to_def_id()] <- tcx.optimized_mir(def_id)); self.tables .cross_crate_inlinable - .set(def_id.to_def_id().index, Some(self.tcx.cross_crate_inlinable(def_id))); + .set(def_id.to_def_id().index, self.tcx.cross_crate_inlinable(def_id)); record!(self.tables.closure_saved_names_of_captured_variables[def_id.to_def_id()] <- tcx.closure_saved_names_of_captured_variables(def_id)); diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index a8582284898..d496e7494e7 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -386,7 +386,12 @@ define_tables! { is_type_alias_impl_trait: Table<DefIndex, bool>, type_alias_is_lazy: Table<DefIndex, bool>, attr_flags: Table<DefIndex, AttrFlags>, - def_path_hashes: Table<DefIndex, DefPathHash>, + // The u64 is the crate-local part of the DefPathHash. All hashes in this crate have the same + // StableCrateId, so we omit encoding those into the table. + // + // Note also that this table is fully populated (no gaps) as every DefIndex should have a + // corresponding DefPathHash. + def_path_hashes: Table<DefIndex, u64>, explicit_item_bounds: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>, inferred_outlives_of: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>, inherent_impls: Table<DefIndex, LazyArray<DefIndex>>, @@ -398,6 +403,7 @@ define_tables! { // That's why the encoded list needs to contain `ModChild` structures describing all the names // individually instead of `DefId`s. module_children_reexports: Table<DefIndex, LazyArray<ModChild>>, + cross_crate_inlinable: Table<DefIndex, bool>, - optional: attributes: Table<DefIndex, LazyArray<ast::Attribute>>, @@ -428,7 +434,6 @@ define_tables! { object_lifetime_default: Table<DefIndex, LazyValue<ObjectLifetimeDefault>>, optimized_mir: Table<DefIndex, LazyValue<mir::Body<'static>>>, mir_for_ctfe: Table<DefIndex, LazyValue<mir::Body<'static>>>, - cross_crate_inlinable: Table<DefIndex, bool>, closure_saved_names_of_captured_variables: Table<DefIndex, LazyValue<IndexVec<FieldIdx, Symbol>>>, mir_coroutine_witnesses: Table<DefIndex, LazyValue<mir::CoroutineLayout<'static>>>, promoted_mir: Table<DefIndex, LazyValue<IndexVec<mir::Promoted, mir::Body<'static>>>>, @@ -443,7 +448,7 @@ define_tables! { rendered_const: Table<DefIndex, LazyValue<String>>, asyncness: Table<DefIndex, ty::Asyncness>, fn_arg_names: Table<DefIndex, LazyArray<Ident>>, - coroutine_kind: Table<DefIndex, LazyValue<hir::CoroutineKind>>, + coroutine_kind: Table<DefIndex, hir::CoroutineKind>, trait_def: Table<DefIndex, LazyValue<ty::TraitDef>>, trait_item_def_id: Table<DefIndex, RawDefId>, expn_that_defined: Table<DefIndex, LazyValue<ExpnId>>, diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 3fc6d9db331..d53ee4836bb 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -1,6 +1,5 @@ use crate::rmeta::*; -use rustc_data_structures::fingerprint::Fingerprint; use rustc_hir::def::CtorOf; use rustc_index::Idx; @@ -44,12 +43,6 @@ impl<T> IsDefault for LazyArray<T> { } } -impl IsDefault for DefPathHash { - fn is_default(&self) -> bool { - self.0 == Fingerprint::ZERO - } -} - impl IsDefault for UnusedGenericParams { fn is_default(&self) -> bool { // UnusedGenericParams encodes the *un*usedness as a bitset. @@ -205,6 +198,21 @@ fixed_size_enum! { } fixed_size_enum! { + hir::CoroutineKind { + ( Coroutine ) + ( Desugared(hir::CoroutineDesugaring::Gen, hir::CoroutineSource::Block) ) + ( Desugared(hir::CoroutineDesugaring::Gen, hir::CoroutineSource::Fn) ) + ( Desugared(hir::CoroutineDesugaring::Gen, hir::CoroutineSource::Closure) ) + ( Desugared(hir::CoroutineDesugaring::Async, hir::CoroutineSource::Block) ) + ( Desugared(hir::CoroutineDesugaring::Async, hir::CoroutineSource::Fn) ) + ( Desugared(hir::CoroutineDesugaring::Async, hir::CoroutineSource::Closure) ) + ( Desugared(hir::CoroutineDesugaring::AsyncGen, hir::CoroutineSource::Block) ) + ( Desugared(hir::CoroutineDesugaring::AsyncGen, hir::CoroutineSource::Fn) ) + ( Desugared(hir::CoroutineDesugaring::AsyncGen, hir::CoroutineSource::Closure) ) + } +} + +fixed_size_enum! { ty::AssocItemContainer { ( TraitContainer ) ( ImplContainer ) @@ -219,22 +227,6 @@ fixed_size_enum! { } } -// We directly encode `DefPathHash` because a `LazyValue` would incur a 25% cost. -impl FixedSizeEncoding for DefPathHash { - type ByteArray = [u8; 16]; - - #[inline] - fn from_bytes(b: &[u8; 16]) -> Self { - DefPathHash(Fingerprint::from_le_bytes(*b)) - } - - #[inline] - fn write_to_bytes(self, b: &mut [u8; 16]) { - debug_assert!(!self.is_default()); - *b = self.0.to_le_bytes(); - } -} - // We directly encode RawDefId because using a `LazyValue` would incur a 50% overhead in the worst case. impl FixedSizeEncoding for Option<RawDefId> { type ByteArray = [u8; 8]; diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index e048268fad1..3475e582a8f 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -49,7 +49,6 @@ #![feature(associated_type_bounds)] #![feature(rustc_attrs)] #![feature(control_flow_enum)] -#![cfg_attr(bootstrap, feature(trait_upcasting))] #![feature(trusted_step)] #![feature(try_blocks)] #![feature(try_reserve_kind)] diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index c49c4ee819c..d34d9160d55 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -293,19 +293,16 @@ pub fn struct_lint_level( }, ); - let mut err = match (level, span) { - (Level::Allow, span) => { + // Convert lint level to error level. + let err_level = match level { + Level::Allow => { if has_future_breakage { - if let Some(span) = span { - sess.struct_span_allow(span, "") - } else { - sess.struct_allow("") - } + rustc_errors::Level::Allow } else { return; } } - (Level::Expect(expect_id), _) => { + Level::Expect(expect_id) => { // This case is special as we actually allow the lint itself in this context, but // we can't return early like in the case for `Level::Allow` because we still // need the lint diagnostic to be emitted to `rustc_error::DiagCtxtInner`. @@ -313,23 +310,16 @@ pub fn struct_lint_level( // We can also not mark the lint expectation as fulfilled here right away, as it // can still be cancelled in the decorate function. All of this means that we simply // create a `DiagnosticBuilder` and continue as we would for warnings. - sess.struct_expect("", expect_id) + rustc_errors::Level::Expect(expect_id) } - (Level::ForceWarn(Some(expect_id)), Some(span)) => { - sess.struct_span_warn_with_expectation(span, "", expect_id) - } - (Level::ForceWarn(Some(expect_id)), None) => { - sess.struct_warn_with_expectation("", expect_id) - } - (Level::Warn | Level::ForceWarn(None), Some(span)) => sess.struct_span_warn(span, ""), - (Level::Warn | Level::ForceWarn(None), None) => sess.struct_warn(""), - (Level::Deny | Level::Forbid, Some(span)) => { - let mut builder = sess.dcx().struct_err_lint(""); - builder.set_span(span); - builder - } - (Level::Deny | Level::Forbid, None) => sess.dcx().struct_err_lint(""), + Level::ForceWarn(Some(expect_id)) => rustc_errors::Level::Warning(Some(expect_id)), + Level::Warn | Level::ForceWarn(None) => rustc_errors::Level::Warning(None), + Level::Deny | Level::Forbid => rustc_errors::Level::Error { lint: true }, }; + let mut err = DiagnosticBuilder::new(sess.dcx(), err_level, ""); + if let Some(span) = span { + err.set_span(span); + } err.set_is_lint(); diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 41386793987..2cd2fcca9d5 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -90,10 +90,7 @@ pub type EvalToConstValueResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>; /// This is needed in `thir::pattern::lower_inline_const`. pub type EvalToValTreeResult<'tcx> = Result<Option<ValTree<'tcx>>, ErrorHandled>; -pub fn struct_error<'tcx>( - tcx: TyCtxtAt<'tcx>, - msg: &str, -) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { +pub fn struct_error<'tcx>(tcx: TyCtxtAt<'tcx>, msg: &str) -> DiagnosticBuilder<'tcx> { struct_span_err!(tcx.sess, tcx.span, E0080, "{}", msg) } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 1e5a7401c6f..5c425fef27e 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -17,7 +17,7 @@ use rustc_data_structures::captures::Captures; use rustc_errors::{DiagnosticArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg}; use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::def_id::{DefId, CRATE_DEF_ID}; -use rustc_hir::{self, CoroutineKind, ImplicitSelfKind}; +use rustc_hir::{self, CoroutineDesugaring, CoroutineKind, ImplicitSelfKind}; use rustc_hir::{self as hir, HirId}; use rustc_session::Session; use rustc_target::abi::{FieldIdx, VariantIdx}; diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 98e3a1f604e..e0c9def0379 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -148,19 +148,23 @@ impl<O> AssertKind<O> { DivisionByZero(_) => "attempt to divide by zero", RemainderByZero(_) => "attempt to calculate the remainder with a divisor of zero", ResumedAfterReturn(CoroutineKind::Coroutine) => "coroutine resumed after completion", - ResumedAfterReturn(CoroutineKind::Async(_)) => "`async fn` resumed after completion", - ResumedAfterReturn(CoroutineKind::AsyncGen(_)) => { + ResumedAfterReturn(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) => { + "`async fn` resumed after completion" + } + ResumedAfterReturn(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _)) => { "`async gen fn` resumed after completion" } - ResumedAfterReturn(CoroutineKind::Gen(_)) => { + ResumedAfterReturn(CoroutineKind::Desugared(CoroutineDesugaring::Gen, _)) => { "`gen fn` should just keep returning `None` after completion" } ResumedAfterPanic(CoroutineKind::Coroutine) => "coroutine resumed after panicking", - ResumedAfterPanic(CoroutineKind::Async(_)) => "`async fn` resumed after panicking", - ResumedAfterPanic(CoroutineKind::AsyncGen(_)) => { + ResumedAfterPanic(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) => { + "`async fn` resumed after panicking" + } + ResumedAfterPanic(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _)) => { "`async gen fn` resumed after panicking" } - ResumedAfterPanic(CoroutineKind::Gen(_)) => { + ResumedAfterPanic(CoroutineKind::Desugared(CoroutineDesugaring::Gen, _)) => { "`gen fn` should just keep returning `None` after panicking" } @@ -249,17 +253,27 @@ impl<O> AssertKind<O> { OverflowNeg(_) => middle_assert_overflow_neg, DivisionByZero(_) => middle_assert_divide_by_zero, RemainderByZero(_) => middle_assert_remainder_by_zero, - ResumedAfterReturn(CoroutineKind::Async(_)) => middle_assert_async_resume_after_return, - ResumedAfterReturn(CoroutineKind::AsyncGen(_)) => todo!(), - ResumedAfterReturn(CoroutineKind::Gen(_)) => { + ResumedAfterReturn(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) => { + middle_assert_async_resume_after_return + } + ResumedAfterReturn(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _)) => { + todo!() + } + ResumedAfterReturn(CoroutineKind::Desugared(CoroutineDesugaring::Gen, _)) => { bug!("gen blocks can be resumed after they return and will keep returning `None`") } ResumedAfterReturn(CoroutineKind::Coroutine) => { middle_assert_coroutine_resume_after_return } - ResumedAfterPanic(CoroutineKind::Async(_)) => middle_assert_async_resume_after_panic, - ResumedAfterPanic(CoroutineKind::AsyncGen(_)) => todo!(), - ResumedAfterPanic(CoroutineKind::Gen(_)) => middle_assert_gen_resume_after_panic, + ResumedAfterPanic(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) => { + middle_assert_async_resume_after_panic + } + ResumedAfterPanic(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _)) => { + todo!() + } + ResumedAfterPanic(CoroutineKind::Desugared(CoroutineDesugaring::Gen, _)) => { + middle_assert_gen_resume_after_panic + } ResumedAfterPanic(CoroutineKind::Coroutine) => { middle_assert_coroutine_resume_after_panic } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index b5ca700c2cd..655dde1d9c9 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -849,7 +849,10 @@ impl<'tcx> TyCtxt<'tcx> { /// Returns `true` if the node pointed to by `def_id` is a coroutine for an async construct. pub fn coroutine_is_async(self, def_id: DefId) -> bool { - matches!(self.coroutine_kind(def_id), Some(hir::CoroutineKind::Async(_))) + matches!( + self.coroutine_kind(def_id), + Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) + ) } /// Returns `true` if the node pointed to by `def_id` is a general coroutine that implements `Coroutine`. @@ -860,12 +863,18 @@ impl<'tcx> TyCtxt<'tcx> { /// Returns `true` if the node pointed to by `def_id` is a coroutine for a `gen` construct. pub fn coroutine_is_gen(self, def_id: DefId) -> bool { - matches!(self.coroutine_kind(def_id), Some(hir::CoroutineKind::Gen(_))) + matches!( + self.coroutine_kind(def_id), + Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)) + ) } /// Returns `true` if the node pointed to by `def_id` is a coroutine for a `async gen` construct. pub fn coroutine_is_async_gen(self, def_id: DefId) -> bool { - matches!(self.coroutine_kind(def_id), Some(hir::CoroutineKind::AsyncGen(_))) + matches!( + self.coroutine_kind(def_id), + Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)) + ) } pub fn stability(self) -> &'tcx stability::Index { diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 0094825fc70..c1e2479defd 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -628,11 +628,3 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for MakeSuggestableFolder<'tcx> { c.try_super_fold_with(self) } } - -#[derive(Diagnostic)] -#[diag(middle_const_not_used_in_type_alias)] -pub(super) struct ConstNotUsedTraitAlias { - pub ct: String, - #[primary_span] - pub span: Span, -} diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs index ae17942785f..c571ac50724 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs @@ -1,7 +1,7 @@ use smallvec::SmallVec; use crate::ty::context::TyCtxt; -use crate::ty::{self, DefId, ParamEnv, Ty}; +use crate::ty::{self, DefId, OpaqueTypeKey, ParamEnv, Ty}; /// Represents whether some type is inhabited in a given context. /// Examples of uninhabited types are `!`, `enum Void {}`, or a struct @@ -23,6 +23,8 @@ pub enum InhabitedPredicate<'tcx> { /// Inhabited if some generic type is inhabited. /// These are replaced by calling [`Self::instantiate`]. GenericType(Ty<'tcx>), + /// Inhabited if either we don't know the hidden type or we know it and it is inhabited. + OpaqueType(OpaqueTypeKey<'tcx>), /// A AND B And(&'tcx [InhabitedPredicate<'tcx>; 2]), /// A OR B @@ -30,35 +32,53 @@ pub enum InhabitedPredicate<'tcx> { } impl<'tcx> InhabitedPredicate<'tcx> { - /// Returns true if the corresponding type is inhabited in the given - /// `ParamEnv` and module + /// Returns true if the corresponding type is inhabited in the given `ParamEnv` and module. pub fn apply(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, module_def_id: DefId) -> bool { - let Ok(result) = self.apply_inner::<!>(tcx, param_env, &mut Default::default(), &|id| { - Ok(tcx.is_descendant_of(module_def_id, id)) - }); + self.apply_revealing_opaque(tcx, param_env, module_def_id, &|_| None) + } + + /// Returns true if the corresponding type is inhabited in the given `ParamEnv` and module, + /// revealing opaques when possible. + pub fn apply_revealing_opaque( + self, + tcx: TyCtxt<'tcx>, + param_env: ParamEnv<'tcx>, + module_def_id: DefId, + reveal_opaque: &impl Fn(OpaqueTypeKey<'tcx>) -> Option<Ty<'tcx>>, + ) -> bool { + let Ok(result) = self.apply_inner::<!>( + tcx, + param_env, + &mut Default::default(), + &|id| Ok(tcx.is_descendant_of(module_def_id, id)), + reveal_opaque, + ); result } /// Same as `apply`, but returns `None` if self contains a module predicate pub fn apply_any_module(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> { - self.apply_inner(tcx, param_env, &mut Default::default(), &|_| Err(())).ok() + self.apply_inner(tcx, param_env, &mut Default::default(), &|_| Err(()), &|_| None).ok() } /// Same as `apply`, but `NotInModule(_)` predicates yield `false`. That is, /// privately uninhabited types are considered always uninhabited. pub fn apply_ignore_module(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> bool { let Ok(result) = - self.apply_inner::<!>(tcx, param_env, &mut Default::default(), &|_| Ok(true)); + self.apply_inner::<!>(tcx, param_env, &mut Default::default(), &|_| Ok(true), &|_| { + None + }); result } - #[instrument(level = "debug", skip(tcx, param_env, in_module), ret)] + #[instrument(level = "debug", skip(tcx, param_env, in_module, reveal_opaque), ret)] fn apply_inner<E: std::fmt::Debug>( self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, eval_stack: &mut SmallVec<[Ty<'tcx>; 1]>, // for cycle detection in_module: &impl Fn(DefId) -> Result<bool, E>, + reveal_opaque: &impl Fn(OpaqueTypeKey<'tcx>) -> Option<Ty<'tcx>>, ) -> Result<bool, E> { match self { Self::False => Ok(false), @@ -84,18 +104,41 @@ impl<'tcx> InhabitedPredicate<'tcx> { return Ok(true); // Recover; this will error later. } eval_stack.push(t); - let ret = pred.apply_inner(tcx, param_env, eval_stack, in_module); + let ret = + pred.apply_inner(tcx, param_env, eval_stack, in_module, reveal_opaque); eval_stack.pop(); ret } } } - Self::And([a, b]) => { - try_and(a, b, |x| x.apply_inner(tcx, param_env, eval_stack, in_module)) - } - Self::Or([a, b]) => { - try_or(a, b, |x| x.apply_inner(tcx, param_env, eval_stack, in_module)) - } + Self::OpaqueType(key) => match reveal_opaque(key) { + // Unknown opaque is assumed inhabited. + None => Ok(true), + // Known opaque type is inspected recursively. + Some(t) => { + // A cyclic opaque type can happen in corner cases that would only error later. + // See e.g. `tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs`. + if eval_stack.contains(&t) { + return Ok(true); // Recover; this will error later. + } + eval_stack.push(t); + let ret = t.inhabited_predicate(tcx).apply_inner( + tcx, + param_env, + eval_stack, + in_module, + reveal_opaque, + ); + eval_stack.pop(); + ret + } + }, + Self::And([a, b]) => try_and(a, b, |x| { + x.apply_inner(tcx, param_env, eval_stack, in_module, reveal_opaque) + }), + Self::Or([a, b]) => try_or(a, b, |x| { + x.apply_inner(tcx, param_env, eval_stack, in_module, reveal_opaque) + }), } } diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index d67fb9fd0b7..bbcc244cb26 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs @@ -45,7 +45,7 @@ use crate::query::Providers; use crate::ty::context::TyCtxt; -use crate::ty::{self, DefId, Ty, VariantDef, Visibility}; +use crate::ty::{self, DefId, Ty, TypeVisitableExt, VariantDef, Visibility}; use rustc_type_ir::TyKind::*; @@ -105,6 +105,7 @@ impl<'tcx> VariantDef { impl<'tcx> Ty<'tcx> { #[instrument(level = "debug", skip(tcx), ret)] pub fn inhabited_predicate(self, tcx: TyCtxt<'tcx>) -> InhabitedPredicate<'tcx> { + debug_assert!(!self.has_infer()); match self.kind() { // For now, unions are always considered inhabited Adt(adt, _) if adt.is_union() => InhabitedPredicate::True, @@ -113,7 +114,18 @@ impl<'tcx> Ty<'tcx> { InhabitedPredicate::True } Never => InhabitedPredicate::False, - Param(_) | Alias(ty::Projection, _) => InhabitedPredicate::GenericType(self), + Param(_) | Alias(ty::Projection | ty::Weak, _) => InhabitedPredicate::GenericType(self), + Alias(ty::Opaque, alias_ty) => { + match alias_ty.def_id.as_local() { + // Foreign opaque is considered inhabited. + None => InhabitedPredicate::True, + // Local opaque type may possibly be revealed. + Some(local_def_id) => { + let key = ty::OpaqueTypeKey { def_id: local_def_id, args: alias_ty.args }; + InhabitedPredicate::OpaqueType(key) + } + } + } // FIXME(inherent_associated_types): Most likely we can just map to `GenericType` like above. // However it's unclear if the args passed to `InhabitedPredicate::instantiate` are of the correct // format, i.e. don't contain parent args. If you hit this case, please verify this beforehand. diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 225dd217807..5ae758edfa3 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -5,7 +5,8 @@ use crate::ty::normalize_erasing_regions::NormalizationError; use crate::ty::{self, ConstKind, Ty, TyCtxt, TypeVisitableExt}; use rustc_error_messages::DiagnosticMessage; use rustc_errors::{ - DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, IntoDiagnostic, IntoDiagnosticArg, + DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, + IntoDiagnosticArg, Level, }; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -1272,14 +1273,14 @@ pub enum FnAbiError<'tcx> { AdjustForForeignAbi(call::AdjustForForeignAbiError), } -impl<'a, 'b> IntoDiagnostic<'a, !> for FnAbiError<'b> { - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, !> { +impl<'a, 'b, G: EmissionGuarantee> IntoDiagnostic<'a, G> for FnAbiError<'b> { + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { match self { - Self::Layout(e) => e.into_diagnostic().into_diagnostic(dcx), + Self::Layout(e) => e.into_diagnostic().into_diagnostic(dcx, level), Self::AdjustForForeignAbi(call::AdjustForForeignAbiError::Unsupported { arch, abi, - }) => UnsupportedFnAbi { arch, abi: abi.name() }.into_diagnostic(dcx), + }) => UnsupportedFnAbi { arch, abi: abi.name() }.into_diagnostic(dcx, level), } } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 35c135830c3..36b8d387d69 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1481,7 +1481,7 @@ impl<'tcx> OpaqueHiddenType<'tcx> { other: &Self, opaque_def_id: LocalDefId, tcx: TyCtxt<'tcx>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { if let Some(diag) = tcx .sess .dcx() diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 8b2b76764e6..ab2488f2e91 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -728,10 +728,16 @@ impl<'tcx> TyCtxt<'tcx> { DefKind::AssocFn if self.associated_item(def_id).fn_has_self_parameter => "method", DefKind::Closure if let Some(coroutine_kind) = self.coroutine_kind(def_id) => { match coroutine_kind { - rustc_hir::CoroutineKind::Async(..) => "async closure", - rustc_hir::CoroutineKind::AsyncGen(..) => "async gen closure", - rustc_hir::CoroutineKind::Coroutine => "coroutine", - rustc_hir::CoroutineKind::Gen(..) => "gen closure", + hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _) => { + "async closure" + } + hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _) => { + "async gen closure" + } + hir::CoroutineKind::Coroutine => "coroutine", + hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _) => { + "gen closure" + } } } _ => def_kind.descr(def_id), @@ -749,10 +755,10 @@ impl<'tcx> TyCtxt<'tcx> { DefKind::AssocFn if self.associated_item(def_id).fn_has_self_parameter => "a", DefKind::Closure if let Some(coroutine_kind) = self.coroutine_kind(def_id) => { match coroutine_kind { - rustc_hir::CoroutineKind::Async(..) => "an", - rustc_hir::CoroutineKind::AsyncGen(..) => "an", - rustc_hir::CoroutineKind::Coroutine => "a", - rustc_hir::CoroutineKind::Gen(..) => "a", + hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, ..) => "an", + hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, ..) => "an", + hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, ..) => "a", + hir::CoroutineKind::Coroutine => "a", } } _ => def_kind.article(), diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index c66687330dc..8677cba6a7c 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -2,7 +2,7 @@ use crate::fluent_generated as fluent; use rustc_errors::DiagnosticArgValue; use rustc_errors::{ error_code, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, - ErrorGuaranteed, IntoDiagnostic, MultiSpan, SubdiagnosticMessage, + IntoDiagnostic, Level, MultiSpan, SubdiagnosticMessage, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{self, Ty}; @@ -461,13 +461,14 @@ pub(crate) struct NonExhaustivePatternsTypeNotEmpty<'p, 'tcx, 'm> { } impl<'a> IntoDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> { - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_span_err_with_code( - self.span, + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'_> { + let mut diag = DiagnosticBuilder::new( + dcx, + level, fluent::mir_build_non_exhaustive_patterns_type_not_empty, - error_code!(E0004), ); - + diag.set_span(self.span); + diag.code(error_code!(E0004)); let peeled_ty = self.ty.peel_refs(); diag.set_arg("ty", self.ty); diag.set_arg("peeled_ty", peeled_ty); diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index c435f4023af..fcccdf105f6 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -28,6 +28,7 @@ use rustc_span::hygiene::DesugaringKind; use rustc_span::Span; pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> { + let typeck_results = tcx.typeck(def_id); let (thir, expr) = tcx.thir_body(def_id)?; let thir = thir.borrow(); let pattern_arena = TypedArena::default(); @@ -35,6 +36,7 @@ pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), Err let mut visitor = MatchVisitor { tcx, thir: &*thir, + typeck_results, param_env: tcx.param_env(def_id), lint_level: tcx.local_def_id_to_hir_id(def_id), let_source: LetSource::None, @@ -52,11 +54,7 @@ pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), Err visitor.error } -fn create_e0004( - sess: &Session, - sp: Span, - error_message: String, -) -> DiagnosticBuilder<'_, ErrorGuaranteed> { +fn create_e0004(sess: &Session, sp: Span, error_message: String) -> DiagnosticBuilder<'_> { struct_span_err!(sess, sp, E0004, "{}", &error_message) } @@ -80,6 +78,7 @@ enum LetSource { struct MatchVisitor<'thir, 'p, 'tcx> { tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, + typeck_results: &'tcx ty::TypeckResults<'tcx>, thir: &'thir Thir<'tcx>, lint_level: HirId, let_source: LetSource, @@ -382,6 +381,7 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> { scrutinee.map(|scrut| self.is_known_valid_scrutinee(scrut)).unwrap_or(true); MatchCheckCtxt { tcx: self.tcx, + typeck_results: self.typeck_results, param_env: self.param_env, module: self.tcx.parent_module(self.lint_level).to_def_id(), pattern_arena: self.pattern_arena, @@ -856,7 +856,7 @@ fn report_arm_reachability<'p, 'tcx>( for (arm, is_useful) in report.arm_usefulness.iter() { match is_useful { Usefulness::Redundant => { - report_unreachable_pattern(*arm.pat.data(), arm.arm_data, catchall) + report_unreachable_pattern(*arm.pat.data().unwrap(), arm.arm_data, catchall) } Usefulness::Useful(redundant_subpats) if redundant_subpats.is_empty() => {} // The arm is reachable, but contains redundant subpatterns (from or-patterns). @@ -865,12 +865,12 @@ fn report_arm_reachability<'p, 'tcx>( // Emit lints in the order in which they occur in the file. redundant_subpats.sort_unstable_by_key(|pat| pat.data()); for pat in redundant_subpats { - report_unreachable_pattern(*pat.data(), arm.arm_data, None); + report_unreachable_pattern(*pat.data().unwrap(), arm.arm_data, None); } } } if !arm.has_guard && catchall.is_none() && pat_is_catchall(arm.pat) { - catchall = Some(*arm.pat.data()); + catchall = Some(*arm.pat.data().unwrap()); } } } diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index 646c70eb88f..595c2ff5bf7 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -81,17 +81,17 @@ impl<'tcx, 'a> crate::GenKillAnalysis<'tcx> for MaybeStorageLive<'a> { } #[derive(Clone)] -pub struct MaybeStorageDead { - always_live_locals: BitSet<Local>, +pub struct MaybeStorageDead<'a> { + always_live_locals: Cow<'a, BitSet<Local>>, } -impl MaybeStorageDead { - pub fn new(always_live_locals: BitSet<Local>) -> Self { +impl<'a> MaybeStorageDead<'a> { + pub fn new(always_live_locals: Cow<'a, BitSet<Local>>) -> Self { MaybeStorageDead { always_live_locals } } } -impl<'tcx> crate::AnalysisDomain<'tcx> for MaybeStorageDead { +impl<'tcx, 'a> crate::AnalysisDomain<'tcx> for MaybeStorageDead<'a> { type Domain = BitSet<Local>; const NAME: &'static str = "maybe_storage_dead"; @@ -112,7 +112,7 @@ impl<'tcx> crate::AnalysisDomain<'tcx> for MaybeStorageDead { } } -impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageDead { +impl<'tcx, 'a> crate::GenKillAnalysis<'tcx> for MaybeStorageDead<'a> { type Idx = Local; fn domain_size(&self, body: &Body<'tcx>) -> usize { diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index d7dd44af7d2..6da102dcb1c 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -59,7 +59,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::pluralize; use rustc_hir as hir; use rustc_hir::lang_items::LangItem; -use rustc_hir::CoroutineKind; +use rustc_hir::{CoroutineDesugaring, CoroutineKind}; use rustc_index::bit_set::{BitMatrix, BitSet, GrowableBitSet}; use rustc_index::{Idx, IndexVec}; use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor}; @@ -254,10 +254,12 @@ impl<'tcx> TransformVisitor<'tcx> { let source_info = SourceInfo::outermost(body.span); let none_value = match self.coroutine_kind { - CoroutineKind::Async(_) => span_bug!(body.span, "`Future`s are not fused inherently"), + CoroutineKind::Desugared(CoroutineDesugaring::Async, _) => { + span_bug!(body.span, "`Future`s are not fused inherently") + } CoroutineKind::Coroutine => span_bug!(body.span, "`Coroutine`s cannot be fused"), // `gen` continues return `None` - CoroutineKind::Gen(_) => { + CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => { let option_def_id = self.tcx.require_lang_item(LangItem::Option, None); Rvalue::Aggregate( Box::new(AggregateKind::Adt( @@ -271,7 +273,7 @@ impl<'tcx> TransformVisitor<'tcx> { ) } // `async gen` continues to return `Poll::Ready(None)` - CoroutineKind::AsyncGen(_) => { + CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _) => { let ty::Adt(_poll_adt, args) = *self.old_yield_ty.kind() else { bug!() }; let ty::Adt(_option_adt, args) = *args.type_at(0).kind() else { bug!() }; let yield_ty = args.type_at(0); @@ -316,7 +318,7 @@ impl<'tcx> TransformVisitor<'tcx> { statements: &mut Vec<Statement<'tcx>>, ) { let rvalue = match self.coroutine_kind { - CoroutineKind::Async(_) => { + CoroutineKind::Desugared(CoroutineDesugaring::Async, _) => { let poll_def_id = self.tcx.require_lang_item(LangItem::Poll, None); let args = self.tcx.mk_args(&[self.old_ret_ty.into()]); if is_return { @@ -345,7 +347,7 @@ impl<'tcx> TransformVisitor<'tcx> { ) } } - CoroutineKind::Gen(_) => { + CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => { let option_def_id = self.tcx.require_lang_item(LangItem::Option, None); let args = self.tcx.mk_args(&[self.old_yield_ty.into()]); if is_return { @@ -374,7 +376,7 @@ impl<'tcx> TransformVisitor<'tcx> { ) } } - CoroutineKind::AsyncGen(_) => { + CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _) => { if is_return { let ty::Adt(_poll_adt, args) = *self.old_yield_ty.kind() else { bug!() }; let ty::Adt(_option_adt, args) = *args.type_at(0).kind() else { bug!() }; @@ -1426,10 +1428,11 @@ fn create_coroutine_resume_function<'tcx>( if can_return { let block = match coroutine_kind { - CoroutineKind::Async(_) | CoroutineKind::Coroutine => { + CoroutineKind::Desugared(CoroutineDesugaring::Async, _) | CoroutineKind::Coroutine => { insert_panic_block(tcx, body, ResumedAfterReturn(coroutine_kind)) } - CoroutineKind::AsyncGen(_) | CoroutineKind::Gen(_) => { + CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _) + | CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => { transform.insert_none_ret_block(body) } }; @@ -1443,7 +1446,7 @@ fn create_coroutine_resume_function<'tcx>( match coroutine_kind { // Iterator::next doesn't accept a pinned argument, // unlike for all other coroutine kinds. - CoroutineKind::Gen(_) => {} + CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => {} _ => { make_coroutine_state_argument_pinned(tcx, body); } @@ -1609,25 +1612,34 @@ impl<'tcx> MirPass<'tcx> for StateTransform { } }; - let is_async_kind = matches!(body.coroutine_kind(), Some(CoroutineKind::Async(_))); - let is_async_gen_kind = matches!(body.coroutine_kind(), Some(CoroutineKind::AsyncGen(_))); - let is_gen_kind = matches!(body.coroutine_kind(), Some(CoroutineKind::Gen(_))); + let is_async_kind = matches!( + body.coroutine_kind(), + Some(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) + ); + let is_async_gen_kind = matches!( + body.coroutine_kind(), + Some(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _)) + ); + let is_gen_kind = matches!( + body.coroutine_kind(), + Some(CoroutineKind::Desugared(CoroutineDesugaring::Gen, _)) + ); let new_ret_ty = match body.coroutine_kind().unwrap() { - CoroutineKind::Async(_) => { + CoroutineKind::Desugared(CoroutineDesugaring::Async, _) => { // Compute Poll<return_ty> let poll_did = tcx.require_lang_item(LangItem::Poll, None); let poll_adt_ref = tcx.adt_def(poll_did); let poll_args = tcx.mk_args(&[old_ret_ty.into()]); Ty::new_adt(tcx, poll_adt_ref, poll_args) } - CoroutineKind::Gen(_) => { + CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => { // Compute Option<yield_ty> let option_did = tcx.require_lang_item(LangItem::Option, None); let option_adt_ref = tcx.adt_def(option_did); let option_args = tcx.mk_args(&[old_yield_ty.into()]); Ty::new_adt(tcx, option_adt_ref, option_args) } - CoroutineKind::AsyncGen(_) => { + CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _) => { // The yield ty is already `Poll<Option<yield_ty>>` old_yield_ty } diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index fd4af31501c..17916e16daf 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use rustc_errors::{ Applicability, DecorateLint, DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, - DiagnosticMessage, EmissionGuarantee, ErrorGuaranteed, IntoDiagnostic, + DiagnosticMessage, EmissionGuarantee, IntoDiagnostic, Level, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::mir::{AssertKind, UnsafetyViolationDetails}; @@ -62,10 +62,10 @@ pub(crate) struct RequiresUnsafe { // so we need to eagerly translate the label here, which isn't supported by the derive API // We could also exhaustively list out the primary messages for all unsafe violations, // but this would result in a lot of duplication. -impl<'sess> IntoDiagnostic<'sess> for RequiresUnsafe { +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for RequiresUnsafe { #[track_caller] - fn into_diagnostic(self, dcx: &'sess DiagCtxt) -> DiagnosticBuilder<'sess, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::mir_transform_requires_unsafe); + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { + let mut diag = DiagnosticBuilder::new(dcx, level, fluent::mir_transform_requires_unsafe); diag.code(rustc_errors::DiagnosticId::Error("E0133".to_string())); diag.set_span(self.span); diag.span_label(self.span, self.details.label()); diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 89e897191e8..98d4d96d0c7 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -86,6 +86,7 @@ pub mod inline; mod instsimplify; mod jump_threading; mod large_enums; +mod lint; mod lower_intrinsics; mod lower_slice_len; mod match_branches; diff --git a/compiler/rustc_mir_transform/src/lint.rs b/compiler/rustc_mir_transform/src/lint.rs new file mode 100644 index 00000000000..3940d0ddbf3 --- /dev/null +++ b/compiler/rustc_mir_transform/src/lint.rs @@ -0,0 +1,119 @@ +//! This pass statically detects code which has undefined behaviour or is likely to be erroneous. +//! It can be used to locate problems in MIR building or optimizations. It assumes that all code +//! can be executed, so it has false positives. +use rustc_index::bit_set::BitSet; +use rustc_middle::mir::visit::{PlaceContext, Visitor}; +use rustc_middle::mir::*; +use rustc_middle::ty::TyCtxt; +use rustc_mir_dataflow::impls::{MaybeStorageDead, MaybeStorageLive}; +use rustc_mir_dataflow::storage::always_storage_live_locals; +use rustc_mir_dataflow::{Analysis, ResultsCursor}; +use std::borrow::Cow; + +pub fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) { + let reachable_blocks = traversal::reachable_as_bitset(body); + let always_live_locals = &always_storage_live_locals(body); + + let maybe_storage_live = MaybeStorageLive::new(Cow::Borrowed(always_live_locals)) + .into_engine(tcx, body) + .iterate_to_fixpoint() + .into_results_cursor(body); + + let maybe_storage_dead = MaybeStorageDead::new(Cow::Borrowed(always_live_locals)) + .into_engine(tcx, body) + .iterate_to_fixpoint() + .into_results_cursor(body); + + Lint { + tcx, + when, + body, + is_fn_like: tcx.def_kind(body.source.def_id()).is_fn_like(), + always_live_locals, + reachable_blocks, + maybe_storage_live, + maybe_storage_dead, + } + .visit_body(body); +} + +struct Lint<'a, 'tcx> { + tcx: TyCtxt<'tcx>, + when: String, + body: &'a Body<'tcx>, + is_fn_like: bool, + always_live_locals: &'a BitSet<Local>, + reachable_blocks: BitSet<BasicBlock>, + maybe_storage_live: ResultsCursor<'a, 'tcx, MaybeStorageLive<'a>>, + maybe_storage_dead: ResultsCursor<'a, 'tcx, MaybeStorageDead<'a>>, +} + +impl<'a, 'tcx> Lint<'a, 'tcx> { + #[track_caller] + fn fail(&self, location: Location, msg: impl AsRef<str>) { + let span = self.body.source_info(location).span; + self.tcx.sess.dcx().span_delayed_bug( + span, + format!( + "broken MIR in {:?} ({}) at {:?}:\n{}", + self.body.source.instance, + self.when, + location, + msg.as_ref() + ), + ); + } +} + +impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> { + fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) { + if self.reachable_blocks.contains(location.block) && context.is_use() { + self.maybe_storage_dead.seek_after_primary_effect(location); + if self.maybe_storage_dead.get().contains(local) { + self.fail(location, format!("use of local {local:?}, which has no storage here")); + } + } + } + + fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { + match statement.kind { + StatementKind::StorageLive(local) => { + if self.reachable_blocks.contains(location.block) { + self.maybe_storage_live.seek_before_primary_effect(location); + if self.maybe_storage_live.get().contains(local) { + self.fail( + location, + format!("StorageLive({local:?}) which already has storage here"), + ); + } + } + } + _ => {} + } + + self.super_statement(statement, location); + } + + fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { + match terminator.kind { + TerminatorKind::Return => { + if self.is_fn_like && self.reachable_blocks.contains(location.block) { + self.maybe_storage_live.seek_after_primary_effect(location); + for local in self.maybe_storage_live.get().iter() { + if !self.always_live_locals.contains(local) { + self.fail( + location, + format!( + "local {local:?} still has storage when returning from function" + ), + ); + } + } + } + } + _ => {} + } + + self.super_terminator(terminator, location); + } +} diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index c4eca18ff27..1da1c1920b2 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -2,7 +2,7 @@ use rustc_middle::mir::{self, Body, MirPhase, RuntimePhase}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; -use crate::{validate, MirPass}; +use crate::{lint::lint_body, validate, MirPass}; /// Just like `MirPass`, except it cannot mutate `Body`. pub trait MirLint<'tcx> { @@ -109,6 +109,7 @@ fn run_passes_inner<'tcx>( phase_change: Option<MirPhase>, validate_each: bool, ) { + let lint = tcx.sess.opts.unstable_opts.lint_mir & !body.should_skip(); let validate = validate_each & tcx.sess.opts.unstable_opts.validate_mir & !body.should_skip(); let overridden_passes = &tcx.sess.opts.unstable_opts.mir_enable_passes; trace!(?overridden_passes); @@ -131,6 +132,9 @@ fn run_passes_inner<'tcx>( if validate { validate_body(tcx, body, format!("before pass {name}")); } + if lint { + lint_body(tcx, body, format!("before pass {name}")); + } if let Some(prof_arg) = &prof_arg { tcx.sess @@ -147,6 +151,9 @@ fn run_passes_inner<'tcx>( if validate { validate_body(tcx, body, format!("after pass {name}")); } + if lint { + lint_body(tcx, body, format!("after pass {name}")); + } body.pass_count += 1; } @@ -164,6 +171,9 @@ fn run_passes_inner<'tcx>( if validate || new_phase == MirPhase::Runtime(RuntimePhase::Optimized) { validate_body(tcx, body, format!("after phase change to {}", new_phase.name())); } + if lint { + lint_body(tcx, body, format!("after phase change to {}", new_phase.name())); + } body.pass_count = 1; } diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs index f13ab5b0f1f..05a3ac3cc75 100644 --- a/compiler/rustc_mir_transform/src/ref_prop.rs +++ b/compiler/rustc_mir_transform/src/ref_prop.rs @@ -7,6 +7,7 @@ use rustc_middle::ty::TyCtxt; use rustc_mir_dataflow::impls::MaybeStorageDead; use rustc_mir_dataflow::storage::always_storage_live_locals; use rustc_mir_dataflow::Analysis; +use std::borrow::Cow; use crate::ssa::{SsaLocals, StorageLiveLocals}; @@ -120,7 +121,7 @@ fn compute_replacement<'tcx>( // Compute `MaybeStorageDead` dataflow to check that we only replace when the pointee is // definitely live. - let mut maybe_dead = MaybeStorageDead::new(always_live_locals) + let mut maybe_dead = MaybeStorageDead::new(Cow::Owned(always_live_locals)) .into_engine(tcx, body) .iterate_to_fixpoint() .into_results_cursor(body); diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index 247b2245583..592e71251b8 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -1,8 +1,7 @@ use std::path::PathBuf; use crate::fluent_generated as fluent; -use rustc_errors::ErrorGuaranteed; -use rustc_errors::IntoDiagnostic; +use rustc_errors::{DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level}; use rustc_macros::{Diagnostic, LintDiagnostic}; use rustc_span::{Span, Symbol}; @@ -47,13 +46,11 @@ pub struct UnusedGenericParamsHint { pub param_names: Vec<String>, } -impl IntoDiagnostic<'_> for UnusedGenericParamsHint { +impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for UnusedGenericParamsHint { #[track_caller] - fn into_diagnostic( - self, - dcx: &'_ rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::monomorphize_unused_generic_params); + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = + DiagnosticBuilder::new(dcx, level, fluent::monomorphize_unused_generic_params); diag.set_span(self.span); for (span, name) in self.param_spans.into_iter().zip(self.param_names) { // FIXME: I can figure out how to do a label with a fluent string with a fixed message, diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 008adcc83d0..53cce9e2883 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2,7 +2,10 @@ use std::borrow::Cow; use rustc_ast::token::Token; use rustc_ast::{Path, Visibility}; -use rustc_errors::{AddToDiagnostic, Applicability, ErrorGuaranteed, IntoDiagnostic}; +use rustc_errors::{ + AddToDiagnostic, Applicability, DiagCtxt, DiagnosticBuilder, IntoDiagnostic, Level, + SubdiagnosticMessage, +}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::edition::{Edition, LATEST_STABLE_EDITION}; @@ -1040,25 +1043,28 @@ pub(crate) struct ExpectedIdentifier { impl<'a> IntoDiagnostic<'a> for ExpectedIdentifier { #[track_caller] - fn into_diagnostic( - self, - dcx: &'a rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'a, ErrorGuaranteed> { + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a> { let token_descr = TokenDescription::from_token(&self.token); - let mut diag = dcx.struct_err(match token_descr { - Some(TokenDescription::ReservedIdentifier) => { - fluent::parse_expected_identifier_found_reserved_identifier_str - } - Some(TokenDescription::Keyword) => fluent::parse_expected_identifier_found_keyword_str, - Some(TokenDescription::ReservedKeyword) => { - fluent::parse_expected_identifier_found_reserved_keyword_str - } - Some(TokenDescription::DocComment) => { - fluent::parse_expected_identifier_found_doc_comment_str - } - None => fluent::parse_expected_identifier_found_str, - }); + let mut diag = DiagnosticBuilder::new( + dcx, + level, + match token_descr { + Some(TokenDescription::ReservedIdentifier) => { + fluent::parse_expected_identifier_found_reserved_identifier_str + } + Some(TokenDescription::Keyword) => { + fluent::parse_expected_identifier_found_keyword_str + } + Some(TokenDescription::ReservedKeyword) => { + fluent::parse_expected_identifier_found_reserved_keyword_str + } + Some(TokenDescription::DocComment) => { + fluent::parse_expected_identifier_found_doc_comment_str + } + None => fluent::parse_expected_identifier_found_str, + }, + ); diag.set_span(self.span); diag.set_arg("token", self.token); @@ -1097,23 +1103,26 @@ pub(crate) struct ExpectedSemi { impl<'a> IntoDiagnostic<'a> for ExpectedSemi { #[track_caller] - fn into_diagnostic( - self, - dcx: &'a rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'a, ErrorGuaranteed> { + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a> { let token_descr = TokenDescription::from_token(&self.token); - let mut diag = dcx.struct_err(match token_descr { - Some(TokenDescription::ReservedIdentifier) => { - fluent::parse_expected_semi_found_reserved_identifier_str - } - Some(TokenDescription::Keyword) => fluent::parse_expected_semi_found_keyword_str, - Some(TokenDescription::ReservedKeyword) => { - fluent::parse_expected_semi_found_reserved_keyword_str - } - Some(TokenDescription::DocComment) => fluent::parse_expected_semi_found_doc_comment_str, - None => fluent::parse_expected_semi_found_str, - }); + let mut diag = DiagnosticBuilder::new( + dcx, + level, + match token_descr { + Some(TokenDescription::ReservedIdentifier) => { + fluent::parse_expected_semi_found_reserved_identifier_str + } + Some(TokenDescription::Keyword) => fluent::parse_expected_semi_found_keyword_str, + Some(TokenDescription::ReservedKeyword) => { + fluent::parse_expected_semi_found_reserved_keyword_str + } + Some(TokenDescription::DocComment) => { + fluent::parse_expected_semi_found_doc_comment_str + } + None => fluent::parse_expected_semi_found_str, + }, + ); diag.set_span(self.span); diag.set_arg("token", self.token); @@ -1436,10 +1445,7 @@ pub(crate) struct FnTraitMissingParen { impl AddToDiagnostic for FnTraitMissingParen { fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F) where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, + F: Fn(&mut rustc_errors::Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { diag.span_label(self.span, crate::fluent_generated::parse_fn_trait_missing_paren); let applicability = if self.machine_applicable { diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index c158edaac25..59bc0eeb1c5 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -7,7 +7,9 @@ use rustc_ast::ast::{self, AttrStyle}; use rustc_ast::token::{self, CommentKind, Delimiter, Token, TokenKind}; use rustc_ast::tokenstream::TokenStream; use rustc_ast::util::unicode::contains_text_flow_control_chars; -use rustc_errors::{error_code, Applicability, Diagnostic, DiagnosticBuilder, StashKey}; +use rustc_errors::{ + error_code, Applicability, Diagnostic, DiagnosticBuilder, FatalAbort, StashKey, +}; use rustc_lexer::unescape::{self, EscapeError, Mode}; use rustc_lexer::{Base, DocStyle, RawStrError}; use rustc_lexer::{Cursor, LiteralKind}; @@ -344,7 +346,7 @@ impl<'a> StringReader<'a> { to_pos: BytePos, m: &str, c: char, - ) -> DiagnosticBuilder<'a, !> { + ) -> DiagnosticBuilder<'a, FatalAbort> { self.sess .dcx .struct_span_fatal(self.mk_sp(from_pos, to_pos), format!("{}: {}", m, escaped_char(c))) diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 56e52baf98b..53b29eccc2c 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -5,7 +5,7 @@ use super::{AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle use rustc_ast as ast; use rustc_ast::attr; use rustc_ast::token::{self, Delimiter, Nonterminal}; -use rustc_errors::{error_code, Diagnostic, IntoDiagnostic, PResult}; +use rustc_errors::{error_code, Diagnostic, PResult}; use rustc_span::{sym, BytePos, Span}; use thin_vec::ThinVec; use tracing::debug; @@ -416,8 +416,9 @@ impl<'a> Parser<'a> { Err(err) => err.cancel(), } - Err(InvalidMetaItem { span: self.token.span, token: self.token.clone() } - .into_diagnostic(self.dcx())) + Err(self + .dcx() + .create_err(InvalidMetaItem { span: self.token.span, token: self.token.clone() })) } } diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index c077e0a83a1..4d557e495d8 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -35,7 +35,7 @@ use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{ pluralize, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, - DiagnosticMessage, ErrorGuaranteed, FatalError, IntoDiagnostic, MultiSpan, PResult, + DiagnosticMessage, FatalError, MultiSpan, PResult, }; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::Spanned; @@ -245,7 +245,7 @@ impl<'a> Parser<'a> { &self, sp: S, m: impl Into<DiagnosticMessage>, - ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'a> { self.dcx().struct_span_err(sp, m) } @@ -280,11 +280,10 @@ impl<'a> Parser<'a> { recover: bool, ) -> PResult<'a, (Ident, /* is_raw */ bool)> { if let TokenKind::DocComment(..) = self.prev_token.kind { - return Err(DocCommentDoesNotDocumentAnything { + return Err(self.dcx().create_err(DocCommentDoesNotDocumentAnything { span: self.prev_token.span, missing_comma: None, - } - .into_diagnostic(self.dcx())); + })); } let valid_follow = &[ @@ -347,7 +346,7 @@ impl<'a> Parser<'a> { suggest_remove_comma, help_cannot_start_number, }; - let mut err = err.into_diagnostic(self.dcx()); + let mut err = self.dcx().create_err(err); // if the token we have is a `<` // it *might* be a misplaced generic @@ -414,7 +413,7 @@ impl<'a> Parser<'a> { } } - pub(super) fn expected_ident_found_err(&mut self) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + pub(super) fn expected_ident_found_err(&mut self) -> DiagnosticBuilder<'a> { self.expected_ident_found(false).unwrap_err() } @@ -959,7 +958,7 @@ impl<'a> Parser<'a> { pub(super) fn recover_closure_body( &mut self, - mut err: DiagnosticBuilder<'a, ErrorGuaranteed>, + mut err: DiagnosticBuilder<'a>, before: token::Token, prev: token::Token, token: token::Token, @@ -1190,7 +1189,7 @@ impl<'a> Parser<'a> { /// encounter a parse error when encountering the first `,`. pub(super) fn check_mistyped_turbofish_with_multiple_type_params( &mut self, - mut e: DiagnosticBuilder<'a, ErrorGuaranteed>, + mut e: DiagnosticBuilder<'a>, expr: &mut P<Expr>, ) -> PResult<'a, ()> { if let ExprKind::Binary(binop, _, _) = &expr.kind @@ -1235,10 +1234,7 @@ impl<'a> Parser<'a> { /// Suggest add the missing `let` before the identifier in stmt /// `a: Ty = 1` -> `let a: Ty = 1` - pub(super) fn suggest_add_missing_let_for_stmt( - &mut self, - err: &mut DiagnosticBuilder<'a, ErrorGuaranteed>, - ) { + pub(super) fn suggest_add_missing_let_for_stmt(&mut self, err: &mut DiagnosticBuilder<'a>) { if self.token == token::Colon { let prev_span = self.prev_token.span.shrink_to_lo(); let snapshot = self.create_snapshot_for_diagnostic(); @@ -1432,7 +1428,7 @@ impl<'a> Parser<'a> { // Not entirely sure now, but we bubble the error up with the // suggestion. self.restore_snapshot(snapshot); - Err(err.into_diagnostic(self.dcx())) + Err(self.dcx().create_err(err)) } } } else if token::OpenDelim(Delimiter::Parenthesis) == self.token.kind { @@ -1447,7 +1443,7 @@ impl<'a> Parser<'a> { } // Consume the fn call arguments. match self.consume_fn_args() { - Err(()) => Err(err.into_diagnostic(self.dcx())), + Err(()) => Err(self.dcx().create_err(err)), Ok(()) => { self.sess.emit_err(err); // FIXME: actually check that the two expressions in the binop are @@ -1473,7 +1469,7 @@ impl<'a> Parser<'a> { mk_err_expr(self, inner_op.span.to(self.prev_token.span)) } else { // These cases cause too many knock-down errors, bail out (#61329). - Err(err.into_diagnostic(self.dcx())) + Err(self.dcx().create_err(err)) } }; } @@ -2321,7 +2317,7 @@ impl<'a> Parser<'a> { } } - pub(super) fn expected_expression_found(&self) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + pub(super) fn expected_expression_found(&self) -> DiagnosticBuilder<'a> { let (span, msg) = match (&self.token.kind, self.subparser_name) { (&token::Eof, Some(origin)) => { let sp = self.prev_token.span.shrink_to_hi(); @@ -2561,7 +2557,7 @@ impl<'a> Parser<'a> { Ok(Some(GenericArg::Const(self.parse_const_arg()?))) } else { let after_kw_const = self.token.span; - self.recover_const_arg(after_kw_const, err.into_diagnostic(self.dcx())).map(Some) + self.recover_const_arg(after_kw_const, self.dcx().create_err(err)).map(Some) } } @@ -2573,7 +2569,7 @@ impl<'a> Parser<'a> { pub fn recover_const_arg( &mut self, start: Span, - mut err: DiagnosticBuilder<'a, ErrorGuaranteed>, + mut err: DiagnosticBuilder<'a>, ) -> PResult<'a, GenericArg> { let is_op_or_dot = AssocOp::from_token(&self.token) .and_then(|op| { @@ -2675,7 +2671,7 @@ impl<'a> Parser<'a> { /// Creates a dummy const argument, and reports that the expression must be enclosed in braces pub fn dummy_const_arg_needs_braces( &self, - mut err: DiagnosticBuilder<'a, ErrorGuaranteed>, + mut err: DiagnosticBuilder<'a>, span: Span, ) -> GenericArg { err.multipart_suggestion( @@ -2915,11 +2911,10 @@ impl<'a> Parser<'a> { let (a_span, b_span) = (a.span(), b.span()); let between_span = a_span.shrink_to_hi().to(b_span.shrink_to_lo()); if self.span_to_snippet(between_span).as_deref() == Ok(":: ") { - return Err(DoubleColonInBound { + return Err(self.dcx().create_err(DoubleColonInBound { span: path.span.shrink_to_hi(), between: between_span, - } - .into_diagnostic(self.dcx())); + })); } } } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index cd3e8b92f2f..a6783eaf8d4 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -10,7 +10,7 @@ use super::{ use crate::errors; use crate::maybe_recover_from_interpolated_ty_qpath; use ast::mut_visit::{noop_visit_expr, MutVisitor}; -use ast::{CoroutineKind, GenBlockKind, Pat, Path, PathSegment}; +use ast::{CoroutineKind, ForLoopKind, GenBlockKind, Pat, Path, PathSegment}; use core::mem; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; @@ -26,8 +26,7 @@ use rustc_ast::{ClosureBinder, MetaItemLit, StmtKind}; use rustc_ast_pretty::pprust; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{ - AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, - PResult, StashKey, + AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, PResult, StashKey, }; use rustc_macros::Subdiagnostic; use rustc_session::errors::{report_lit_error, ExprParenthesesNeeded}; @@ -1255,21 +1254,21 @@ impl<'a> Parser<'a> { // that of the open delim in `TokenTreesReader::parse_token_tree`, even if they are different. self.span_to_snippet(close_paren).is_ok_and(|snippet| snippet == ")") { - let mut replacement_err = errors::ParenthesesWithStructFields { - span, - r#type: path, - braces_for_struct: errors::BracesForStructLiteral { - first: open_paren, - second: close_paren, - }, - no_fields_for_fn: errors::NoFieldsForFnCall { - fields: fields - .into_iter() - .map(|field| field.span.until(field.expr.span)) - .collect(), - }, - } - .into_diagnostic(self.dcx()); + let mut replacement_err = + self.dcx().create_err(errors::ParenthesesWithStructFields { + span, + r#type: path, + braces_for_struct: errors::BracesForStructLiteral { + first: open_paren, + second: close_paren, + }, + no_fields_for_fn: errors::NoFieldsForFnCall { + fields: fields + .into_iter() + .map(|field| field.span.until(field.expr.span)) + .collect(), + }, + }); replacement_err.emit(); let old_err = mem::replace(err, replacement_err); @@ -1691,7 +1690,7 @@ impl<'a> Parser<'a> { &self, lifetime: Ident, mk_lit_char: impl FnOnce(Symbol, Span) -> L, - err: impl FnOnce(&Self) -> DiagnosticBuilder<'a, ErrorGuaranteed>, + err: impl FnOnce(&Self) -> DiagnosticBuilder<'a>, ) -> L { if let Some(mut diag) = self.dcx().steal_diagnostic(lifetime.span, StashKey::LifetimeIsChar) { @@ -1801,7 +1800,7 @@ impl<'a> Parser<'a> { && matches!( expr.kind, ExprKind::While(_, _, None) - | ExprKind::ForLoop(_, _, _, None) + | ExprKind::ForLoop { label: None, .. } | ExprKind::Loop(_, None, _) | ExprKind::Block(_, None) ) @@ -1883,8 +1882,7 @@ impl<'a> Parser<'a> { self.bump(); // `#` let Some((ident, false)) = self.token.ident() else { - let err = - errors::ExpectedBuiltinIdent { span: self.token.span }.into_diagnostic(self.dcx()); + let err = self.dcx().create_err(errors::ExpectedBuiltinIdent { span: self.token.span }); return Err(err); }; self.sess.gated_spans.gate(sym::builtin_syntax, ident.span); @@ -1894,8 +1892,10 @@ impl<'a> Parser<'a> { let ret = if let Some(res) = parse(self, lo, ident)? { Ok(res) } else { - let err = errors::UnknownBuiltinConstruct { span: lo.to(ident.span), name: ident.name } - .into_diagnostic(self.dcx()); + let err = self.dcx().create_err(errors::UnknownBuiltinConstruct { + span: lo.to(ident.span), + name: ident.name, + }); return Err(err); }; self.expect(&TokenKind::CloseDelim(Delimiter::Parenthesis))?; @@ -1958,8 +1958,9 @@ impl<'a> Parser<'a> { && let token::NtExpr(e) | token::NtLiteral(e) = &nt.0 && matches!(e.kind, ExprKind::Err) { - let mut err = errors::InvalidInterpolatedExpression { span: self.token.span } - .into_diagnostic(self.dcx()); + let mut err = self + .dcx() + .create_err(errors::InvalidInterpolatedExpression { span: self.token.span }); err.downgrade_to_delayed_bug(); return Err(err); } @@ -2168,10 +2169,10 @@ impl<'a> Parser<'a> { .span_to_snippet(snapshot.token.span) .is_ok_and(|snippet| snippet == "]") => { - return Err(errors::MissingSemicolonBeforeArray { + return Err(self.dcx().create_err(errors::MissingSemicolonBeforeArray { open_delim: open_delim_span, semicolon: prev_span.shrink_to_hi(), - }.into_diagnostic(self.dcx())); + })); } Ok(_) => (), Err(err) => err.cancel(), @@ -2318,8 +2319,9 @@ impl<'a> Parser<'a> { // Check for `move async` and recover if self.check_keyword(kw::Async) { let move_async_span = self.token.span.with_lo(self.prev_token.span.data().lo); - Err(errors::AsyncMoveOrderIncorrect { span: move_async_span } - .into_diagnostic(self.dcx())) + Err(self + .dcx() + .create_err(errors::AsyncMoveOrderIncorrect { span: move_async_span })) } else { Ok(CaptureBy::Value { move_kw: move_kw_span }) } @@ -2509,7 +2511,7 @@ impl<'a> Parser<'a> { }; if self.prev_token.kind == token::BinOp(token::Or) { // This was part of a closure, the that part of the parser recover. - return Err(err.into_diagnostic(self.dcx())); + return Err(self.dcx().create_err(err)); } else { Some(self.sess.emit_err(err)) } @@ -2682,8 +2684,17 @@ impl<'a> Parser<'a> { Ok((pat, expr)) } - /// Parses `for <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten). + /// Parses `for await? <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten). fn parse_expr_for(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> { + let is_await = + self.token.uninterpolated_span().at_least_rust_2018() && self.eat_keyword(kw::Await); + + if is_await { + self.sess.gated_spans.gate(sym::async_for_loop, self.prev_token.span); + } + + let kind = if is_await { ForLoopKind::ForAwait } else { ForLoopKind::For }; + let (pat, expr) = self.parse_for_head()?; // Recover from missing expression in `for` loop if matches!(expr.kind, ExprKind::Block(..)) @@ -2696,13 +2707,13 @@ impl<'a> Parser<'a> { let block = self.mk_block(thin_vec![], BlockCheckMode::Default, self.prev_token.span); return Ok(self.mk_expr( lo.to(self.prev_token.span), - ExprKind::ForLoop(pat, err_expr, block, opt_label), + ExprKind::ForLoop { pat, iter: err_expr, body: block, label: opt_label, kind }, )); } let (attrs, loop_block) = self.parse_inner_attrs_and_block()?; - let kind = ExprKind::ForLoop(pat, expr, loop_block, opt_label); + let kind = ExprKind::ForLoop { pat, iter: expr, body: loop_block, label: opt_label, kind }; self.recover_loop_else("for", lo)?; @@ -3193,7 +3204,7 @@ impl<'a> Parser<'a> { fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, P<Expr>> { let (attrs, body) = self.parse_inner_attrs_and_block()?; if self.eat_keyword(kw::Catch) { - Err(errors::CatchAfterTry { span: self.prev_token.span }.into_diagnostic(self.dcx())) + Err(self.dcx().create_err(errors::CatchAfterTry { span: self.prev_token.span })) } else { let span = span_lo.to(body.span); self.sess.gated_spans.gate(sym::try_blocks, span); @@ -3530,12 +3541,11 @@ impl<'a> Parser<'a> { || t == &token::CloseDelim(Delimiter::Parenthesis) }); if is_wrong { - return Err(errors::ExpectedStructField { + return Err(this.dcx().create_err(errors::ExpectedStructField { span: this.look_ahead(1, |t| t.span), ident_span: this.token.span, token: this.look_ahead(1, |t| t.clone()), - } - .into_diagnostic(&self.sess.dcx)); + })); } let (ident, expr) = if is_shorthand { // Mimic `x: x` for the `x` field shorthand. @@ -3798,7 +3808,7 @@ impl MutVisitor for CondChecker<'_> { | ExprKind::Lit(_) | ExprKind::If(_, _, _) | ExprKind::While(_, _, _) - | ExprKind::ForLoop(_, _, _, _) + | ExprKind::ForLoop { .. } | ExprKind::Loop(_, _, _) | ExprKind::Match(_, _) | ExprKind::Closure(_) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 09ee042ef6b..051f19f5a9d 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -10,10 +10,7 @@ use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree}; use rustc_ast::util::case::Case; use rustc_ast::{self as ast}; use rustc_ast_pretty::pprust; -use rustc_errors::{ - struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, PResult, - StashKey, -}; +use rustc_errors::{struct_span_err, Applicability, PResult, StashKey}; use rustc_span::edit_distance::edit_distance; use rustc_span::edition::Edition; use rustc_span::source_map; @@ -438,7 +435,7 @@ impl<'a> Parser<'a> { None }; - if let Some(err) = err { Err(err.into_diagnostic(self.dcx())) } else { Ok(()) } + if let Some(err) = err { Err(self.dcx().create_err(err)) } else { Ok(()) } } fn parse_item_builtin(&mut self) -> PResult<'a, Option<ItemInfo>> { @@ -1373,8 +1370,7 @@ impl<'a> Parser<'a> { }; let span = self.prev_token.span.shrink_to_hi(); - let err: DiagnosticBuilder<'_, ErrorGuaranteed> = - errors::MissingConstType { span, colon, kind }.into_diagnostic(self.dcx()); + let err = self.dcx().create_err(errors::MissingConstType { span, colon, kind }); err.stash(span, StashKey::ItemNoType); // The user intended that the type be inferred, @@ -1391,7 +1387,7 @@ impl<'a> Parser<'a> { self.bump(); self.sess.emit_err(err); } else { - return Err(err.into_diagnostic(self.dcx())); + return Err(self.dcx().create_err(err)); } } @@ -1591,7 +1587,7 @@ impl<'a> Parser<'a> { } else { let err = errors::UnexpectedTokenAfterStructName::new(self.token.span, self.token.clone()); - return Err(err.into_diagnostic(self.dcx())); + return Err(self.dcx().create_err(err)); }; Ok((class_name, ItemKind::Struct(vdata, generics))) @@ -1787,7 +1783,7 @@ impl<'a> Parser<'a> { let sp = previous_span.shrink_to_hi(); err.missing_comma = Some(sp); } - return Err(err.into_diagnostic(self.dcx())); + return Err(self.dcx().create_err(err)); } } _ => { diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index b91432f10c8..47c337ad913 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -32,9 +32,7 @@ use rustc_ast::{HasAttrs, HasTokens, Unsafe, Visibility, VisibilityKind}; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; use rustc_errors::PResult; -use rustc_errors::{ - Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError, IntoDiagnostic, MultiSpan, -}; +use rustc_errors::{Applicability, DiagnosticBuilder, FatalError, MultiSpan}; use rustc_session::parse::ParseSess; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -910,7 +908,7 @@ impl<'a> Parser<'a> { fn recover_missing_braces_around_closure_body( &mut self, closure_spans: ClosureSpans, - mut expect_err: DiagnosticBuilder<'_, ErrorGuaranteed>, + mut expect_err: DiagnosticBuilder<'_>, ) -> PResult<'a, ()> { let initial_semicolon = self.token.span; @@ -1492,7 +1490,7 @@ impl<'a> Parser<'a> { pub(crate) fn make_unclosed_delims_error( unmatched: UnmatchedDelim, sess: &ParseSess, -) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> { +) -> Option<DiagnosticBuilder<'_>> { // `None` here means an `Eof` was found. We already emit those errors elsewhere, we add them to // `unmatched_delims` only for error recovery in the `Parser`. let found_delim = unmatched.found_delim?; @@ -1500,14 +1498,13 @@ pub(crate) fn make_unclosed_delims_error( if let Some(sp) = unmatched.unclosed_span { spans.push(sp); }; - let err = MismatchedClosingDelimiter { + let err = sess.dcx.create_err(MismatchedClosingDelimiter { spans, delimiter: pprust::token_kind_to_string(&token::CloseDelim(found_delim)).to_string(), unmatched: unmatched.found_span, opening_candidate: unmatched.candidate_span, unclosed: unmatched.unclosed_span, - } - .into_diagnostic(&sess.dcx); + }); Some(err) } diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 301a88cd077..071d6b72f3b 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -2,7 +2,6 @@ use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Nonterminal::*, NonterminalKind, Token}; use rustc_ast::HasTokens; use rustc_ast_pretty::pprust; -use rustc_errors::IntoDiagnostic; use rustc_errors::PResult; use rustc_span::symbol::{kw, Ident}; @@ -114,9 +113,9 @@ impl<'a> Parser<'a> { NonterminalKind::Item => match self.parse_item(ForceCollect::Yes)? { Some(item) => NtItem(item), None => { - return Err( - UnexpectedNonterminal::Item(self.token.span).into_diagnostic(self.dcx()) - ); + return Err(self + .dcx() + .create_err(UnexpectedNonterminal::Item(self.token.span))); } }, NonterminalKind::Block => { @@ -127,8 +126,9 @@ impl<'a> Parser<'a> { NonterminalKind::Stmt => match self.parse_stmt(ForceCollect::Yes)? { Some(s) => NtStmt(P(s)), None => { - return Err(UnexpectedNonterminal::Statement(self.token.span) - .into_diagnostic(self.dcx())); + return Err(self + .dcx() + .create_err(UnexpectedNonterminal::Statement(self.token.span))); } }, NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => { @@ -160,11 +160,10 @@ impl<'a> Parser<'a> { NtIdent(ident, is_raw) } NonterminalKind::Ident => { - return Err(UnexpectedNonterminal::Ident { + return Err(self.dcx().create_err(UnexpectedNonterminal::Ident { span: self.token.span, token: self.token.clone(), - } - .into_diagnostic(self.dcx())); + })); } NonterminalKind::Path => { NtPath(P(self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?)) @@ -178,11 +177,10 @@ impl<'a> Parser<'a> { if self.check_lifetime() { NtLifetime(self.expect_lifetime().ident) } else { - return Err(UnexpectedNonterminal::Lifetime { + return Err(self.dcx().create_err(UnexpectedNonterminal::Lifetime { span: self.token.span, token: self.token.clone(), - } - .into_diagnostic(self.dcx())); + })); } } }; diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 80233eddb9b..11c4b8fae7c 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -15,10 +15,10 @@ use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter}; use rustc_ast::{ self as ast, AttrVec, BindingAnnotation, ByRef, Expr, ExprKind, MacCall, Mutability, Pat, - PatField, PatKind, Path, QSelf, RangeEnd, RangeSyntax, + PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax, }; use rustc_ast_pretty::pprust; -use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, PResult}; +use rustc_errors::{Applicability, DiagnosticBuilder, PResult}; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{kw, sym, Ident}; @@ -687,7 +687,7 @@ impl<'a> Parser<'a> { fn fatal_unexpected_non_pat( &mut self, - err: DiagnosticBuilder<'a, ErrorGuaranteed>, + err: DiagnosticBuilder<'a>, expected: Option<Expected>, ) -> PResult<'a, P<Pat>> { err.cancel(); @@ -872,8 +872,9 @@ impl<'a> Parser<'a> { // binding mode then we do not end up here, because the lookahead // will direct us over to `parse_enum_variant()`. if self.token == token::OpenDelim(Delimiter::Parenthesis) { - return Err(EnumPatternInsteadOfIdentifier { span: self.prev_token.span } - .into_diagnostic(self.dcx())); + return Err(self + .dcx() + .create_err(EnumPatternInsteadOfIdentifier { span: self.prev_token.span })); } Ok(PatKind::Ident(binding_annotation, ident, sub)) @@ -890,7 +891,8 @@ impl<'a> Parser<'a> { e.span_label(path.span, "while parsing the fields for this pattern"); e.emit(); self.recover_stmt(); - (ThinVec::new(), true) + // When recovering, pretend we had `Foo { .. }`, to avoid cascading errors. + (ThinVec::new(), PatFieldsRest::Rest) }); self.bump(); Ok(PatKind::Struct(qself, path, fields, etc)) @@ -964,11 +966,11 @@ impl<'a> Parser<'a> { } /// Parses the fields of a struct-like pattern. - fn parse_pat_fields(&mut self) -> PResult<'a, (ThinVec<PatField>, bool)> { + fn parse_pat_fields(&mut self) -> PResult<'a, (ThinVec<PatField>, PatFieldsRest)> { let mut fields = ThinVec::new(); - let mut etc = false; + let mut etc = PatFieldsRest::None; let mut ate_comma = true; - let mut delayed_err: Option<DiagnosticBuilder<'a, ErrorGuaranteed>> = None; + let mut delayed_err: Option<DiagnosticBuilder<'a>> = None; let mut first_etc_and_maybe_comma_span = None; let mut last_non_comma_dotdot_span = None; @@ -986,8 +988,8 @@ impl<'a> Parser<'a> { // check that a comma comes after every field if !ate_comma { - let mut err = ExpectedCommaAfterPatternField { span: self.token.span } - .into_diagnostic(self.dcx()); + let mut err = + self.dcx().create_err(ExpectedCommaAfterPatternField { span: self.token.span }); if let Some(mut delayed) = delayed_err { delayed.emit(); } @@ -1000,7 +1002,7 @@ impl<'a> Parser<'a> { || self.check_noexpect(&token::DotDotDot) || self.check_keyword(kw::Underscore) { - etc = true; + etc = PatFieldsRest::Rest; let mut etc_sp = self.token.span; if first_etc_and_maybe_comma_span.is_none() { if let Some(comma_tok) = self @@ -1134,7 +1136,7 @@ impl<'a> Parser<'a> { fn recover_misplaced_pattern_modifiers( &self, fields: &ThinVec<PatField>, - err: &mut DiagnosticBuilder<'a, ErrorGuaranteed>, + err: &mut DiagnosticBuilder<'a>, ) { if let Some(last) = fields.iter().last() && last.is_shorthand diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 3b92a911983..405531c1e41 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -9,7 +9,7 @@ use rustc_ast::{ AssocConstraintKind, BlockCheckMode, GenericArg, GenericArgs, Generics, ParenthesizedArgs, Path, PathSegment, QSelf, }; -use rustc_errors::{Applicability, IntoDiagnostic, PResult}; +use rustc_errors::{Applicability, PResult}; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{BytePos, Span}; use std::mem; @@ -318,15 +318,14 @@ impl<'a> Parser<'a> { }) { err.cancel(); - err = PathSingleColon { + err = self.dcx().create_err(PathSingleColon { span: self.token.span, type_ascription: self .sess .unstable_features .is_nightly_build() .then_some(()), - } - .into_diagnostic(self.dcx()); + }); } // Attempt to find places where a missing `>` might belong. else if let Some(arg) = args @@ -841,7 +840,7 @@ impl<'a> Parser<'a> { { return Ok((false, seg.ident, seg.args.as_deref().cloned())); } else if let ast::TyKind::TraitObject(bounds, ast::TraitObjectSyntax::None) = &ty.kind - && let [ast::GenericBound::Trait(trait_ref, ast::TraitBoundModifier::None)] = + && let [ast::GenericBound::Trait(trait_ref, ast::TraitBoundModifiers::NONE)] = bounds.as_slice() && let [seg] = trait_ref.trait_ref.path.segments.as_slice() { diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 1ee5a96d5dc..1ac5aba212c 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -19,7 +19,7 @@ use rustc_ast::util::classify; use rustc_ast::{AttrStyle, AttrVec, LocalKind, MacCall, MacCallStmt, MacStmtStyle}; use rustc_ast::{Block, BlockCheckMode, Expr, ExprKind, HasAttrs, Local, Stmt}; use rustc_ast::{StmtKind, DUMMY_NODE_ID}; -use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult}; +use rustc_errors::{Applicability, DiagnosticBuilder, PResult}; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{BytePos, Span}; @@ -442,7 +442,7 @@ impl<'a> Parser<'a> { fn error_block_no_opening_brace_msg( &mut self, msg: Cow<'static, str>, - ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'a> { let sp = self.token.span; let mut e = self.struct_span_err(sp, msg); let do_not_suggest_help = self.token.is_keyword(kw::In) || self.token == token::Colon; diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index da8cc05ff66..f89d6d1d965 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -13,37 +13,15 @@ use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; use rustc_ast::util::case::Case; use rustc_ast::{ - self as ast, BareFnTy, BoundPolarity, FnRetTy, GenericBound, GenericBounds, GenericParam, - Generics, Lifetime, MacCall, MutTy, Mutability, PolyTraitRef, TraitBoundModifier, - TraitObjectSyntax, Ty, TyKind, + self as ast, BareFnTy, BoundConstness, BoundPolarity, FnRetTy, GenericBound, GenericBounds, + GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, PolyTraitRef, + TraitBoundModifiers, TraitObjectSyntax, Ty, TyKind, }; use rustc_errors::{Applicability, PResult}; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{Span, Symbol}; use thin_vec::{thin_vec, ThinVec}; -/// Any `?`, `!`, or `~const` modifiers that appear at the start of a bound. -struct BoundModifiers { - /// `?Trait`. - bound_polarity: BoundPolarity, - - /// `~const Trait`. - maybe_const: Option<Span>, -} - -impl BoundModifiers { - fn to_trait_bound_modifier(&self) -> TraitBoundModifier { - match (self.bound_polarity, self.maybe_const) { - (BoundPolarity::Positive, None) => TraitBoundModifier::None, - (BoundPolarity::Negative(_), None) => TraitBoundModifier::Negative, - (BoundPolarity::Maybe(_), None) => TraitBoundModifier::Maybe, - (BoundPolarity::Positive, Some(sp)) => TraitBoundModifier::MaybeConst(sp), - (BoundPolarity::Negative(_), Some(_)) => TraitBoundModifier::MaybeConstNegative, - (BoundPolarity::Maybe(_), Some(_)) => TraitBoundModifier::MaybeConstMaybe, - } - } -} - #[derive(Copy, Clone, PartialEq)] pub(super) enum AllowPlus { Yes, @@ -461,7 +439,7 @@ impl<'a> Parser<'a> { parse_plus: bool, ) -> PResult<'a, TyKind> { let poly_trait_ref = PolyTraitRef::new(generic_params, path, lo.to(self.prev_token.span)); - let bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)]; + let bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifiers::NONE)]; self.parse_remaining_bounds(bounds, parse_plus) } @@ -800,7 +778,7 @@ impl<'a> Parser<'a> { let has_parens = self.eat(&token::OpenDelim(Delimiter::Parenthesis)); let inner_lo = self.token.span; - let modifiers = self.parse_ty_bound_modifiers()?; + let modifiers = self.parse_trait_bound_modifiers()?; let bound = if self.token.is_lifetime() { self.error_lt_bound_with_modifiers(modifiers); self.parse_generic_lt_bound(lo, inner_lo, has_parens)? @@ -831,18 +809,21 @@ impl<'a> Parser<'a> { } /// Emits an error if any trait bound modifiers were present. - fn error_lt_bound_with_modifiers(&self, modifiers: BoundModifiers) { - if let Some(span) = modifiers.maybe_const { - self.sess.emit_err(errors::TildeConstLifetime { span }); + fn error_lt_bound_with_modifiers(&self, modifiers: TraitBoundModifiers) { + match modifiers.constness { + BoundConstness::Never => {} + BoundConstness::Maybe(span) => { + self.sess.emit_err(errors::TildeConstLifetime { span }); + } } - match modifiers.bound_polarity { + match modifiers.polarity { BoundPolarity::Positive => {} - BoundPolarity::Negative(span) => { - self.sess.emit_err(errors::ModifierLifetime { span, sigil: "!" }); - } - BoundPolarity::Maybe(span) => { - self.sess.emit_err(errors::ModifierLifetime { span, sigil: "?" }); + BoundPolarity::Negative(span) | BoundPolarity::Maybe(span) => { + self.sess.emit_err(errors::ModifierLifetime { + span, + sigil: modifiers.polarity.as_str(), + }); } } } @@ -867,26 +848,26 @@ impl<'a> Parser<'a> { /// If no modifiers are present, this does not consume any tokens. /// /// ```ebnf - /// TY_BOUND_MODIFIERS = ["~const"] ["?"] + /// TRAIT_BOUND_MODIFIERS = ["~const"] ["?" | "!"] /// ``` - fn parse_ty_bound_modifiers(&mut self) -> PResult<'a, BoundModifiers> { - let maybe_const = if self.eat(&token::Tilde) { + fn parse_trait_bound_modifiers(&mut self) -> PResult<'a, TraitBoundModifiers> { + let constness = if self.eat(&token::Tilde) { let tilde = self.prev_token.span; self.expect_keyword(kw::Const)?; let span = tilde.to(self.prev_token.span); self.sess.gated_spans.gate(sym::const_trait_impl, span); - Some(span) + BoundConstness::Maybe(span) } else if self.eat_keyword(kw::Const) { let span = self.prev_token.span; self.sess.gated_spans.gate(sym::const_trait_impl, span); self.sess.emit_err(errors::ConstMissingTilde { span, start: span.shrink_to_lo() }); - Some(span) + BoundConstness::Maybe(span) } else { - None + BoundConstness::Never }; - let bound_polarity = if self.eat(&token::Question) { + let polarity = if self.eat(&token::Question) { BoundPolarity::Maybe(self.prev_token.span) } else if self.eat(&token::Not) { self.sess.gated_spans.gate(sym::negative_bounds, self.prev_token.span); @@ -895,13 +876,13 @@ impl<'a> Parser<'a> { BoundPolarity::Positive }; - Ok(BoundModifiers { bound_polarity, maybe_const }) + Ok(TraitBoundModifiers { constness, polarity }) } /// Parses a type bound according to: /// ```ebnf /// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN) - /// TY_BOUND_NOPAREN = [TY_BOUND_MODIFIERS] [for<LT_PARAM_DEFS>] SIMPLE_PATH + /// TY_BOUND_NOPAREN = [TRAIT_BOUND_MODIFIERS] [for<LT_PARAM_DEFS>] SIMPLE_PATH /// ``` /// /// For example, this grammar accepts `~const ?for<'a: 'b> m::Trait<'a>`. @@ -909,7 +890,7 @@ impl<'a> Parser<'a> { &mut self, lo: Span, has_parens: bool, - modifiers: BoundModifiers, + modifiers: TraitBoundModifiers, leading_token: &Token, ) -> PResult<'a, GenericBound> { let mut lifetime_defs = self.parse_late_bound_lifetime_defs()?; @@ -991,9 +972,8 @@ impl<'a> Parser<'a> { } } - let modifier = modifiers.to_trait_bound_modifier(); let poly_trait = PolyTraitRef::new(lifetime_defs, path, lo.to(self.prev_token.span)); - Ok(GenericBound::Trait(poly_trait, modifier)) + Ok(GenericBound::Trait(poly_trait, modifiers)) } // recovers a `Fn(..)` parenthesized-style path from `fn(..)` diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 8f8da211d31..856256a0641 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -6,8 +6,8 @@ use std::{ use crate::fluent_generated as fluent; use rustc_ast::Label; use rustc_errors::{ - error_code, AddToDiagnostic, Applicability, Diagnostic, DiagnosticSymbolList, ErrorGuaranteed, - IntoDiagnostic, MultiSpan, + error_code, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, + DiagnosticSymbolList, EmissionGuarantee, IntoDiagnostic, Level, MultiSpan, }; use rustc_hir::{self as hir, ExprKind, Target}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; @@ -863,13 +863,11 @@ pub struct ItemFollowingInnerAttr { pub kind: &'static str, } -impl IntoDiagnostic<'_> for InvalidAttrAtCrateLevel { +impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for InvalidAttrAtCrateLevel { #[track_caller] - fn into_diagnostic( - self, - dcx: &'_ rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::passes_invalid_attr_at_crate_level); + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = + DiagnosticBuilder::new(dcx, level, fluent::passes_invalid_attr_at_crate_level); diag.set_span(self.span); diag.set_arg("name", self.name); // Only emit an error with a suggestion if we can create a string out @@ -879,7 +877,7 @@ impl IntoDiagnostic<'_> for InvalidAttrAtCrateLevel { span, fluent::passes_suggestion, String::new(), - rustc_errors::Applicability::MachineApplicable, + Applicability::MachineApplicable, ); } if let Some(item) = self.item { @@ -1016,17 +1014,12 @@ pub struct BreakNonLoop<'a> { pub break_expr_span: Span, } -impl<'a> IntoDiagnostic<'_> for BreakNonLoop<'a> { +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'_, G> for BreakNonLoop<'a> { #[track_caller] - fn into_diagnostic( - self, - dcx: &rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_span_err_with_code( - self.span, - fluent::passes_break_non_loop, - error_code!(E0571), - ); + fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = DiagnosticBuilder::new(dcx, level, fluent::passes_break_non_loop); + diag.set_span(self.span); + diag.code(error_code!(E0571)); diag.set_arg("kind", self.kind); diag.span_label(self.span, fluent::passes_label); if let Some(head) = self.head { @@ -1165,17 +1158,12 @@ pub struct NakedFunctionsAsmBlock { pub non_asms: Vec<Span>, } -impl IntoDiagnostic<'_> for NakedFunctionsAsmBlock { +impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for NakedFunctionsAsmBlock { #[track_caller] - fn into_diagnostic( - self, - dcx: &rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_span_err_with_code( - self.span, - fluent::passes_naked_functions_asm_block, - error_code!(E0787), - ); + fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = DiagnosticBuilder::new(dcx, level, fluent::passes_naked_functions_asm_block); + diag.set_span(self.span); + diag.code(error_code!(E0787)); for span in self.multiple_asms.iter() { diag.span_label(*span, fluent::passes_label_multiple_asm); } @@ -1281,17 +1269,12 @@ pub struct NoMainErr { pub add_teach_note: bool, } -impl<'a> IntoDiagnostic<'a> for NoMainErr { +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for NoMainErr { #[track_caller] - fn into_diagnostic( - self, - dcx: &'a rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'a, ErrorGuaranteed> { - let mut diag = dcx.struct_span_err_with_code( - DUMMY_SP, - fluent::passes_no_main_function, - error_code!(E0601), - ); + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { + let mut diag = DiagnosticBuilder::new(dcx, level, fluent::passes_no_main_function); + diag.set_span(DUMMY_SP); + diag.code(error_code!(E0601)); diag.set_arg("crate_name", self.crate_name); diag.set_arg("filename", self.filename); diag.set_arg("has_filename", self.has_filename); @@ -1344,20 +1327,19 @@ pub struct DuplicateLangItem { pub(crate) duplicate: Duplicate, } -impl IntoDiagnostic<'_> for DuplicateLangItem { +impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for DuplicateLangItem { #[track_caller] - fn into_diagnostic( - self, - dcx: &rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err_with_code( + fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = DiagnosticBuilder::new( + dcx, + level, match self.duplicate { Duplicate::Plain => fluent::passes_duplicate_lang_item, Duplicate::Crate => fluent::passes_duplicate_lang_item_crate, Duplicate::CrateDepends => fluent::passes_duplicate_lang_item_crate_depends, }, - error_code!(E0152), ); + diag.code(error_code!(E0152)); diag.set_arg("lang_item_name", self.lang_item_name); diag.set_arg("crate_name", self.crate_name); diag.set_arg("dependency_of", self.dependency_of); diff --git a/compiler/rustc_pattern_analysis/Cargo.toml b/compiler/rustc_pattern_analysis/Cargo.toml index 908d00cf105..2152f9fda00 100644 --- a/compiler/rustc_pattern_analysis/Cargo.toml +++ b/compiler/rustc_pattern_analysis/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start +derivative = "2.2.0" rustc_apfloat = "0.2.0" rustc_arena = { path = "../rustc_arena", optional = true } rustc_data_structures = { path = "../rustc_data_structures", optional = true } diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs index af0a7497a34..b688051ca9c 100644 --- a/compiler/rustc_pattern_analysis/src/constructor.rs +++ b/compiler/rustc_pattern_analysis/src/constructor.rs @@ -642,7 +642,8 @@ impl OpaqueId { /// `specialize_constructor` returns the list of fields corresponding to a pattern, given a /// constructor. `Constructor::apply` reconstructs the pattern from a pair of `Constructor` and /// `Fields`. -#[derive(Clone, Debug, PartialEq)] +#[derive(derivative::Derivative)] +#[derivative(Debug(bound = ""), Clone(bound = ""), PartialEq(bound = ""))] pub enum Constructor<Cx: TypeCx> { /// Tuples and structs. Struct, diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index 785a60e9978..a1c9b157666 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -49,7 +49,7 @@ impl<'a, T: ?Sized> Captures<'a> for T {} /// Context that provides type information about constructors. /// /// Most of the crate is parameterized on a type that implements this trait. -pub trait TypeCx: Sized + Clone + fmt::Debug { +pub trait TypeCx: Sized + fmt::Debug { /// The type of a pattern. type Ty: Copy + Clone + fmt::Debug; // FIXME: remove Copy /// The index of an enum variant. @@ -58,11 +58,11 @@ pub trait TypeCx: Sized + Clone + fmt::Debug { type StrLit: Clone + PartialEq + fmt::Debug; /// Extra data to store in a match arm. type ArmData: Copy + Clone + fmt::Debug; - /// Extra data to store in a pattern. `Default` needed when we create fictitious wildcard - /// patterns during analysis. - type PatData: Clone + Default; + /// Extra data to store in a pattern. + type PatData: Clone; - fn is_opaque_ty(ty: Self::Ty) -> bool; + /// FIXME(Nadrieril): `Cx` should only give us revealed types. + fn reveal_opaque_ty(&self, ty: Self::Ty) -> Self::Ty; fn is_exhaustive_patterns_feature_on(&self) -> bool; /// The number of fields for this constructor. @@ -85,7 +85,8 @@ pub trait TypeCx: Sized + Clone + fmt::Debug { } /// Context that provides information global to a match. -#[derive(Clone)] +#[derive(derivative::Derivative)] +#[derivative(Clone(bound = ""), Copy(bound = ""))] pub struct MatchCtxt<'a, 'p, Cx: TypeCx> { /// The context for type information. pub tycx: &'a Cx, @@ -93,18 +94,16 @@ pub struct MatchCtxt<'a, 'p, Cx: TypeCx> { pub wildcard_arena: &'a TypedArena<DeconstructedPat<'p, Cx>>, } -impl<'a, 'p, Cx: TypeCx> Copy for MatchCtxt<'a, 'p, Cx> {} - /// The arm of a match expression. -#[derive(Clone, Debug)] +#[derive(Debug)] +#[derive(derivative::Derivative)] +#[derivative(Clone(bound = ""), Copy(bound = ""))] pub struct MatchArm<'p, Cx: TypeCx> { pub pat: &'p DeconstructedPat<'p, Cx>, pub has_guard: bool, pub arm_data: Cx::ArmData, } -impl<'p, Cx: TypeCx> Copy for MatchArm<'p, Cx> {} - /// The entrypoint for this crate. Computes whether a match is exhaustive and which of its arms are /// useful, and runs some lints. #[cfg(feature = "rustc")] diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs index 072ef4836a8..2be6e8e3db3 100644 --- a/compiler/rustc_pattern_analysis/src/lints.rs +++ b/compiler/rustc_pattern_analysis/src/lints.rs @@ -48,22 +48,14 @@ impl<'a, 'p, 'tcx> PatternColumn<'a, 'p, 'tcx> { fn is_empty(&self) -> bool { self.patterns.is_empty() } - fn head_ty(&self) -> Option<Ty<'tcx>> { + fn head_ty(&self, cx: MatchCtxt<'a, 'p, 'tcx>) -> Option<Ty<'tcx>> { if self.patterns.len() == 0 { return None; } - // If the type is opaque and it is revealed anywhere in the column, we take the revealed - // version. Otherwise we could encounter constructors for the revealed type and crash. - let first_ty = self.patterns[0].ty(); - if RustcMatchCheckCtxt::is_opaque_ty(first_ty) { - for pat in &self.patterns { - let ty = pat.ty(); - if !RustcMatchCheckCtxt::is_opaque_ty(ty) { - return Some(ty); - } - } - } - Some(first_ty) + + let ty = self.patterns[0].ty(); + // FIXME(Nadrieril): `Cx` should only give us revealed types. + Some(cx.tycx.reveal_opaque_ty(ty)) } /// Do constructor splitting on the constructors of the column. @@ -125,7 +117,7 @@ fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>( cx: MatchCtxt<'a, 'p, 'tcx>, column: &PatternColumn<'a, 'p, 'tcx>, ) -> Vec<WitnessPat<'p, 'tcx>> { - let Some(ty) = column.head_ty() else { + let Some(ty) = column.head_ty(cx) else { return Vec::new(); }; let pcx = &PlaceCtxt::new_dummy(cx, ty); @@ -211,7 +203,7 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>( }; use rustc_errors::DecorateLint; - let mut err = rcx.tcx.sess.struct_span_warn(*arm.pat.data(), ""); + let mut err = rcx.tcx.sess.struct_span_warn(*arm.pat.data().unwrap(), ""); err.set_primary_message(decorator.msg()); decorator.decorate_lint(&mut err); err.emit(); @@ -226,7 +218,7 @@ pub(crate) fn lint_overlapping_range_endpoints<'a, 'p, 'tcx>( cx: MatchCtxt<'a, 'p, 'tcx>, column: &PatternColumn<'a, 'p, 'tcx>, ) { - let Some(ty) = column.head_ty() else { + let Some(ty) = column.head_ty(cx) else { return; }; let pcx = &PlaceCtxt::new_dummy(cx, ty); @@ -261,8 +253,8 @@ pub(crate) fn lint_overlapping_range_endpoints<'a, 'p, 'tcx>( let mut suffixes: SmallVec<[_; 1]> = Default::default(); // Iterate on patterns that contained `overlap`. for pat in column.iter() { - let this_span = *pat.data(); let Constructor::IntRange(this_range) = pat.ctor() else { continue }; + let this_span = *pat.data().unwrap(); if this_range.is_singleton() { // Don't lint when one of the ranges is a singleton. continue; diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs index 0cc8477b7cd..9efd3e864da 100644 --- a/compiler/rustc_pattern_analysis/src/pat.rs +++ b/compiler/rustc_pattern_analysis/src/pat.rs @@ -26,14 +26,16 @@ pub struct DeconstructedPat<'p, Cx: TypeCx> { ctor: Constructor<Cx>, fields: &'p [DeconstructedPat<'p, Cx>], ty: Cx::Ty, - data: Cx::PatData, + /// Extra data to store in a pattern. `None` if the pattern is a wildcard that does not + /// correspond to a user-supplied pattern. + data: Option<Cx::PatData>, /// Whether removing this arm would change the behavior of the match expression. useful: Cell<bool>, } impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> { - pub fn wildcard(ty: Cx::Ty, data: Cx::PatData) -> Self { - Self::new(Wildcard, &[], ty, data) + pub fn wildcard(ty: Cx::Ty) -> Self { + DeconstructedPat { ctor: Wildcard, fields: &[], ty, data: None, useful: Cell::new(false) } } pub fn new( @@ -42,7 +44,7 @@ impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> { ty: Cx::Ty, data: Cx::PatData, ) -> Self { - DeconstructedPat { ctor, fields, ty, data, useful: Cell::new(false) } + DeconstructedPat { ctor, fields, ty, data: Some(data), useful: Cell::new(false) } } pub(crate) fn is_or_pat(&self) -> bool { @@ -63,8 +65,10 @@ impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> { pub fn ty(&self) -> Cx::Ty { self.ty } - pub fn data(&self) -> &Cx::PatData { - &self.data + /// Returns the extra data stored in a pattern. Returns `None` if the pattern is a wildcard that + /// does not correspond to a user-supplied pattern. + pub fn data(&self) -> Option<&Cx::PatData> { + self.data.as_ref() } pub fn iter_fields<'a>( @@ -83,7 +87,7 @@ impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> { let wildcard_sub_tys = || { let tys = pcx.ctor_sub_tys(other_ctor); tys.iter() - .map(|ty| DeconstructedPat::wildcard(*ty, Cx::PatData::default())) + .map(|ty| DeconstructedPat::wildcard(*ty)) .map(|pat| pcx.mcx.wildcard_arena.alloc(pat) as &_) .collect() }; @@ -160,7 +164,8 @@ impl<'p, Cx: TypeCx> fmt::Debug for DeconstructedPat<'p, Cx> { /// Same idea as `DeconstructedPat`, except this is a fictitious pattern built up for diagnostics /// purposes. As such they don't use interning and can be cloned. -#[derive(Debug, Clone)] +#[derive(derivative::Derivative)] +#[derivative(Debug(bound = ""), Clone(bound = ""))] pub struct WitnessPat<Cx: TypeCx> { ctor: Constructor<Cx>, pub(crate) fields: Vec<WitnessPat<Cx>>, diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 65c90aa9f1d..a5a47724f3f 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -12,7 +12,7 @@ use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::{self, Const}; use rustc_middle::thir::{FieldPat, Pat, PatKind, PatRange, PatRangeBoundary}; use rustc_middle::ty::layout::IntegerExt; -use rustc_middle::ty::{self, Ty, TyCtxt, VariantDef}; +use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, VariantDef}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{FieldIdx, Integer, VariantIdx, FIRST_VARIANT}; use smallvec::SmallVec; @@ -44,6 +44,7 @@ pub type WitnessPat<'p, 'tcx> = crate::pat::WitnessPat<RustcMatchCheckCtxt<'p, ' #[derive(Clone)] pub struct RustcMatchCheckCtxt<'p, 'tcx> { pub tcx: TyCtxt<'tcx>, + pub typeck_results: &'tcx ty::TypeckResults<'tcx>, /// The module in which the match occurs. This is necessary for /// checking inhabited-ness of types because whether a type is (visibly) /// inhabited can depend on whether it was defined in the current module or @@ -73,8 +74,16 @@ impl<'p, 'tcx> fmt::Debug for RustcMatchCheckCtxt<'p, 'tcx> { } impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { - pub(crate) fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool { - !ty.is_inhabited_from(self.tcx, self.module, self.param_env) + fn reveal_opaque(&self, key: OpaqueTypeKey<'tcx>) -> Option<Ty<'tcx>> { + self.typeck_results.concrete_opaque_types.get(&key).map(|x| x.ty) + } + pub fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool { + !ty.inhabited_predicate(self.tcx).apply_revealing_opaque( + self.tcx, + self.param_env, + self.module, + &|key| self.reveal_opaque(key), + ) } /// Returns whether the given type is an enum from another crate declared `#[non_exhaustive]`. @@ -101,6 +110,21 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { } } + /// Type inference occasionally gives us opaque types in places where corresponding patterns + /// have more specific types. To avoid inconsistencies as well as detect opaque uninhabited + /// types, we use the corresponding concrete type if possible. + fn reveal_opaque_ty(&self, ty: Ty<'tcx>) -> Ty<'tcx> { + if let ty::Alias(ty::Opaque, alias_ty) = ty.kind() { + if let Some(local_def_id) = alias_ty.def_id.as_local() { + let key = ty::OpaqueTypeKey { def_id: local_def_id, args: alias_ty.args }; + if let Some(real_ty) = self.typeck_results.concrete_opaque_types.get(&key) { + return real_ty.ty; + } + } + } + ty + } + // In the cases of either a `#[non_exhaustive]` field list or a non-public field, we hide // uninhabited fields in order not to reveal the uninhabitedness of the whole variant. // This lists the fields we keep along with their types. @@ -303,7 +327,9 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { let is_inhabited = v .inhabited_predicate(cx.tcx, *def) .instantiate(cx.tcx, args) - .apply(cx.tcx, cx.param_env, cx.module); + .apply_revealing_opaque(cx.tcx, cx.param_env, cx.module, &|key| { + cx.reveal_opaque(key) + }); // Variants that depend on a disabled unstable feature. let is_unstable = matches!( cx.tcx.eval_stability(variant_def_id, None, DUMMY_SP, None), @@ -400,7 +426,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { ty::Tuple(fs) => { ctor = Struct; let mut wilds: SmallVec<[_; 2]> = - fs.iter().map(|ty| DeconstructedPat::wildcard(ty, pat.span)).collect(); + fs.iter().map(|ty| DeconstructedPat::wildcard(ty)).collect(); for pat in subpatterns { wilds[pat.field.index()] = self.lower_pat(&pat.pattern); } @@ -423,7 +449,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { let pat = if let Some(pat) = pattern { self.lower_pat(&pat.pattern) } else { - DeconstructedPat::wildcard(args.type_at(0), pat.span) + DeconstructedPat::wildcard(args.type_at(0)) }; ctor = Struct; fields = singleton(pat); @@ -448,7 +474,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { ty }); let mut wilds: SmallVec<[_; 2]> = - tys.map(|ty| DeconstructedPat::wildcard(ty, pat.span)).collect(); + tys.map(|ty| DeconstructedPat::wildcard(ty)).collect(); for pat in subpatterns { if let Some(i) = field_id_to_id[pat.field.index()] { wilds[i] = self.lower_pat(&pat.pattern); @@ -873,8 +899,9 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { fn is_exhaustive_patterns_feature_on(&self) -> bool { self.tcx.features().exhaustive_patterns } - fn is_opaque_ty(ty: Self::Ty) -> bool { - matches!(ty.kind(), ty::Alias(ty::Opaque, ..)) + + fn reveal_opaque_ty(&self, ty: Ty<'tcx>) -> Ty<'tcx> { + self.reveal_opaque_ty(ty) } fn ctor_arity(&self, ctor: &crate::constructor::Constructor<Self>, ty: Self::Ty) -> usize { diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index 6b1de807797..b51b1a1f722 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -300,6 +300,166 @@ //! //! //! +//! # `Missing` and relevancy +//! +//! ## Relevant values +//! +//! Take the following example: +//! +//! ```compile_fail,E0004 +//! # let foo = (true, true); +//! match foo { +//! (true, _) => 1, +//! (_, true) => 2, +//! }; +//! ``` +//! +//! Consider the value `(true, true)`: +//! - Row 2 does not distinguish `(true, true)` and `(false, true)`; +//! - `false` does not show up in the first column of the match, so without knowing anything else we +//! can deduce that `(false, true)` matches the same or fewer rows than `(true, true)`. +//! +//! Using those two facts together, we deduce that `(true, true)` will not give us more usefulness +//! information about row 2 than `(false, true)` would. We say that "`(true, true)` is made +//! irrelevant for row 2 by `(false, true)`". We will use this idea to prune the search tree. +//! +//! +//! ## Computing relevancy +//! +//! We now generalize from the above example to approximate relevancy in a simple way. Note that we +//! will only compute an approximation: we can sometimes determine when a case is irrelevant, but +//! computing this precisely is at least as hard as computing usefulness. +//! +//! Our computation of relevancy relies on the `Missing` constructor. As explained in +//! [`crate::constructor`], `Missing` represents the constructors not present in a given column. For +//! example in the following: +//! +//! ```compile_fail,E0004 +//! enum Direction { North, South, East, West } +//! # let wind = (Direction::North, 0u8); +//! match wind { +//! (Direction::North, _) => 1, +//! (_, 50..) => 2, +//! }; +//! ``` +//! +//! Here `South`, `East` and `West` are missing in the first column, and `0..50` is missing in the +//! second. Both of these sets are represented by `Constructor::Missing` in their corresponding +//! column. +//! +//! We then compute relevancy as follows: during the course of the algorithm, for a row `r`: +//! - if `r` has a wildcard in the first column; +//! - and some constructors are missing in that column; +//! - then any `c != Missing` is considered irrelevant for row `r`. +//! +//! By this we mean that continuing the algorithm by specializing with `c` is guaranteed not to +//! contribute more information about the usefulness of row `r` than what we would get by +//! specializing with `Missing`. The argument is the same as in the previous subsection. +//! +//! Once we've specialized by a constructor `c` that is irrelevant for row `r`, we're guaranteed to +//! only explore values irrelevant for `r`. If we then ever reach a point where we're only exploring +//! values that are irrelevant to all of the rows (including the virtual wildcard row used for +//! exhaustiveness), we skip that case entirely. +//! +//! +//! ## Example +//! +//! Let's go through a variation on the first example: +//! +//! ```compile_fail,E0004 +//! # let foo = (true, true, true); +//! match foo { +//! (true, _, true) => 1, +//! (_, true, _) => 2, +//! }; +//! ``` +//! +//! ```text +//! ┐ Patterns: +//! │ 1. `[(true, _, true)]` +//! │ 2. `[(_, true, _)]` +//! │ 3. `[_]` // virtual extra wildcard row +//! │ +//! │ Specialize with `(,,)`: +//! ├─┐ Patterns: +//! │ │ 1. `[true, _, true]` +//! │ │ 2. `[_, true, _]` +//! │ │ 3. `[_, _, _]` +//! │ │ +//! │ │ There are missing constructors in the first column (namely `false`), hence +//! │ │ `true` is irrelevant for rows 2 and 3. +//! │ │ +//! │ │ Specialize with `true`: +//! │ ├─┐ Patterns: +//! │ │ │ 1. `[_, true]` +//! │ │ │ 2. `[true, _]` // now exploring irrelevant cases +//! │ │ │ 3. `[_, _]` // now exploring irrelevant cases +//! │ │ │ +//! │ │ │ There are missing constructors in the first column (namely `false`), hence +//! │ │ │ `true` is irrelevant for rows 1 and 3. +//! │ │ │ +//! │ │ │ Specialize with `true`: +//! │ │ ├─┐ Patterns: +//! │ │ │ │ 1. `[true]` // now exploring irrelevant cases +//! │ │ │ │ 2. `[_]` // now exploring irrelevant cases +//! │ │ │ │ 3. `[_]` // now exploring irrelevant cases +//! │ │ │ │ +//! │ │ │ │ The current case is irrelevant for all rows: we backtrack immediately. +//! │ │ ├─┘ +//! │ │ │ +//! │ │ │ Specialize with `false`: +//! │ │ ├─┐ Patterns: +//! │ │ │ │ 1. `[true]` +//! │ │ │ │ 3. `[_]` // now exploring irrelevant cases +//! │ │ │ │ +//! │ │ │ │ Specialize with `true`: +//! │ │ │ ├─┐ Patterns: +//! │ │ │ │ │ 1. `[]` +//! │ │ │ │ │ 3. `[]` // now exploring irrelevant cases +//! │ │ │ │ │ +//! │ │ │ │ │ Row 1 is therefore useful. +//! │ │ │ ├─┘ +//! <etc...> +//! ``` +//! +//! Relevancy allowed us to skip the case `(true, true, _)` entirely. In some cases this pruning can +//! give drastic speedups. The case this was built for is the following (#118437): +//! +//! ```ignore(illustrative) +//! match foo { +//! (true, _, _, _, ..) => 1, +//! (_, true, _, _, ..) => 2, +//! (_, _, true, _, ..) => 3, +//! (_, _, _, true, ..) => 4, +//! ... +//! } +//! ``` +//! +//! Without considering relevancy, we would explore all 2^n combinations of the `true` and `Missing` +//! constructors. Relevancy tells us that e.g. `(true, true, false, false, false, ...)` is +//! irrelevant for all the rows. This allows us to skip all cases with more than one `true` +//! constructor, changing the runtime from exponential to linear. +//! +//! +//! ## Relevancy and exhaustiveness +//! +//! For exhaustiveness, we do something slightly different w.r.t relevancy: we do not report +//! witnesses of non-exhaustiveness that are irrelevant for the virtual wildcard row. For example, +//! in: +//! +//! ```ignore(illustrative) +//! match foo { +//! (true, true) => {} +//! } +//! ``` +//! +//! we only report `(false, _)` as missing. This was a deliberate choice made early in the +//! development of rust, for diagnostic and performance purposes. As showed in the previous section, +//! ignoring irrelevant cases preserves usefulness, so this choice still correctly computes whether +//! a match is exhaustive. +//! +//! +//! //! # Or-patterns //! //! What we have described so far works well if there are no or-patterns. To handle them, if the @@ -569,8 +729,10 @@ pub fn ensure_sufficient_stack<R>(f: impl FnOnce() -> R) -> R { } /// Context that provides information local to a place under investigation. -#[derive(Clone)] +#[derive(derivative::Derivative)] +#[derivative(Debug(bound = ""), Clone(bound = ""), Copy(bound = ""))] pub(crate) struct PlaceCtxt<'a, 'p, Cx: TypeCx> { + #[derivative(Debug = "ignore")] pub(crate) mcx: MatchCtxt<'a, 'p, Cx>, /// Type of the place under investigation. pub(crate) ty: Cx::Ty, @@ -596,14 +758,6 @@ impl<'a, 'p, Cx: TypeCx> PlaceCtxt<'a, 'p, Cx> { } } -impl<'a, 'p, Cx: TypeCx> Copy for PlaceCtxt<'a, 'p, Cx> {} - -impl<'a, 'p, Cx: TypeCx> fmt::Debug for PlaceCtxt<'a, 'p, Cx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("PlaceCtxt").field("ty", &self.ty).finish() - } -} - /// Serves two purposes: /// - in a wildcard, tracks whether the wildcard matches only valid values (i.e. is a binding `_a`) /// or also invalid values (i.e. is a true `_` pattern). @@ -670,15 +824,20 @@ impl fmt::Display for ValidityConstraint { // - 'a allocated by us // - 'p coming from the input // - Cx global compilation context -#[derive(Clone)] +#[derive(derivative::Derivative)] +#[derivative(Clone(bound = ""))] struct PatStack<'a, 'p, Cx: TypeCx> { // Rows of len 1 are very common, which is why `SmallVec[_; 2]` works well. pats: SmallVec<[&'a DeconstructedPat<'p, Cx>; 2]>, + /// Sometimes we know that as far as this row is concerned, the current case is already handled + /// by a different, more general, case. When the case is irrelevant for all rows this allows us + /// to skip a case entirely. This is purely an optimization. See at the top for details. + relevant: bool, } impl<'a, 'p, Cx: TypeCx> PatStack<'a, 'p, Cx> { fn from_pattern(pat: &'a DeconstructedPat<'p, Cx>) -> Self { - PatStack { pats: smallvec![pat] } + PatStack { pats: smallvec![pat], relevant: true } } fn is_empty(&self) -> bool { @@ -713,12 +872,17 @@ impl<'a, 'p, Cx: TypeCx> PatStack<'a, 'p, Cx> { &self, pcx: &PlaceCtxt<'a, 'p, Cx>, ctor: &Constructor<Cx>, + ctor_is_relevant: bool, ) -> PatStack<'a, 'p, Cx> { // We pop the head pattern and push the new fields extracted from the arguments of // `self.head()`. let mut new_pats = self.head().specialize(pcx, ctor); new_pats.extend_from_slice(&self.pats[1..]); - PatStack { pats: new_pats } + // `ctor` is relevant for this row if it is the actual constructor of this row, or if the + // row has a wildcard and `ctor` is relevant for wildcards. + let ctor_is_relevant = + !matches!(self.head().ctor(), Constructor::Wildcard) || ctor_is_relevant; + PatStack { pats: new_pats, relevant: self.relevant && ctor_is_relevant } } } @@ -784,10 +948,11 @@ impl<'a, 'p, Cx: TypeCx> MatrixRow<'a, 'p, Cx> { &self, pcx: &PlaceCtxt<'a, 'p, Cx>, ctor: &Constructor<Cx>, + ctor_is_relevant: bool, parent_row: usize, ) -> MatrixRow<'a, 'p, Cx> { MatrixRow { - pats: self.pats.pop_head_constructor(pcx, ctor), + pats: self.pats.pop_head_constructor(pcx, ctor, ctor_is_relevant), parent_row, is_under_guard: self.is_under_guard, useful: false, @@ -845,8 +1010,7 @@ impl<'a, 'p, Cx: TypeCx> Matrix<'a, 'p, Cx> { scrut_ty: Cx::Ty, scrut_validity: ValidityConstraint, ) -> Self { - let wild_pattern = - wildcard_arena.alloc(DeconstructedPat::wildcard(scrut_ty, Default::default())); + let wild_pattern = wildcard_arena.alloc(DeconstructedPat::wildcard(scrut_ty)); let wildcard_row = PatStack::from_pattern(wild_pattern); let mut matrix = Matrix { rows: Vec::with_capacity(arms.len()), @@ -865,24 +1029,14 @@ impl<'a, 'p, Cx: TypeCx> Matrix<'a, 'p, Cx> { matrix } - fn head_ty(&self) -> Option<Cx::Ty> { + fn head_ty(&self, mcx: MatchCtxt<'a, 'p, Cx>) -> Option<Cx::Ty> { if self.column_count() == 0 { return None; } - let mut ty = self.wildcard_row.head().ty(); - // If the type is opaque and it is revealed anywhere in the column, we take the revealed - // version. Otherwise we could encounter constructors for the revealed type and crash. - if Cx::is_opaque_ty(ty) { - for pat in self.heads() { - let pat_ty = pat.ty(); - if !Cx::is_opaque_ty(pat_ty) { - ty = pat_ty; - break; - } - } - } - Some(ty) + let ty = self.wildcard_row.head().ty(); + // FIXME(Nadrieril): `Cx` should only give us revealed types. + Some(mcx.tycx.reveal_opaque_ty(ty)) } fn column_count(&self) -> usize { self.wildcard_row.len() @@ -913,8 +1067,9 @@ impl<'a, 'p, Cx: TypeCx> Matrix<'a, 'p, Cx> { &self, pcx: &PlaceCtxt<'a, 'p, Cx>, ctor: &Constructor<Cx>, + ctor_is_relevant: bool, ) -> Matrix<'a, 'p, Cx> { - let wildcard_row = self.wildcard_row.pop_head_constructor(pcx, ctor); + let wildcard_row = self.wildcard_row.pop_head_constructor(pcx, ctor, ctor_is_relevant); let new_validity = self.place_validity[0].specialize(ctor); let new_place_validity = std::iter::repeat(new_validity) .take(ctor.arity(pcx)) @@ -924,7 +1079,7 @@ impl<'a, 'p, Cx: TypeCx> Matrix<'a, 'p, Cx> { Matrix { rows: Vec::new(), wildcard_row, place_validity: new_place_validity }; for (i, row) in self.rows().enumerate() { if ctor.is_covered_by(pcx, row.head().ctor()) { - let new_row = row.pop_head_constructor(pcx, ctor, i); + let new_row = row.pop_head_constructor(pcx, ctor, ctor_is_relevant, i); matrix.expand_and_push(new_row); } } @@ -1032,7 +1187,8 @@ impl<'a, 'p, Cx: TypeCx> fmt::Debug for Matrix<'a, 'p, Cx> { /// The final `Pair(Some(_), true)` is then the resulting witness. /// /// See the top of the file for more detailed explanations and examples. -#[derive(Debug, Clone)] +#[derive(derivative::Derivative)] +#[derivative(Debug(bound = ""), Clone(bound = ""))] struct WitnessStack<Cx: TypeCx>(Vec<WitnessPat<Cx>>); impl<Cx: TypeCx> WitnessStack<Cx> { @@ -1079,7 +1235,8 @@ impl<Cx: TypeCx> WitnessStack<Cx> { /// /// Just as the `Matrix` starts with a single column, by the end of the algorithm, this has a single /// column, which contains the patterns that are missing for the match to be exhaustive. -#[derive(Debug, Clone)] +#[derive(derivative::Derivative)] +#[derivative(Debug(bound = ""), Clone(bound = ""))] struct WitnessMatrix<Cx: TypeCx>(Vec<WitnessStack<Cx>>); impl<Cx: TypeCx> WitnessMatrix<Cx> { @@ -1122,7 +1279,10 @@ impl<Cx: TypeCx> WitnessMatrix<Cx> { if matches!(ctor, Constructor::Missing) { // We got the special `Missing` constructor that stands for the constructors not present // in the match. - if !report_individual_missing_ctors { + if missing_ctors.is_empty() { + // Nothing to report. + *self = Self::empty(); + } else if !report_individual_missing_ctors { // Report `_` as missing. let pat = WitnessPat::wild_from_ctor(pcx, Constructor::Wildcard); self.push_pattern(pat); @@ -1181,7 +1341,14 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( ) -> WitnessMatrix<Cx> { debug_assert!(matrix.rows().all(|r| r.len() == matrix.column_count())); - let Some(ty) = matrix.head_ty() else { + if !matrix.wildcard_row.relevant && matrix.rows().all(|r| !r.pats.relevant) { + // Here we know that nothing will contribute further to exhaustiveness or usefulness. This + // is purely an optimization: skipping this check doesn't affect correctness. See the top of + // the file for details. + return WitnessMatrix::empty(); + } + + let Some(ty) = matrix.head_ty(mcx) else { // The base case: there are no columns in the matrix. We are morally pattern-matching on (). // A row is useful iff it has no (unguarded) rows above it. for row in matrix.rows_mut() { @@ -1193,8 +1360,14 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( return WitnessMatrix::empty(); } } - // No (unguarded) rows, so the match is not exhaustive. We return a new witness. - return WitnessMatrix::unit_witness(); + // No (unguarded) rows, so the match is not exhaustive. We return a new witness unless + // irrelevant. + return if matrix.wildcard_row.relevant { + WitnessMatrix::unit_witness() + } else { + // We choose to not report anything here; see at the top for details. + WitnessMatrix::empty() + }; }; debug!("ty: {ty:?}"); @@ -1237,32 +1410,21 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( let mut ret = WitnessMatrix::empty(); for ctor in split_ctors { - debug!("specialize({:?})", ctor); // Dig into rows that match `ctor`. - let mut spec_matrix = matrix.specialize_constructor(pcx, &ctor); + debug!("specialize({:?})", ctor); + // `ctor` is *irrelevant* if there's another constructor in `split_ctors` that matches + // strictly fewer rows. In that case we can sometimes skip it. See the top of the file for + // details. + let ctor_is_relevant = matches!(ctor, Constructor::Missing) || missing_ctors.is_empty(); + let mut spec_matrix = matrix.specialize_constructor(pcx, &ctor, ctor_is_relevant); let mut witnesses = ensure_sufficient_stack(|| { compute_exhaustiveness_and_usefulness(mcx, &mut spec_matrix, false) }); - let counts_for_exhaustiveness = match ctor { - Constructor::Missing => !missing_ctors.is_empty(), - // If there are missing constructors we'll report those instead. Since `Missing` matches - // only the wildcard rows, it matches fewer rows than this constructor, and is therefore - // guaranteed to result in the same or more witnesses. So skipping this does not - // jeopardize correctness. - _ => missing_ctors.is_empty(), - }; - if counts_for_exhaustiveness { - // Transform witnesses for `spec_matrix` into witnesses for `matrix`. - witnesses.apply_constructor( - pcx, - &missing_ctors, - &ctor, - report_individual_missing_ctors, - ); - // Accumulate the found witnesses. - ret.extend(witnesses); - } + // Transform witnesses for `spec_matrix` into witnesses for `matrix`. + witnesses.apply_constructor(pcx, &missing_ctors, &ctor, report_individual_missing_ctors); + // Accumulate the found witnesses. + ret.extend(witnesses); // A parent row is useful if any of its children is. for child_row in spec_matrix.rows() { diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index 2a34ffb75f2..982b9ee94da 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -4,9 +4,7 @@ use crate::query::plumbing::CycleError; use crate::query::DepKind; use crate::query::{QueryContext, QueryStackFrame}; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{ - DiagCtxt, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, Level, -}; +use rustc_errors::{DiagCtxt, Diagnostic, DiagnosticBuilder, Level}; use rustc_hir::def::DefKind; use rustc_session::Session; use rustc_span::Span; @@ -561,7 +559,7 @@ pub fn deadlock(query_map: QueryMap, registry: &rayon_core::Registry) { pub(crate) fn report_cycle<'a>( sess: &'a Session, CycleError { usage, cycle: stack }: &CycleError, -) -> DiagnosticBuilder<'a, ErrorGuaranteed> { +) -> DiagnosticBuilder<'a> { assert!(!stack.is_empty()); let span = stack[0].query.default_span(stack[1 % stack.len()].span); @@ -604,7 +602,7 @@ pub(crate) fn report_cycle<'a>( note_span: (), }; - cycle_diag.into_diagnostic(sess.dcx()) + sess.dcx().create_err(cycle_diag) } pub fn print_query_stack<Qcx: QueryContext>( diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 41638b38c74..3e29574c871 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -19,7 +19,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::sync::Lock; #[cfg(parallel_compiler)] use rustc_data_structures::{outline, sync}; -use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, FatalError, StashKey}; +use rustc_errors::{DiagnosticBuilder, FatalError, StashKey}; use rustc_span::{Span, DUMMY_SP}; use std::cell::Cell; use std::collections::hash_map::Entry; @@ -112,7 +112,7 @@ fn handle_cycle_error<Q, Qcx>( query: Q, qcx: Qcx, cycle_error: &CycleError, - mut error: DiagnosticBuilder<'_, ErrorGuaranteed>, + mut error: DiagnosticBuilder<'_>, ) -> Q::Value where Q: QueryConfig<Qcx>, diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 542aff69e34..af0c5b56d73 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -551,7 +551,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, span: Span, resolution_error: ResolutionError<'a>, - ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'_> { match resolution_error { ResolutionError::GenericParamsFromOuterItem(outer_res, has_generic_params) => { use errs::GenericParamsFromOuterItemLabel as Label; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index cf50f630bf2..4bef67be3ef 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3693,7 +3693,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { let mut parent_err = this.r.into_struct_error(parent_err.span, parent_err.node); // overwrite all properties with the parent's error message - err.message = take(&mut parent_err.message); + err.messages = take(&mut parent_err.messages); err.code = take(&mut parent_err.code); swap(&mut err.span, &mut parent_err.span); err.children = take(&mut parent_err.children); @@ -4258,11 +4258,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { }); } - ExprKind::ForLoop(ref pat, ref iter_expr, ref block, label) => { - self.visit_expr(iter_expr); + ExprKind::ForLoop { ref pat, ref iter, ref body, label, kind: _ } => { + self.visit_expr(iter); self.with_rib(ValueNS, RibKind::Normal, |this| { this.resolve_pattern_top(pat, PatternSource::For); - this.resolve_labeled_block(label, expr.id, block); + this.resolve_labeled_block(label, expr.id, body); }); } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index d767ed74139..e410e76abf4 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -424,7 +424,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { span: Span, source: PathSource<'_>, res: Option<Res>, - ) -> (DiagnosticBuilder<'tcx, ErrorGuaranteed>, Vec<ImportSuggestion>) { + ) -> (DiagnosticBuilder<'tcx>, Vec<ImportSuggestion>) { debug!(?res, ?source); let base_error = self.make_base_error(path, span, source, res); @@ -520,7 +520,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { continue; }; for bound in bounds { - let ast::GenericBound::Trait(trait_ref, ast::TraitBoundModifier::None) = bound + let ast::GenericBound::Trait(trait_ref, ast::TraitBoundModifiers::NONE) = bound else { continue; }; @@ -1242,7 +1242,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } if let ( [ast::PathSegment { args: None, .. }], - [ast::GenericBound::Trait(poly_trait_ref, ast::TraitBoundModifier::None)], + [ast::GenericBound::Trait(poly_trait_ref, ast::TraitBoundModifiers::NONE)], ) = (&type_param_path.segments[..], &bounds[..]) { if let [ast::PathSegment { ident, args: None, .. }] = @@ -1409,7 +1409,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { | ExprKind::Unary(..) | ExprKind::If(..) | ExprKind::While(..) - | ExprKind::ForLoop(..) + | ExprKind::ForLoop { .. } | ExprKind::Match(..), .. }), @@ -3276,7 +3276,7 @@ fn mk_where_bound_predicate( }, span: DUMMY_SP, }, - ast::TraitBoundModifier::None, + ast::TraitBoundModifiers::NONE, )], }; diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 75ec594eb9b..a14f3d494fb 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -37,7 +37,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::intern::Interned; use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::{FreezeReadGuard, Lrc}; -use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed}; +use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_expand::base::{DeriveResolutions, SyntaxExtension, SyntaxExtensionKind}; use rustc_feature::BUILTIN_ATTRIBUTES; use rustc_hir::def::Namespace::{self, *}; @@ -704,7 +704,7 @@ struct PrivacyError<'a> { #[derive(Debug)] struct UseError<'a> { - err: DiagnosticBuilder<'a, ErrorGuaranteed>, + err: DiagnosticBuilder<'a>, /// Candidates which user could `use` to access the missing type. candidates: Vec<ImportSuggestion>, /// The `DefId` of the module to place the use-statements in. diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 0c21e4eb43e..0d731e330f3 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1594,7 +1594,7 @@ pub(super) fn build_target_config( |t| Ok((t, TargetWarnings::empty())), ); let (target, target_warnings) = target_result.unwrap_or_else(|e| { - early_dcx.early_error(format!( + early_dcx.early_fatal(format!( "Error loading target specification: {e}. \ Run `rustc --print target-list` for a list of built-in targets" )) @@ -1604,7 +1604,7 @@ pub(super) fn build_target_config( } if !matches!(target.pointer_width, 16 | 32 | 64) { - early_dcx.early_error(format!( + early_dcx.early_fatal(format!( "target specification was invalid: unrecognized target-pointer-width {}", target.pointer_width )) @@ -1869,7 +1869,7 @@ pub fn get_cmd_lint_options( let lint_cap = matches.opt_str("cap-lints").map(|cap| { lint::Level::from_str(&cap) - .unwrap_or_else(|| early_dcx.early_error(format!("unknown lint level: `{cap}`"))) + .unwrap_or_else(|| early_dcx.early_fatal(format!("unknown lint level: `{cap}`"))) }); (lint_opts, describe_lints, lint_cap) @@ -1884,7 +1884,7 @@ pub fn parse_color(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> Col None => ColorConfig::Auto, - Some(arg) => early_dcx.early_error(format!( + Some(arg) => early_dcx.early_fatal(format!( "argument for `--color` must be auto, \ always or never (instead was `{arg}`)" )), @@ -1942,7 +1942,7 @@ pub fn parse_json(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> Json // won't actually be emitting any colors and anything colorized is // embedded in a diagnostic message anyway. if matches.opt_str("color").is_some() { - early_dcx.early_error("cannot specify the `--color` option with `--json`"); + early_dcx.early_fatal("cannot specify the `--color` option with `--json`"); } for sub_option in option.split(',') { @@ -1953,7 +1953,7 @@ pub fn parse_json(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> Json "unused-externs" => json_unused_externs = JsonUnusedExterns::Loud, "unused-externs-silent" => json_unused_externs = JsonUnusedExterns::Silent, "future-incompat" => json_future_incompat = true, - s => early_dcx.early_error(format!("unknown `--json` option `{s}`")), + s => early_dcx.early_fatal(format!("unknown `--json` option `{s}`")), } } } @@ -1993,7 +1993,7 @@ pub fn parse_error_format( early_dcx.abort_if_error_and_set_error_format(ErrorOutputType::HumanReadable( HumanReadableErrorType::Default(color), )); - early_dcx.early_error(format!( + early_dcx.early_fatal(format!( "argument for `--error-format` must be `human`, `json` or \ `short` (instead was `{arg}`)" )) @@ -2010,7 +2010,7 @@ pub fn parse_error_format( // `--error-format=json`. This means that `--json` is specified we // should actually be emitting JSON blobs. _ if !matches.opt_strs("json").is_empty() => { - early_dcx.early_error("using `--json` requires also using `--error-format=json`"); + early_dcx.early_fatal("using `--json` requires also using `--error-format=json`"); } _ => {} @@ -2022,7 +2022,7 @@ pub fn parse_error_format( pub fn parse_crate_edition(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> Edition { let edition = match matches.opt_str("edition") { Some(arg) => Edition::from_str(&arg).unwrap_or_else(|_| { - early_dcx.early_error(format!( + early_dcx.early_fatal(format!( "argument for `--edition` must be one of: \ {EDITION_NAME_LIST}. (instead was `{arg}`)" )) @@ -2039,7 +2039,7 @@ pub fn parse_crate_edition(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches } else { format!("edition {edition} is unstable and only available with -Z unstable-options") }; - early_dcx.early_error(msg) + early_dcx.early_fatal(msg) } edition @@ -2057,7 +2057,7 @@ fn check_error_format_stability( pretty: false, json_rendered, }); - early_dcx.early_error("`--error-format=pretty-json` is unstable"); + early_dcx.early_fatal("`--error-format=pretty-json` is unstable"); } if let ErrorOutputType::HumanReadable(HumanReadableErrorType::AnnotateSnippet(_)) = error_format @@ -2066,7 +2066,7 @@ fn check_error_format_stability( pretty: false, json_rendered, }); - early_dcx.early_error("`--error-format=human-annotate-rs` is unstable"); + early_dcx.early_fatal("`--error-format=human-annotate-rs` is unstable"); } } } @@ -2082,7 +2082,7 @@ fn parse_output_types( for output_type in list.split(',') { let (shorthand, path) = split_out_file_name(output_type); let output_type = OutputType::from_shorthand(shorthand).unwrap_or_else(|| { - early_dcx.early_error(format!( + early_dcx.early_fatal(format!( "unknown emission type: `{shorthand}` - expected one of: {display}", display = OutputType::shorthands_display(), )) @@ -2144,7 +2144,7 @@ fn should_override_cgus_and_disable_thinlto( } if codegen_units == Some(0) { - early_dcx.early_error("value for codegen units must be a positive non-zero integer"); + early_dcx.early_fatal("value for codegen units must be a positive non-zero integer"); } (disable_local_thinlto, codegen_units) @@ -2204,7 +2204,7 @@ fn collect_print_requests( if unstable_opts.unstable_options { PrintKind::TargetSpec } else { - early_dcx.early_error( + early_dcx.early_fatal( "the `-Z unstable-options` flag must also be passed to \ enable the target-spec-json print option", ); @@ -2214,7 +2214,7 @@ fn collect_print_requests( if unstable_opts.unstable_options { PrintKind::AllTargetSpecs } else { - early_dcx.early_error( + early_dcx.early_fatal( "the `-Z unstable-options` flag must also be passed to \ enable the all-target-specs-json print option", ); @@ -2225,7 +2225,7 @@ fn collect_print_requests( let prints = PRINT_KINDS.iter().map(|(name, _)| format!("`{name}`")).collect::<Vec<_>>(); let prints = prints.join(", "); - early_dcx.early_error(format!( + early_dcx.early_fatal(format!( "unknown print request `{req}`. Valid print requests are: {prints}" )); } @@ -2234,7 +2234,7 @@ fn collect_print_requests( let out = out.unwrap_or(OutFileName::Stdout); if let OutFileName::Real(path) = &out { if !printed_paths.insert(path.clone()) { - early_dcx.early_error(format!( + early_dcx.early_fatal(format!( "cannot print multiple outputs to the same path: {}", path.display(), )); @@ -2252,7 +2252,7 @@ pub fn parse_target_triple(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches Some(target) if target.ends_with(".json") => { let path = Path::new(&target); TargetTriple::from_path(path).unwrap_or_else(|_| { - early_dcx.early_error(format!("target file {path:?} does not exist")) + early_dcx.early_fatal(format!("target file {path:?} does not exist")) }) } Some(target) => TargetTriple::TargetTriple(target), @@ -2291,7 +2291,7 @@ fn parse_opt_level( "s" => OptLevel::Size, "z" => OptLevel::SizeMin, arg => { - early_dcx.early_error(format!( + early_dcx.early_fatal(format!( "optimization level needs to be \ between 0-3, s or z (instead was `{arg}`)" )); @@ -2321,7 +2321,7 @@ fn parse_assert_incr_state( Some(s) if s.as_str() == "loaded" => Some(IncrementalStateAssertion::Loaded), Some(s) if s.as_str() == "not-loaded" => Some(IncrementalStateAssertion::NotLoaded), Some(s) => { - early_dcx.early_error(format!("unexpected incremental state assertion value: {s}")) + early_dcx.early_fatal(format!("unexpected incremental state assertion value: {s}")) } None => None, } @@ -2348,11 +2348,11 @@ fn parse_native_lib_kind( } else { ", the `-Z unstable-options` flag must also be passed to use it" }; - early_dcx.early_error(format!("library kind `link-arg` is unstable{why}")) + early_dcx.early_fatal(format!("library kind `link-arg` is unstable{why}")) } NativeLibKind::LinkArg } - _ => early_dcx.early_error(format!( + _ => early_dcx.early_fatal(format!( "unknown library kind `{kind}`, expected one of: static, dylib, framework, link-arg" )), }; @@ -2372,7 +2372,7 @@ fn parse_native_lib_modifiers( for modifier in modifiers.split(',') { let (modifier, value) = match modifier.strip_prefix(['+', '-']) { Some(m) => (m, modifier.starts_with('+')), - None => early_dcx.early_error( + None => early_dcx.early_fatal( "invalid linking modifier syntax, expected '+' or '-' prefix \ before one of: bundle, verbatim, whole-archive, as-needed", ), @@ -2385,20 +2385,20 @@ fn parse_native_lib_modifiers( } else { ", the `-Z unstable-options` flag must also be passed to use it" }; - early_dcx.early_error(format!("linking modifier `{modifier}` is unstable{why}")) + early_dcx.early_fatal(format!("linking modifier `{modifier}` is unstable{why}")) } }; let assign_modifier = |dst: &mut Option<bool>| { if dst.is_some() { let msg = format!("multiple `{modifier}` modifiers in a single `-l` option"); - early_dcx.early_error(msg) + early_dcx.early_fatal(msg) } else { *dst = Some(value); } }; match (modifier, &mut kind) { ("bundle", NativeLibKind::Static { bundle, .. }) => assign_modifier(bundle), - ("bundle", _) => early_dcx.early_error( + ("bundle", _) => early_dcx.early_fatal( "linking modifier `bundle` is only compatible with `static` linking kind", ), @@ -2407,7 +2407,7 @@ fn parse_native_lib_modifiers( ("whole-archive", NativeLibKind::Static { whole_archive, .. }) => { assign_modifier(whole_archive) } - ("whole-archive", _) => early_dcx.early_error( + ("whole-archive", _) => early_dcx.early_fatal( "linking modifier `whole-archive` is only compatible with `static` linking kind", ), @@ -2416,14 +2416,14 @@ fn parse_native_lib_modifiers( report_unstable_modifier(); assign_modifier(as_needed) } - ("as-needed", _) => early_dcx.early_error( + ("as-needed", _) => early_dcx.early_fatal( "linking modifier `as-needed` is only compatible with \ `dylib` and `framework` linking kinds", ), // Note: this error also excludes the case with empty modifier // string, like `modifiers = ""`. - _ => early_dcx.early_error(format!( + _ => early_dcx.early_fatal(format!( "unknown linking modifier `{modifier}`, expected one \ of: bundle, verbatim, whole-archive, as-needed" )), @@ -2457,7 +2457,7 @@ fn parse_libs(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> Vec<Nati Some((name, new_name)) => (name.to_string(), Some(new_name.to_owned())), }; if name.is_empty() { - early_dcx.early_error("library name must not be empty"); + early_dcx.early_fatal("library name must not be empty"); } NativeLib { name, new_name, kind, verbatim } }) @@ -2493,7 +2493,7 @@ pub fn parse_externs( }; if !is_ascii_ident(&name) { - let mut error = early_dcx.early_struct_error(format!( + let mut error = early_dcx.early_struct_fatal(format!( "crate name `{name}` passed to `--extern` is not a valid ASCII identifier" )); let adjusted_name = name.replace('-', "_"); @@ -2555,7 +2555,7 @@ pub fn parse_externs( let mut force = false; if let Some(opts) = options { if !is_unstable_enabled { - early_dcx.early_error( + early_dcx.early_fatal( "the `-Z unstable-options` flag must also be passed to \ enable `--extern` options", ); @@ -2567,14 +2567,14 @@ pub fn parse_externs( if let ExternLocation::ExactPaths(_) = &entry.location { add_prelude = false; } else { - early_dcx.early_error( + early_dcx.early_fatal( "the `noprelude` --extern option requires a file path", ); } } "nounused" => nounused_dep = true, "force" => force = true, - _ => early_dcx.early_error(format!("unknown --extern option `{opt}`")), + _ => early_dcx.early_fatal(format!("unknown --extern option `{opt}`")), } } } @@ -2602,7 +2602,7 @@ fn parse_remap_path_prefix( .into_iter() .map(|remap| match remap.rsplit_once('=') { None => { - early_dcx.early_error("--remap-path-prefix must contain '=' between FROM and TO") + early_dcx.early_fatal("--remap-path-prefix must contain '=' between FROM and TO") } Some((from, to)) => (PathBuf::from(from), PathBuf::from(to)), }) @@ -2627,7 +2627,7 @@ fn parse_logical_env( if let Some((name, val)) = arg.split_once('=') { vars.insert(name.to_string(), val.to_string()); } else { - early_dcx.early_error(format!("`--env`: specify value for variable `{arg}`")); + early_dcx.early_fatal(format!("`--env`: specify value for variable `{arg}`")); } } @@ -2653,12 +2653,12 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M early_dcx.abort_if_error_and_set_error_format(error_format); let diagnostic_width = matches.opt_get("diagnostic-width").unwrap_or_else(|_| { - early_dcx.early_error("`--diagnostic-width` must be an positive integer"); + early_dcx.early_fatal("`--diagnostic-width` must be an positive integer"); }); let unparsed_crate_types = matches.opt_strs("crate-type"); let crate_types = parse_crate_types_from_list(unparsed_crate_types) - .unwrap_or_else(|e| early_dcx.early_error(e)); + .unwrap_or_else(|e| early_dcx.early_fatal(e)); let mut unstable_opts = UnstableOptions::build(early_dcx, matches); let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(early_dcx, matches); @@ -2666,7 +2666,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M check_error_format_stability(early_dcx, &unstable_opts, error_format, json_rendered); if !unstable_opts.unstable_options && json_unused_externs.is_enabled() { - early_dcx.early_error( + early_dcx.early_fatal( "the `-Z unstable-options` flag must also be passed to enable \ the flag `--json=unused-externs`", ); @@ -2683,15 +2683,15 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M ); if unstable_opts.threads == 0 { - early_dcx.early_error("value for threads must be a positive non-zero integer"); + early_dcx.early_fatal("value for threads must be a positive non-zero integer"); } let fuel = unstable_opts.fuel.is_some() || unstable_opts.print_fuel.is_some(); if fuel && unstable_opts.threads > 1 { - early_dcx.early_error("optimization fuel is incompatible with multiple threads"); + early_dcx.early_fatal("optimization fuel is incompatible with multiple threads"); } if fuel && cg.incremental.is_some() { - early_dcx.early_error("optimization fuel is incompatible with incremental compilation"); + early_dcx.early_fatal("optimization fuel is incompatible with incremental compilation"); } let incremental = cg.incremental.as_ref().map(PathBuf::from); @@ -2699,25 +2699,25 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M let assert_incr_state = parse_assert_incr_state(early_dcx, &unstable_opts.assert_incr_state); if unstable_opts.profile && incremental.is_some() { - early_dcx.early_error("can't instrument with gcov profiling when compiling incrementally"); + early_dcx.early_fatal("can't instrument with gcov profiling when compiling incrementally"); } if unstable_opts.profile { match codegen_units { Some(1) => {} None => codegen_units = Some(1), Some(_) => early_dcx - .early_error("can't instrument with gcov profiling with multiple codegen units"), + .early_fatal("can't instrument with gcov profiling with multiple codegen units"), } } if cg.profile_generate.enabled() && cg.profile_use.is_some() { - early_dcx.early_error("options `-C profile-generate` and `-C profile-use` are exclusive"); + early_dcx.early_fatal("options `-C profile-generate` and `-C profile-use` are exclusive"); } if unstable_opts.profile_sample_use.is_some() && (cg.profile_generate.enabled() || cg.profile_use.is_some()) { - early_dcx.early_error( + early_dcx.early_fatal( "option `-Z profile-sample-use` cannot be used with `-C profile-generate` or `-C profile-use`", ); } @@ -2730,7 +2730,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M // Unstable values: Some(SymbolManglingVersion::Legacy) => { if !unstable_opts.unstable_options { - early_dcx.early_error( + early_dcx.early_fatal( "`-C symbol-mangling-version=legacy` requires `-Z unstable-options`", ); } @@ -2747,7 +2747,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M | InstrumentCoverage::ExceptUnusedFunctions | InstrumentCoverage::ExceptUnusedGenerics => { if !unstable_opts.unstable_options { - early_dcx.early_error( + early_dcx.early_fatal( "`-C instrument-coverage=branch` and `-C instrument-coverage=except-*` \ require `-Z unstable-options`", ); @@ -2757,7 +2757,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M if cg.instrument_coverage != InstrumentCoverage::Off { if cg.profile_generate.enabled() || cg.profile_use.is_some() { - early_dcx.early_error( + early_dcx.early_fatal( "option `-C instrument-coverage` is not compatible with either `-C profile-use` \ or `-C profile-generate`", ); @@ -2787,7 +2787,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M match cg.lto { LtoCli::No | LtoCli::Unspecified => {} LtoCli::Yes | LtoCli::NoParam | LtoCli::Thin | LtoCli::Fat => { - early_dcx.early_error("options `-C embed-bitcode=no` and `-C lto` are incompatible") + early_dcx.early_fatal("options `-C embed-bitcode=no` and `-C lto` are incompatible") } } } @@ -2799,7 +2799,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M let uses_unstable_self_contained_option = cg.link_self_contained.are_unstable_variants_set(); if uses_unstable_self_contained_option { - early_dcx.early_error( + early_dcx.early_fatal( "only `-C link-self-contained` values `y`/`yes`/`on`/`n`/`no`/`off` are stable, \ the `-Z unstable-options` flag must also be passed to use the unstable values", ); @@ -2807,7 +2807,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M if let Some(flavor) = cg.linker_flavor { if flavor.is_unstable() { - early_dcx.early_error(format!( + early_dcx.early_fatal(format!( "the linker flavor `{}` is unstable, the `-Z unstable-options` \ flag must also be passed to use the unstable values", flavor.desc() @@ -2824,7 +2824,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M .map(|c| c.as_str().unwrap()) .intersperse(", ") .collect(); - early_dcx.early_error(format!( + early_dcx.early_fatal(format!( "some `-C link-self-contained` components were both enabled and disabled: {names}" )); } @@ -2871,7 +2871,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M // query-dep-graph is required if dump-dep-graph is given #106736 if unstable_opts.dump_dep_graph && !unstable_opts.query_dep_graph { - early_dcx.early_error("can't dump dependency graph without `-Z query-dep-graph`"); + early_dcx.early_fatal("can't dump dependency graph without `-Z query-dep-graph`"); } let logical_env = parse_logical_env(early_dcx, matches); @@ -2905,7 +2905,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M }; let working_dir = std::env::current_dir().unwrap_or_else(|e| { - early_dcx.early_error(format!("Current directory is invalid: {e}")); + early_dcx.early_fatal(format!("Current directory is invalid: {e}")); }); let remap = file_path_mapping(remap_path_prefix.clone(), &unstable_opts); @@ -2980,7 +2980,7 @@ fn parse_pretty(early_dcx: &EarlyDiagCtxt, unstable_opts: &UnstableOptions) -> O "mir" => Mir, "stable-mir" => StableMir, "mir-cfg" => MirCFG, - name => early_dcx.early_error(format!( + name => early_dcx.early_fatal(format!( "argument to `unpretty` must be one of `normal`, `identified`, \ `expanded`, `expanded,identified`, `expanded,hygiene`, \ `ast-tree`, `ast-tree,expanded`, `hir`, `hir,identified`, \ @@ -3060,7 +3060,7 @@ pub mod nightly_options { continue; } if opt.name != "Z" && !has_z_unstable_option { - early_dcx.early_error(format!( + early_dcx.early_fatal(format!( "the `-Z unstable-options` flag must also be passed to enable \ the flag `{}`", opt.name @@ -3076,7 +3076,7 @@ pub mod nightly_options { "the option `{}` is only accepted on the nightly compiler", opt.name ); - let _ = early_dcx.early_error_no_abort(msg); + let _ = early_dcx.early_err(msg); } OptionStability::Stable => {} } @@ -3086,7 +3086,7 @@ pub mod nightly_options { .early_help("consider switching to a nightly toolchain: `rustup default nightly`"); early_dcx.early_note("selecting a toolchain with `+toolchain` arguments require a rustup proxy; see <https://rust-lang.github.io/rustup/concepts/index.html>"); early_dcx.early_note("for more information about Rust's stability policy, see <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html#unstable-features>"); - early_dcx.early_error(format!( + early_dcx.early_fatal(format!( "{} nightly option{} were parsed", nightly_options_on_stable, if nightly_options_on_stable > 1 { "s" } else { "" } diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index c3360815ac9..9f7d918d98b 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -3,7 +3,9 @@ use std::num::NonZeroU32; use crate::parse::ParseSess; use rustc_ast::token; use rustc_ast::util::literal::LitError; -use rustc_errors::{error_code, DiagnosticMessage, ErrorGuaranteed, IntoDiagnostic, MultiSpan}; +use rustc_errors::{ + error_code, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, IntoDiagnostic, Level, MultiSpan, +}; use rustc_macros::Diagnostic; use rustc_span::{BytePos, Span, Symbol}; use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple}; @@ -15,11 +17,8 @@ pub struct FeatureGateError { impl<'a> IntoDiagnostic<'a> for FeatureGateError { #[track_caller] - fn into_diagnostic( - self, - dcx: &'a rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'a, ErrorGuaranteed> { - let mut diag = dcx.struct_err(self.explain); + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a> { + let mut diag = DiagnosticBuilder::new(dcx, level, self.explain); diag.set_span(self.span); diag.code(error_code!(E0658)); diag diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 06b554e8e63..10a4bdb94d4 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -337,12 +337,12 @@ fn build_options<O: Default>( Some((_, setter, type_desc, _)) => { if !setter(&mut op, value) { match value { - None => early_dcx.early_error( + None => early_dcx.early_fatal( format!( "{outputname} option `{key}` requires {type_desc} ({prefix} {key}=<value>)" ), ), - Some(value) => early_dcx.early_error( + Some(value) => early_dcx.early_fatal( format!( "incorrect value `{value}` for {outputname} option `{key}` - {type_desc} was expected" ), @@ -350,7 +350,7 @@ fn build_options<O: Default>( } } } - None => early_dcx.early_error(format!("unknown {outputname} option: `{key}`")), + None => early_dcx.early_fatal(format!("unknown {outputname} option: `{key}`")), } } return op; @@ -1694,6 +1694,8 @@ options! { "link native libraries in the linker invocation (default: yes)"), link_only: bool = (false, parse_bool, [TRACKED], "link the `.rlink` file generated by `-Z no-link` (default: no)"), + lint_mir: bool = (false, parse_bool, [UNTRACKED], + "lint MIR before and after each transformation"), llvm_module_flag: Vec<(String, u32, String)> = (Vec::new(), parse_llvm_module_flag, [TRACKED], "a list of module flags to pass to LLVM (space separated)"), llvm_plugins: Vec<String> = (Vec::new(), parse_list, [TRACKED], diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 2cb47e3a932..52a637b74e7 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -14,7 +14,7 @@ use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc}; use rustc_errors::{emitter::SilentEmitter, DiagCtxt}; use rustc_errors::{ fallback_fluent_bundle, Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, - ErrorGuaranteed, IntoDiagnostic, MultiSpan, Noted, StashKey, + ErrorGuaranteed, FatalAbort, IntoDiagnostic, Level, MultiSpan, StashKey, }; use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures}; use rustc_span::edition::Edition; @@ -83,7 +83,7 @@ pub fn feature_err( feature: Symbol, span: impl Into<MultiSpan>, explain: impl Into<DiagnosticMessage>, -) -> DiagnosticBuilder<'_, ErrorGuaranteed> { +) -> DiagnosticBuilder<'_> { feature_err_issue(sess, feature, span, GateIssue::Language, explain) } @@ -98,7 +98,7 @@ pub fn feature_err_issue( span: impl Into<MultiSpan>, issue: GateIssue, explain: impl Into<DiagnosticMessage>, -) -> DiagnosticBuilder<'_, ErrorGuaranteed> { +) -> DiagnosticBuilder<'_> { let span = span.into(); // Cancel an earlier warning for this same error, if it exists. @@ -318,11 +318,8 @@ impl ParseSess { } #[track_caller] - pub fn create_err<'a>( - &'a self, - err: impl IntoDiagnostic<'a>, - ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - err.into_diagnostic(&self.dcx) + pub fn create_err<'a>(&'a self, err: impl IntoDiagnostic<'a>) -> DiagnosticBuilder<'a> { + err.into_diagnostic(&self.dcx, Level::Error { lint: false }) } #[track_caller] @@ -335,7 +332,7 @@ impl ParseSess { &'a self, warning: impl IntoDiagnostic<'a, ()>, ) -> DiagnosticBuilder<'a, ()> { - warning.into_diagnostic(&self.dcx) + warning.into_diagnostic(&self.dcx, Level::Warning(None)) } #[track_caller] @@ -346,35 +343,32 @@ impl ParseSess { #[track_caller] pub fn create_note<'a>( &'a self, - note: impl IntoDiagnostic<'a, Noted>, - ) -> DiagnosticBuilder<'a, Noted> { - note.into_diagnostic(&self.dcx) + note: impl IntoDiagnostic<'a, ()>, + ) -> DiagnosticBuilder<'a, ()> { + note.into_diagnostic(&self.dcx, Level::Note) } #[track_caller] - pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, Noted>) -> Noted { + pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, ()>) { self.create_note(note).emit() } #[track_caller] pub fn create_fatal<'a>( &'a self, - fatal: impl IntoDiagnostic<'a, !>, - ) -> DiagnosticBuilder<'a, !> { - fatal.into_diagnostic(&self.dcx) + fatal: impl IntoDiagnostic<'a, FatalAbort>, + ) -> DiagnosticBuilder<'a, FatalAbort> { + fatal.into_diagnostic(&self.dcx, Level::Fatal) } #[track_caller] - pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, !>) -> ! { + pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, FatalAbort>) -> ! { self.create_fatal(fatal).emit() } #[rustc_lint_diagnostics] #[track_caller] - pub fn struct_err( - &self, - msg: impl Into<DiagnosticMessage>, - ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + pub fn struct_err(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_> { self.dcx.struct_err(msg) } @@ -386,7 +380,10 @@ impl ParseSess { #[rustc_lint_diagnostics] #[track_caller] - pub fn struct_fatal(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, !> { + pub fn struct_fatal( + &self, + msg: impl Into<DiagnosticMessage>, + ) -> DiagnosticBuilder<'_, FatalAbort> { self.dcx.struct_fatal(msg) } } diff --git a/compiler/rustc_session/src/search_paths.rs b/compiler/rustc_session/src/search_paths.rs index 8ed50f6a14f..9b913c76998 100644 --- a/compiler/rustc_session/src/search_paths.rs +++ b/compiler/rustc_session/src/search_paths.rs @@ -61,7 +61,7 @@ impl SearchPath { (PathKind::All, path) }; if path.is_empty() { - early_dcx.early_error("empty search path given via `-L`"); + early_dcx.early_fatal("empty search path given via `-L`"); } let dir = PathBuf::from(path); diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 7f168572f7d..272e231d3ed 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -23,8 +23,8 @@ use rustc_errors::json::JsonEmitter; use rustc_errors::registry::Registry; use rustc_errors::{ error_code, fallback_fluent_bundle, DiagCtxt, DiagnosticBuilder, DiagnosticId, - DiagnosticMessage, ErrorGuaranteed, FluentBundle, IntoDiagnostic, LazyFallbackBundle, - MultiSpan, Noted, TerminalUrl, + DiagnosticMessage, ErrorGuaranteed, FatalAbort, FluentBundle, IntoDiagnostic, + LazyFallbackBundle, MultiSpan, TerminalUrl, }; use rustc_macros::HashStable_Generic; pub use rustc_span::def_id::StableCrateId; @@ -321,16 +321,6 @@ impl Session { } #[rustc_lint_diagnostics] #[track_caller] - pub fn struct_span_warn_with_expectation<S: Into<MultiSpan>>( - &self, - sp: S, - msg: impl Into<DiagnosticMessage>, - id: lint::LintExpectationId, - ) -> DiagnosticBuilder<'_, ()> { - self.dcx().struct_span_warn_with_expectation(sp, msg, id) - } - #[rustc_lint_diagnostics] - #[track_caller] pub fn struct_span_warn_with_code<S: Into<MultiSpan>>( &self, sp: S, @@ -346,24 +336,6 @@ impl Session { } #[rustc_lint_diagnostics] #[track_caller] - pub fn struct_warn_with_expectation( - &self, - msg: impl Into<DiagnosticMessage>, - id: lint::LintExpectationId, - ) -> DiagnosticBuilder<'_, ()> { - self.dcx().struct_warn_with_expectation(msg, id) - } - #[rustc_lint_diagnostics] - #[track_caller] - pub fn struct_span_allow<S: Into<MultiSpan>>( - &self, - sp: S, - msg: impl Into<DiagnosticMessage>, - ) -> DiagnosticBuilder<'_, ()> { - self.dcx().struct_span_allow(sp, msg) - } - #[rustc_lint_diagnostics] - #[track_caller] pub fn struct_allow(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> { self.dcx().struct_allow(msg) } @@ -382,7 +354,7 @@ impl Session { &self, sp: S, msg: impl Into<DiagnosticMessage>, - ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'_> { self.dcx().struct_span_err(sp, msg) } #[rustc_lint_diagnostics] @@ -392,16 +364,13 @@ impl Session { sp: S, msg: impl Into<DiagnosticMessage>, code: DiagnosticId, - ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'_> { self.dcx().struct_span_err_with_code(sp, msg, code) } // FIXME: This method should be removed (every error should have an associated error code). #[rustc_lint_diagnostics] #[track_caller] - pub fn struct_err( - &self, - msg: impl Into<DiagnosticMessage>, - ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + pub fn struct_err(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_> { self.parse_sess.struct_err(msg) } #[track_caller] @@ -410,7 +379,7 @@ impl Session { &self, msg: impl Into<DiagnosticMessage>, code: DiagnosticId, - ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'_> { self.dcx().struct_err_with_code(msg, code) } #[rustc_lint_diagnostics] @@ -428,7 +397,7 @@ impl Session { &self, sp: S, msg: impl Into<DiagnosticMessage>, - ) -> DiagnosticBuilder<'_, !> { + ) -> DiagnosticBuilder<'_, FatalAbort> { self.dcx().struct_span_fatal(sp, msg) } #[rustc_lint_diagnostics] @@ -437,11 +406,14 @@ impl Session { sp: S, msg: impl Into<DiagnosticMessage>, code: DiagnosticId, - ) -> DiagnosticBuilder<'_, !> { + ) -> DiagnosticBuilder<'_, FatalAbort> { self.dcx().struct_span_fatal_with_code(sp, msg, code) } #[rustc_lint_diagnostics] - pub fn struct_fatal(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, !> { + pub fn struct_fatal( + &self, + msg: impl Into<DiagnosticMessage>, + ) -> DiagnosticBuilder<'_, FatalAbort> { self.dcx().struct_fatal(msg) } @@ -488,10 +460,7 @@ impl Session { self.dcx().err(msg) } #[track_caller] - pub fn create_err<'a>( - &'a self, - err: impl IntoDiagnostic<'a>, - ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + pub fn create_err<'a>(&'a self, err: impl IntoDiagnostic<'a>) -> DiagnosticBuilder<'a> { self.parse_sess.create_err(err) } #[track_caller] @@ -499,10 +468,10 @@ impl Session { &'a self, err: impl IntoDiagnostic<'a>, feature: Symbol, - ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'a> { let mut err = self.parse_sess.create_err(err); if err.code.is_none() { - err.code = std::option::Option::Some(error_code!(E0658)); + err.code(error_code!(E0658)); } add_feature_diagnostics(&mut err, &self.parse_sess, feature); err @@ -525,23 +494,23 @@ impl Session { #[track_caller] pub fn create_note<'a>( &'a self, - note: impl IntoDiagnostic<'a, Noted>, - ) -> DiagnosticBuilder<'a, Noted> { + note: impl IntoDiagnostic<'a, ()>, + ) -> DiagnosticBuilder<'a, ()> { self.parse_sess.create_note(note) } #[track_caller] - pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, Noted>) -> Noted { + pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, ()>) { self.parse_sess.emit_note(note) } #[track_caller] pub fn create_fatal<'a>( &'a self, - fatal: impl IntoDiagnostic<'a, !>, - ) -> DiagnosticBuilder<'a, !> { + fatal: impl IntoDiagnostic<'a, FatalAbort>, + ) -> DiagnosticBuilder<'a, FatalAbort> { self.parse_sess.create_fatal(fatal) } #[track_caller] - pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, !>) -> ! { + pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, FatalAbort>) -> ! { self.parse_sess.emit_fatal(fatal) } #[inline] @@ -1390,7 +1359,7 @@ pub fn build_session( let target_cfg = config::build_target_config(&early_dcx, &sopts, target_override, &sysroot); let host_triple = TargetTriple::from_triple(config::host_triple()); let (host, target_warnings) = Target::search(&host_triple, &sysroot).unwrap_or_else(|e| { - early_dcx.early_error(format!("Error loading host specification: {e}")) + early_dcx.early_fatal(format!("Error loading host specification: {e}")) }); for warning in target_warnings.warning_messages() { early_dcx.early_warn(warning) @@ -1765,22 +1734,22 @@ impl EarlyDiagCtxt { #[allow(rustc::untranslatable_diagnostic)] #[allow(rustc::diagnostic_outside_of_impl)] #[must_use = "ErrorGuaranteed must be returned from `run_compiler` in order to exit with a non-zero status code"] - pub fn early_error_no_abort(&self, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed { + pub fn early_err(&self, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed { self.dcx.struct_err(msg).emit() } #[allow(rustc::untranslatable_diagnostic)] #[allow(rustc::diagnostic_outside_of_impl)] - pub fn early_error(&self, msg: impl Into<DiagnosticMessage>) -> ! { + pub fn early_fatal(&self, msg: impl Into<DiagnosticMessage>) -> ! { self.dcx.struct_fatal(msg).emit() } #[allow(rustc::untranslatable_diagnostic)] #[allow(rustc::diagnostic_outside_of_impl)] - pub fn early_struct_error( + pub fn early_struct_fatal( &self, msg: impl Into<DiagnosticMessage>, - ) -> DiagnosticBuilder<'_, !> { + ) -> DiagnosticBuilder<'_, FatalAbort> { self.dcx.struct_fatal(msg) } diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mod.rs b/compiler/rustc_smir/src/rustc_smir/convert/mod.rs index 8b7b26f969c..5f505ac181c 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mod.rs @@ -41,17 +41,26 @@ impl<'tcx> Stable<'tcx> for rustc_hir::CoroutineSource { impl<'tcx> Stable<'tcx> for rustc_hir::CoroutineKind { type T = stable_mir::mir::CoroutineKind; fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { - use rustc_hir::CoroutineKind; + use rustc_hir::{CoroutineDesugaring, CoroutineKind}; match self { - CoroutineKind::Async(source) => { - stable_mir::mir::CoroutineKind::Async(source.stable(tables)) + CoroutineKind::Desugared(CoroutineDesugaring::Async, source) => { + stable_mir::mir::CoroutineKind::Desugared( + stable_mir::mir::CoroutineDesugaring::Async, + source.stable(tables), + ) } - CoroutineKind::Gen(source) => { - stable_mir::mir::CoroutineKind::Gen(source.stable(tables)) + CoroutineKind::Desugared(CoroutineDesugaring::Gen, source) => { + stable_mir::mir::CoroutineKind::Desugared( + stable_mir::mir::CoroutineDesugaring::Gen, + source.stable(tables), + ) } CoroutineKind::Coroutine => stable_mir::mir::CoroutineKind::Coroutine, - CoroutineKind::AsyncGen(source) => { - stable_mir::mir::CoroutineKind::AsyncGen(source.stable(tables)) + CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, source) => { + stable_mir::mir::CoroutineKind::Desugared( + stable_mir::mir::CoroutineDesugaring::AsyncGen, + source.stable(tables), + ) } } } diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs index b2d51ac6c0d..e397fab5459 100644 --- a/compiler/rustc_span/src/def_id.rs +++ b/compiler/rustc_span/src/def_id.rs @@ -114,8 +114,6 @@ impl DefPathHash { } /// Returns the crate-local part of the [DefPathHash]. - /// - /// Used for tests. #[inline] pub fn local_hash(&self) -> Hash64 { self.0.split().1 diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 0333b5f04c3..95106cc64c1 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -426,7 +426,9 @@ symbols! { async_closure, async_fn_in_trait, async_fn_track_caller, + async_for_loop, async_iterator, + async_iterator_poll_next, atomic, atomic_mod, atomics, @@ -893,6 +895,7 @@ symbols! { instruction_set, integer_: "integer", // underscore to avoid clashing with the function `sym::integer` below integral, + into_async_iter_into_iter, into_future, into_iter, intra_doc_pointers, diff --git a/compiler/rustc_symbol_mangling/src/errors.rs b/compiler/rustc_symbol_mangling/src/errors.rs index ff253b6f467..06a2b3ca9c4 100644 --- a/compiler/rustc_symbol_mangling/src/errors.rs +++ b/compiler/rustc_symbol_mangling/src/errors.rs @@ -1,6 +1,6 @@ //! Errors emitted by symbol_mangling. -use rustc_errors::{ErrorGuaranteed, IntoDiagnostic}; +use rustc_errors::{DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level}; use rustc_span::Span; use std::fmt; @@ -13,15 +13,12 @@ pub struct TestOutput { // This diagnostic doesn't need translation because (a) it doesn't contain any // natural language, and (b) it's only used in tests. So we construct it // manually and avoid the fluent machinery. -impl IntoDiagnostic<'_> for TestOutput { - fn into_diagnostic( - self, - dcx: &'_ rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { +impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for TestOutput { + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { let TestOutput { span, kind, content } = self; #[allow(rustc::untranslatable_diagnostic)] - let mut diag = dcx.struct_err(format!("{kind}({content})")); + let mut diag = DiagnosticBuilder::new(dcx, level, format!("{kind}({content})")); diag.set_span(span); diag } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index b688c97311a..4789a9be151 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1493,6 +1493,7 @@ supported_targets! { ("mips64-unknown-linux-muslabi64", mips64_unknown_linux_muslabi64), ("mips64el-unknown-linux-muslabi64", mips64el_unknown_linux_muslabi64), ("hexagon-unknown-linux-musl", hexagon_unknown_linux_musl), + ("hexagon-unknown-none-elf", hexagon_unknown_none_elf), ("mips-unknown-linux-uclibc", mips_unknown_linux_uclibc), ("mipsel-unknown-linux-uclibc", mipsel_unknown_linux_uclibc), @@ -1590,6 +1591,7 @@ supported_targets! { ("sparcv9-sun-solaris", sparcv9_sun_solaris), ("x86_64-unknown-illumos", x86_64_unknown_illumos), + ("aarch64-unknown-illumos", aarch64_unknown_illumos), ("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu), ("i686-pc-windows-gnu", i686_pc_windows_gnu), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_illumos.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_illumos.rs new file mode 100644 index 00000000000..634cb063a49 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_illumos.rs @@ -0,0 +1,19 @@ +use crate::spec::{base, Cc, LinkerFlavor, SanitizerSet, Target}; + +pub fn target() -> Target { + let mut base = base::illumos::opts(); + base.add_pre_link_args(LinkerFlavor::Unix(Cc::Yes), &["-std=c99"]); + base.max_atomic_width = Some(128); + base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI; + base.features = "+v8a".into(); + + Target { + // LLVM does not currently have a separate illumos target, + // so we still pass Solaris to it + llvm_target: "aarch64-unknown-solaris2.11".into(), + pointer_width: 64, + data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(), + arch: "aarch64".into(), + options: base, + } +} diff --git a/compiler/rustc_target/src/spec/targets/hexagon_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/hexagon_unknown_none_elf.rs new file mode 100644 index 00000000000..205f195a701 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/hexagon_unknown_none_elf.rs @@ -0,0 +1,27 @@ +use crate::spec::{PanicStrategy, Target, TargetOptions}; + +pub fn target() -> Target { + Target { + llvm_target: "hexagon-unknown-none-elf".into(), + pointer_width: 32, + data_layout: concat!( + "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32", + ":32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32", + ":32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048", + ":2048:2048" + ) + .into(), + arch: "hexagon".into(), + + options: TargetOptions { + cpu: "hexagonv60".into(), + panic_strategy: PanicStrategy::Abort, + dynamic_linking: true, + features: "-small-data,+hvx-length128b".into(), + max_atomic_width: Some(32), + emit_debug_gdb_scripts: false, + c_enum_min_bits: Some(8), + ..Default::default() + }, + } +} diff --git a/compiler/rustc_target/src/spec/tests/tests_impl.rs b/compiler/rustc_target/src/spec/tests/tests_impl.rs index 257867b1b80..3fefd60f7cd 100644 --- a/compiler/rustc_target/src/spec/tests/tests_impl.rs +++ b/compiler/rustc_target/src/spec/tests/tests_impl.rs @@ -116,7 +116,8 @@ impl Target { // Check dynamic linking stuff // BPF: when targeting user space vms (like rbpf), those can load dynamic libraries. - if self.os == "none" && self.arch != "bpf" { + // hexagon: when targeting QuRT, that OS can load dynamic libraries. + if self.os == "none" && (self.arch != "bpf" && self.arch != "hexagon") { assert!(!self.dynamic_linking); } if self.only_cdylib diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index b0ec8b3a4fa..bea6fbd6ac5 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -1,7 +1,7 @@ use crate::fluent_generated as fluent; use rustc_errors::{ - AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, ErrorGuaranteed, IntoDiagnostic, - SubdiagnosticMessage, + AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, EmissionGuarantee, + IntoDiagnostic, Level, SubdiagnosticMessage, }; use rustc_macros::Diagnostic; use rustc_middle::ty::{self, ClosureKind, PolyTraitRef, Ty}; @@ -57,13 +57,15 @@ pub struct NegativePositiveConflict<'tcx> { pub positive_impl_span: Result<Span, Symbol>, } -impl IntoDiagnostic<'_> for NegativePositiveConflict<'_> { +impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for NegativePositiveConflict<'_> { #[track_caller] fn into_diagnostic( self, dcx: &DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::trait_selection_negative_positive_conflict); + level: Level, + ) -> rustc_errors::DiagnosticBuilder<'_, G> { + let mut diag = + DiagnosticBuilder::new(dcx, level, fluent::trait_selection_negative_positive_conflict); diag.set_arg("trait_desc", self.trait_desc.print_only_trait_path().to_string()); diag.set_arg( "self_desc", diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 13a09917c03..c6d029ddb65 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -477,7 +477,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { let mut vid_map: FxHashMap<RegionTarget<'cx>, RegionDeps<'cx>> = FxHashMap::default(); let mut finished_map = FxHashMap::default(); - for constraint in regions.constraints.keys() { + for (constraint, _) in ®ions.constraints { match constraint { &Constraint::VarSubVar(r1, r2) => { { diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs index 0190d5ab4be..676b40850b1 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs @@ -1,7 +1,7 @@ use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::infer::InferCtxt; use crate::traits::{Obligation, ObligationCause, ObligationCtxt}; -use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed}; +use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::Node; use rustc_middle::ty::{self, Ty}; @@ -29,7 +29,7 @@ pub trait InferCtxtExt<'tcx> { found_args: Vec<ArgKind>, is_closure: bool, closure_pipe_span: Option<Span>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>; + ) -> DiagnosticBuilder<'tcx>; /// Checks if the type implements one of `Fn`, `FnMut`, or `FnOnce` /// in that order, and returns the generic type corresponding to the @@ -118,7 +118,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { found_args: Vec<ArgKind>, is_closure: bool, closure_arg_span: Option<Span>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { let kind = if is_closure { "closure" } else { "function" }; let args_str = |arguments: &[ArgKind], other: &[ArgKind]| { diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index a1b896d2251..e84c5b76421 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -14,7 +14,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{ error_code, pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, - ErrorGuaranteed, MultiSpan, Style, SuggestionStyle, + MultiSpan, Style, SuggestionStyle, }; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -22,7 +22,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; use rustc_hir::is_range_literal; use rustc_hir::lang_items::LangItem; -use rustc_hir::{CoroutineKind, CoroutineSource, Node}; +use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, Node}; use rustc_hir::{Expr, HirId}; use rustc_infer::infer::error_reporting::TypeErrCtxt; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; @@ -207,7 +207,7 @@ pub trait TypeErrCtxtExt<'tcx> { fn point_at_returns_when_relevant( &self, - err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>, + err: &mut DiagnosticBuilder<'tcx>, obligation: &PredicateObligation<'tcx>, ); @@ -220,7 +220,7 @@ pub trait TypeErrCtxtExt<'tcx> { cause: &ObligationCauseCode<'tcx>, found_node: Option<Node<'_>>, param_env: ty::ParamEnv<'tcx>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>; + ) -> DiagnosticBuilder<'tcx>; fn note_conflicting_fn_args( &self, @@ -234,7 +234,7 @@ pub trait TypeErrCtxtExt<'tcx> { fn note_conflicting_closure_bounds( &self, cause: &ObligationCauseCode<'tcx>, - err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>, + err: &mut DiagnosticBuilder<'tcx>, ); fn suggest_fully_qualified_path( @@ -1384,7 +1384,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if has_custom_message { err.note(msg); } else { - err.message = + err.messages = vec![(rustc_errors::DiagnosticMessage::from(msg), Style::NoStyle)]; } let mut file = None; @@ -1920,7 +1920,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { fn point_at_returns_when_relevant( &self, - err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>, + err: &mut DiagnosticBuilder<'tcx>, obligation: &PredicateObligation<'tcx>, ) { match obligation.cause.code().peel_derives() { @@ -1961,7 +1961,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { cause: &ObligationCauseCode<'tcx>, found_node: Option<Node<'_>>, param_env: ty::ParamEnv<'tcx>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { pub(crate) fn build_fn_sig_ty<'tcx>( infcx: &InferCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>, @@ -2187,7 +2187,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { fn note_conflicting_closure_bounds( &self, cause: &ObligationCauseCode<'tcx>, - err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>, + err: &mut DiagnosticBuilder<'tcx>, ) { // First, look for an `ExprBindingObligation`, which means we can get // the unsubstituted predicate list of the called function. And check @@ -2578,7 +2578,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { .and_then(|coroutine_did| { Some(match self.tcx.coroutine_kind(coroutine_did).unwrap() { CoroutineKind::Coroutine => format!("coroutine is not {trait_name}"), - CoroutineKind::Async(CoroutineSource::Fn) => self + CoroutineKind::Desugared( + CoroutineDesugaring::Async, + CoroutineSource::Fn, + ) => self .tcx .parent(coroutine_did) .as_local() @@ -2587,13 +2590,22 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { .map(|name| { format!("future returned by `{name}` is not {trait_name}") })?, - CoroutineKind::Async(CoroutineSource::Block) => { + CoroutineKind::Desugared( + CoroutineDesugaring::Async, + CoroutineSource::Block, + ) => { format!("future created by async block is not {trait_name}") } - CoroutineKind::Async(CoroutineSource::Closure) => { + CoroutineKind::Desugared( + CoroutineDesugaring::Async, + CoroutineSource::Closure, + ) => { format!("future created by async closure is not {trait_name}") } - CoroutineKind::AsyncGen(CoroutineSource::Fn) => self + CoroutineKind::Desugared( + CoroutineDesugaring::AsyncGen, + CoroutineSource::Fn, + ) => self .tcx .parent(coroutine_did) .as_local() @@ -2602,27 +2614,40 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { .map(|name| { format!("async iterator returned by `{name}` is not {trait_name}") })?, - CoroutineKind::AsyncGen(CoroutineSource::Block) => { + CoroutineKind::Desugared( + CoroutineDesugaring::AsyncGen, + CoroutineSource::Block, + ) => { format!("async iterator created by async gen block is not {trait_name}") } - CoroutineKind::AsyncGen(CoroutineSource::Closure) => { + CoroutineKind::Desugared( + CoroutineDesugaring::AsyncGen, + CoroutineSource::Closure, + ) => { format!( "async iterator created by async gen closure is not {trait_name}" ) } - CoroutineKind::Gen(CoroutineSource::Fn) => self - .tcx - .parent(coroutine_did) - .as_local() - .map(|parent_did| self.tcx.local_def_id_to_hir_id(parent_did)) - .and_then(|parent_hir_id| hir.opt_name(parent_hir_id)) - .map(|name| { - format!("iterator returned by `{name}` is not {trait_name}") - })?, - CoroutineKind::Gen(CoroutineSource::Block) => { + CoroutineKind::Desugared(CoroutineDesugaring::Gen, CoroutineSource::Fn) => { + self.tcx + .parent(coroutine_did) + .as_local() + .map(|parent_did| self.tcx.local_def_id_to_hir_id(parent_did)) + .and_then(|parent_hir_id| hir.opt_name(parent_hir_id)) + .map(|name| { + format!("iterator returned by `{name}` is not {trait_name}") + })? + } + CoroutineKind::Desugared( + CoroutineDesugaring::Gen, + CoroutineSource::Block, + ) => { format!("iterator created by gen block is not {trait_name}") } - CoroutineKind::Gen(CoroutineSource::Closure) => { + CoroutineKind::Desugared( + CoroutineDesugaring::Gen, + CoroutineSource::Closure, + ) => { format!("iterator created by gen closure is not {trait_name}") } }) @@ -3145,9 +3170,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let what = match self.tcx.coroutine_kind(coroutine_def_id) { None | Some(hir::CoroutineKind::Coroutine) - | Some(hir::CoroutineKind::Gen(_)) => "yield", - Some(hir::CoroutineKind::Async(..)) => "await", - Some(hir::CoroutineKind::AsyncGen(_)) => "yield`/`await", + | Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)) => { + "yield" + } + Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) => { + "await" + } + Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)) => { + "yield`/`await" + } }; err.note(format!( "all values live across `{what}` must have a statically known size" @@ -3535,7 +3566,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) { if let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) { let body = self.tcx.hir().body(body_id); - if let Some(hir::CoroutineKind::Async(_)) = body.coroutine_kind { + if let Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) = + body.coroutine_kind + { let future_trait = self.tcx.require_lang_item(LangItem::Future, None); let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty()); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 9ee091bbd1e..a495f8399b9 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -1,3 +1,5 @@ +// ignore-tidy-filelength :( + use super::on_unimplemented::{AppendConstMessage, OnUnimplementedNote, TypeErrCtxtExt as _}; use super::suggestions::{get_explanation_based_on_obligation, TypeErrCtxtExt as _}; use crate::errors::{ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch}; @@ -59,7 +61,7 @@ pub trait TypeErrCtxtExt<'tcx> { predicate: &T, span: Span, suggest_increasing_limit: bool, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> + ) -> DiagnosticBuilder<'tcx> where T: fmt::Display + TypeFoldable<TyCtxt<'tcx>> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>; @@ -118,7 +120,7 @@ pub trait TypeErrCtxtExt<'tcx> { &self, ty: Ty<'tcx>, obligation: &PredicateObligation<'tcx>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>; + ) -> DiagnosticBuilder<'tcx>; } impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { @@ -263,7 +265,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { predicate: &T, span: Span, suggest_increasing_limit: bool, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> + ) -> DiagnosticBuilder<'tcx> where T: fmt::Display + TypeFoldable<TyCtxt<'tcx>> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>, { @@ -1226,7 +1228,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { &self, ty: Ty<'tcx>, obligation: &PredicateObligation<'tcx>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { let span = obligation.cause.span; let mut diag = match ty.kind() { @@ -1491,7 +1493,7 @@ pub(super) trait InferCtxtPrivExt<'tcx> { closure_def_id: DefId, found_kind: ty::ClosureKind, kind: ty::ClosureKind, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>; + ) -> DiagnosticBuilder<'tcx>; fn report_type_parameter_mismatch_cyclic_type_error( &self, @@ -1499,13 +1501,13 @@ pub(super) trait InferCtxtPrivExt<'tcx> { found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, terr: TypeError<'tcx>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>; + ) -> DiagnosticBuilder<'tcx>; fn report_opaque_type_auto_trait_leakage( &self, obligation: &PredicateObligation<'tcx>, def_id: DefId, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>; + ) -> DiagnosticBuilder<'tcx>; fn report_type_parameter_mismatch_error( &self, @@ -1513,13 +1515,13 @@ pub(super) trait InferCtxtPrivExt<'tcx> { span: Span, found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, - ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>>; + ) -> Option<DiagnosticBuilder<'tcx>>; fn report_not_const_evaluatable_error( &self, obligation: &PredicateObligation<'tcx>, span: Span, - ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>>; + ) -> Option<DiagnosticBuilder<'tcx>>; } impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { @@ -1926,15 +1928,42 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { fn describe_coroutine(&self, body_id: hir::BodyId) -> Option<&'static str> { self.tcx.hir().body(body_id).coroutine_kind.map(|coroutine_source| match coroutine_source { hir::CoroutineKind::Coroutine => "a coroutine", - hir::CoroutineKind::Async(hir::CoroutineSource::Block) => "an async block", - hir::CoroutineKind::Async(hir::CoroutineSource::Fn) => "an async function", - hir::CoroutineKind::Async(hir::CoroutineSource::Closure) => "an async closure", - hir::CoroutineKind::AsyncGen(hir::CoroutineSource::Block) => "an async gen block", - hir::CoroutineKind::AsyncGen(hir::CoroutineSource::Fn) => "an async gen function", - hir::CoroutineKind::AsyncGen(hir::CoroutineSource::Closure) => "an async gen closure", - hir::CoroutineKind::Gen(hir::CoroutineSource::Block) => "a gen block", - hir::CoroutineKind::Gen(hir::CoroutineSource::Fn) => "a gen function", - hir::CoroutineKind::Gen(hir::CoroutineSource::Closure) => "a gen closure", + hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Async, + hir::CoroutineSource::Block, + ) => "an async block", + hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Async, + hir::CoroutineSource::Fn, + ) => "an async function", + hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Async, + hir::CoroutineSource::Closure, + ) => "an async closure", + hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::AsyncGen, + hir::CoroutineSource::Block, + ) => "an async gen block", + hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::AsyncGen, + hir::CoroutineSource::Fn, + ) => "an async gen function", + hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::AsyncGen, + hir::CoroutineSource::Closure, + ) => "an async gen closure", + hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Gen, + hir::CoroutineSource::Block, + ) => "a gen block", + hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Gen, + hir::CoroutineSource::Fn, + ) => "a gen function", + hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Gen, + hir::CoroutineSource::Closure, + ) => "a gen closure", }) } @@ -3305,7 +3334,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { closure_def_id: DefId, found_kind: ty::ClosureKind, kind: ty::ClosureKind, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { let closure_span = self.tcx.def_span(closure_def_id); let mut err = ClosureKindMismatch { @@ -3347,7 +3376,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, terr: TypeError<'tcx>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { let self_ty = found_trait_ref.self_ty().skip_binder(); let (cause, terr) = if let ty::Closure(def_id, _) = self_ty.kind() { ( @@ -3367,7 +3396,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { &self, obligation: &PredicateObligation<'tcx>, def_id: DefId, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx> { let name = match self.tcx.opaque_type_origin(def_id.expect_local()) { hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_) => { "opaque type".to_string() @@ -3409,7 +3438,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { span: Span, found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, - ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { + ) -> Option<DiagnosticBuilder<'tcx>> { let found_trait_ref = self.resolve_vars_if_possible(found_trait_ref); let expected_trait_ref = self.resolve_vars_if_possible(expected_trait_ref); @@ -3515,7 +3544,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { &self, obligation: &PredicateObligation<'tcx>, span: Span, - ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { + ) -> Option<DiagnosticBuilder<'tcx>> { if !self.tcx.features().generic_const_exprs { let mut err = self .tcx diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index a5f11ca23e1..86501b5a72d 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -114,13 +114,13 @@ fn fn_sig_for_fn_abi<'tcx>( let pin_adt_ref = tcx.adt_def(pin_did); let pin_args = tcx.mk_args(&[env_ty.into()]); let env_ty = match coroutine_kind { - hir::CoroutineKind::Gen(_) => { + hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _) => { // Iterator::next doesn't accept a pinned argument, // unlike for all other coroutine kinds. env_ty } - hir::CoroutineKind::Async(_) - | hir::CoroutineKind::AsyncGen(_) + hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _) + | hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _) | hir::CoroutineKind::Coroutine => Ty::new_adt(tcx, pin_adt_ref, pin_args), }; @@ -131,7 +131,7 @@ fn fn_sig_for_fn_abi<'tcx>( // or the `Iterator::next(...) -> Option` function in case this is a // special coroutine backing a gen construct. let (resume_ty, ret_ty) = match coroutine_kind { - hir::CoroutineKind::Async(_) => { + hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _) => { // The signature should be `Future::poll(_, &mut Context<'_>) -> Poll<Output>` assert_eq!(sig.yield_ty, tcx.types.unit); @@ -156,7 +156,7 @@ fn fn_sig_for_fn_abi<'tcx>( (Some(context_mut_ref), ret_ty) } - hir::CoroutineKind::Gen(_) => { + hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _) => { // The signature should be `Iterator::next(_) -> Option<Yield>` let option_did = tcx.require_lang_item(LangItem::Option, None); let option_adt_ref = tcx.adt_def(option_did); @@ -168,7 +168,7 @@ fn fn_sig_for_fn_abi<'tcx>( (None, ret_ty) } - hir::CoroutineKind::AsyncGen(_) => { + hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _) => { // The signature should be // `AsyncIterator::poll_next(_, &mut Context<'_>) -> Poll<Option<Output>>` assert_eq!(sig.return_ty, tcx.types.unit); diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index b8fd9370aa6..89d75569ce3 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -288,27 +288,33 @@ impl AssertMessage { AssertMessage::ResumedAfterReturn(CoroutineKind::Coroutine) => { Ok("coroutine resumed after completion") } - AssertMessage::ResumedAfterReturn(CoroutineKind::Async(_)) => { - Ok("`async fn` resumed after completion") - } - AssertMessage::ResumedAfterReturn(CoroutineKind::Gen(_)) => { - Ok("`async gen fn` resumed after completion") - } - AssertMessage::ResumedAfterReturn(CoroutineKind::AsyncGen(_)) => { - Ok("`gen fn` should just keep returning `AssertMessage::None` after completion") - } + AssertMessage::ResumedAfterReturn(CoroutineKind::Desugared( + CoroutineDesugaring::Async, + _, + )) => Ok("`async fn` resumed after completion"), + AssertMessage::ResumedAfterReturn(CoroutineKind::Desugared( + CoroutineDesugaring::Gen, + _, + )) => Ok("`async gen fn` resumed after completion"), + AssertMessage::ResumedAfterReturn(CoroutineKind::Desugared( + CoroutineDesugaring::AsyncGen, + _, + )) => Ok("`gen fn` should just keep returning `AssertMessage::None` after completion"), AssertMessage::ResumedAfterPanic(CoroutineKind::Coroutine) => { Ok("coroutine resumed after panicking") } - AssertMessage::ResumedAfterPanic(CoroutineKind::Async(_)) => { - Ok("`async fn` resumed after panicking") - } - AssertMessage::ResumedAfterPanic(CoroutineKind::Gen(_)) => { - Ok("`async gen fn` resumed after panicking") - } - AssertMessage::ResumedAfterPanic(CoroutineKind::AsyncGen(_)) => { - Ok("`gen fn` should just keep returning `AssertMessage::None` after panicking") - } + AssertMessage::ResumedAfterPanic(CoroutineKind::Desugared( + CoroutineDesugaring::Async, + _, + )) => Ok("`async fn` resumed after panicking"), + AssertMessage::ResumedAfterPanic(CoroutineKind::Desugared( + CoroutineDesugaring::Gen, + _, + )) => Ok("`async gen fn` resumed after panicking"), + AssertMessage::ResumedAfterPanic(CoroutineKind::Desugared( + CoroutineDesugaring::AsyncGen, + _, + )) => Ok("`gen fn` should just keep returning `AssertMessage::None` after panicking"), AssertMessage::BoundsCheck { .. } => Ok("index out of bounds"), AssertMessage::MisalignedPointerDereference { .. } => { @@ -392,10 +398,8 @@ pub enum UnOp { #[derive(Clone, Debug, Eq, PartialEq)] pub enum CoroutineKind { - Async(CoroutineSource), + Desugared(CoroutineDesugaring, CoroutineSource), Coroutine, - Gen(CoroutineSource), - AsyncGen(CoroutineSource), } #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -405,6 +409,15 @@ pub enum CoroutineSource { Fn, } +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum CoroutineDesugaring { + Async, + + Gen, + + AsyncGen, +} + pub(crate) type LocalDefId = Opaque; /// The rustc coverage data structures are heavily tied to internal details of the /// coverage implementation that are likely to change, and are unlikely to be diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 62179756850..59f3a50ddb7 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1768,7 +1768,7 @@ impl<T: Clone, A: Allocator + Clone> Rc<T, A> { /// assert!(ptr::eq(ptr, inner.as_ptr())); /// ``` #[inline] - #[stable(feature = "arc_unwrap_or_clone", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "arc_unwrap_or_clone", since = "1.76.0")] pub fn unwrap_or_clone(this: Self) -> T { Rc::try_unwrap(this).unwrap_or_else(|rc| (*rc).clone()) } diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index e2e836bb975..85df491636a 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -2194,7 +2194,7 @@ impl<T: Clone, A: Allocator + Clone> Arc<T, A> { /// assert!(ptr::eq(ptr, inner.as_ptr())); /// ``` #[inline] - #[stable(feature = "arc_unwrap_or_clone", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "arc_unwrap_or_clone", since = "1.76.0")] pub fn unwrap_or_clone(this: Self) -> T { Arc::try_unwrap(this).unwrap_or_else(|arc| (*arc).clone()) } diff --git a/library/core/src/any.rs b/library/core/src/any.rs index c82984d5c6b..e8f00e8760e 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -729,7 +729,7 @@ pub const fn type_name<T: ?Sized>() -> &'static str { /// assert!(type_name_of_val(&y).contains("f32")); /// ``` #[must_use] -#[stable(feature = "type_name_of_val", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "type_name_of_val", since = "1.76.0")] #[rustc_const_unstable(feature = "const_type_name", issue = "63084")] pub const fn type_name_of_val<T: ?Sized>(_val: &T) -> &'static str { type_name::<T>() diff --git a/library/core/src/async_iter/async_iter.rs b/library/core/src/async_iter/async_iter.rs index 8a45bd36f7a..db71a286b6d 100644 --- a/library/core/src/async_iter/async_iter.rs +++ b/library/core/src/async_iter/async_iter.rs @@ -13,7 +13,7 @@ use crate::task::{Context, Poll}; #[unstable(feature = "async_iterator", issue = "79024")] #[must_use = "async iterators do nothing unless polled"] #[doc(alias = "Stream")] -#[cfg_attr(not(bootstrap), lang = "async_iterator")] +#[lang = "async_iterator"] pub trait AsyncIterator { /// The type of items yielded by the async iterator. type Item; @@ -47,6 +47,7 @@ pub trait AsyncIterator { /// Rust's usual rules apply: calls must never cause undefined behavior /// (memory corruption, incorrect use of `unsafe` functions, or the like), /// regardless of the async iterator's state. + #[cfg_attr(not(bootstrap), lang = "async_iterator_poll_next")] fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>>; /// Returns the bounds on the remaining length of the async iterator. @@ -116,7 +117,7 @@ impl<T> Poll<Option<T>> { /// A helper function for internal desugaring -- produces `Ready(Some(t))`, /// which corresponds to the async iterator yielding a value. #[unstable(feature = "async_gen_internals", issue = "none")] - #[cfg_attr(not(bootstrap), lang = "AsyncGenReady")] + #[lang = "AsyncGenReady"] pub fn async_gen_ready(t: T) -> Self { Poll::Ready(Some(t)) } @@ -124,13 +125,36 @@ impl<T> Poll<Option<T>> { /// A helper constant for internal desugaring -- produces `Pending`, /// which corresponds to the async iterator pending on an `.await`. #[unstable(feature = "async_gen_internals", issue = "none")] - #[cfg_attr(not(bootstrap), lang = "AsyncGenPending")] + #[lang = "AsyncGenPending"] // FIXME(gen_blocks): This probably could be deduplicated. pub const PENDING: Self = Poll::Pending; /// A helper constant for internal desugaring -- produces `Ready(None)`, /// which corresponds to the async iterator finishing its iteration. #[unstable(feature = "async_gen_internals", issue = "none")] - #[cfg_attr(not(bootstrap), lang = "AsyncGenFinished")] + #[lang = "AsyncGenFinished"] pub const FINISHED: Self = Poll::Ready(None); } + +/// Convert something into an async iterator +#[unstable(feature = "async_iterator", issue = "79024")] +pub trait IntoAsyncIterator { + /// The type of the item yielded by the iterator + type Item; + /// The type of the resulting iterator + type IntoAsyncIter: AsyncIterator<Item = Self::Item>; + + /// Converts `self` into an async iterator + #[cfg_attr(not(bootstrap), lang = "into_async_iter_into_iter")] + fn into_async_iter(self) -> Self::IntoAsyncIter; +} + +#[unstable(feature = "async_iterator", issue = "79024")] +impl<I: AsyncIterator> IntoAsyncIterator for I { + type Item = I::Item; + type IntoAsyncIter = I; + + fn into_async_iter(self) -> Self::IntoAsyncIter { + self + } +} diff --git a/library/core/src/async_iter/mod.rs b/library/core/src/async_iter/mod.rs index 0c6f637711b..e1f1c907582 100644 --- a/library/core/src/async_iter/mod.rs +++ b/library/core/src/async_iter/mod.rs @@ -124,5 +124,5 @@ mod async_iter; mod from_iter; -pub use async_iter::AsyncIterator; +pub use async_iter::{AsyncIterator, IntoAsyncIterator}; pub use from_iter::{from_iter, FromIter}; diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index d7c41ac5c06..bffd3b2af97 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -224,13 +224,13 @@ use self::Ordering::*; append_const_msg )] #[rustc_diagnostic_item = "PartialEq"] -#[cfg_attr(not(bootstrap), const_trait)] +#[const_trait] pub trait PartialEq<Rhs: ?Sized = Self> { /// This method tests for `self` and `other` values to be equal, and is used /// by `==`. #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(bootstrap), rustc_diagnostic_item = "cmp_partialeq_eq")] + #[rustc_diagnostic_item = "cmp_partialeq_eq"] fn eq(&self, other: &Rhs) -> bool; /// This method tests for `!=`. The default implementation is almost always @@ -238,7 +238,7 @@ pub trait PartialEq<Rhs: ?Sized = Self> { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(bootstrap), rustc_diagnostic_item = "cmp_partialeq_ne")] + #[rustc_diagnostic_item = "cmp_partialeq_ne"] fn ne(&self, other: &Rhs) -> bool { !self.eq(other) } @@ -1417,17 +1417,7 @@ mod impls { macro_rules! partial_eq_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - #[cfg(bootstrap)] - impl PartialEq for $t { - #[inline] - fn eq(&self, other: &$t) -> bool { (*self) == (*other) } - #[inline] - fn ne(&self, other: &$t) -> bool { (*self) != (*other) } - } - - #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] - #[cfg(not(bootstrap))] impl const PartialEq for $t { #[inline] fn eq(&self, other: &$t) -> bool { (*self) == (*other) } diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd.rs index 68c8a335b40..0fd27974dce 100644 --- a/library/core/src/intrinsics/simd.rs +++ b/library/core/src/intrinsics/simd.rs @@ -257,7 +257,6 @@ extern "platform-intrinsic" { /// type). /// /// `mask` must only contain `0` or `!0` values. - #[cfg(not(bootstrap))] pub fn simd_masked_load<V, U, T>(mask: V, ptr: U, val: T) -> T; /// Write to a vector of pointers. @@ -277,7 +276,6 @@ extern "platform-intrinsic" { /// type). /// /// `mask` must only contain `0` or `!0` values. - #[cfg(not(bootstrap))] pub fn simd_masked_store<V, U, T>(mask: V, ptr: U, val: T); /// Add two simd vectors elementwise, with saturation. diff --git a/library/core/src/option.rs b/library/core/src/option.rs index bfd6aee4a23..ff435349249 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1088,7 +1088,7 @@ impl<T> Option<T> { /// let x: Option<&usize> = v.get(5).inspect(|x| println!("got: {x}")); /// ``` #[inline] - #[stable(feature = "result_option_inspect", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "result_option_inspect", since = "1.76.0")] pub fn inspect<F: FnOnce(&T)>(self, f: F) -> Self { if let Some(ref x) = self { f(x); diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index a444c30c756..12ff64de879 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -1772,7 +1772,7 @@ impl<T> *const [T] { #[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized> PartialEq for *const T { #[inline] - #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))] + #[allow(ambiguous_wide_pointer_comparisons)] fn eq(&self, other: &*const T) -> bool { *self == *other } @@ -1785,7 +1785,7 @@ impl<T: ?Sized> Eq for *const T {} #[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized> Ord for *const T { #[inline] - #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))] + #[allow(ambiguous_wide_pointer_comparisons)] fn cmp(&self, other: &*const T) -> Ordering { if self < other { Less @@ -1805,25 +1805,25 @@ impl<T: ?Sized> PartialOrd for *const T { } #[inline] - #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))] + #[allow(ambiguous_wide_pointer_comparisons)] fn lt(&self, other: &*const T) -> bool { *self < *other } #[inline] - #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))] + #[allow(ambiguous_wide_pointer_comparisons)] fn le(&self, other: &*const T) -> bool { *self <= *other } #[inline] - #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))] + #[allow(ambiguous_wide_pointer_comparisons)] fn gt(&self, other: &*const T) -> bool { *self > *other } #[inline] - #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))] + #[allow(ambiguous_wide_pointer_comparisons)] fn ge(&self, other: &*const T) -> bool { *self >= *other } diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index eed793186b9..a9078854125 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -720,8 +720,8 @@ where /// type or mutability, in particular if the code is refactored. #[inline(always)] #[must_use] -#[stable(feature = "ptr_from_ref", since = "CURRENT_RUSTC_VERSION")] -#[rustc_const_stable(feature = "ptr_from_ref", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "ptr_from_ref", since = "1.76.0")] +#[rustc_const_stable(feature = "ptr_from_ref", since = "1.76.0")] #[rustc_never_returns_null_ptr] #[rustc_diagnostic_item = "ptr_from_ref"] pub const fn from_ref<T: ?Sized>(r: &T) -> *const T { @@ -734,8 +734,8 @@ pub const fn from_ref<T: ?Sized>(r: &T) -> *const T { /// type or mutability, in particular if the code is refactored. #[inline(always)] #[must_use] -#[stable(feature = "ptr_from_ref", since = "CURRENT_RUSTC_VERSION")] -#[rustc_const_stable(feature = "ptr_from_ref", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "ptr_from_ref", since = "1.76.0")] +#[rustc_const_stable(feature = "ptr_from_ref", since = "1.76.0")] #[rustc_allow_const_fn_unstable(const_mut_refs)] #[rustc_never_returns_null_ptr] pub const fn from_mut<T: ?Sized>(r: &mut T) -> *mut T { @@ -1900,7 +1900,7 @@ pub(crate) const unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usiz #[inline(always)] #[must_use = "pointer comparison produces a value"] #[rustc_diagnostic_item = "ptr_eq"] -#[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))] // it's actually clear here +#[allow(ambiguous_wide_pointer_comparisons)] // it's actually clear here pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool { a == b } @@ -1922,7 +1922,7 @@ pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool { /// assert!(ptr::addr_eq(whole, first)); /// assert!(!ptr::eq::<dyn std::fmt::Debug>(whole, first)); /// ``` -#[stable(feature = "ptr_addr_eq", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "ptr_addr_eq", since = "1.76.0")] #[inline(always)] #[must_use = "pointer comparison produces a value"] pub fn addr_eq<T: ?Sized, U: ?Sized>(p: *const T, q: *const U) -> bool { diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 9e7b8ec64ac..4f5fca4367d 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -2199,7 +2199,7 @@ impl<T> *mut [T] { #[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized> PartialEq for *mut T { #[inline(always)] - #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))] + #[allow(ambiguous_wide_pointer_comparisons)] fn eq(&self, other: &*mut T) -> bool { *self == *other } @@ -2211,7 +2211,7 @@ impl<T: ?Sized> Eq for *mut T {} #[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized> Ord for *mut T { #[inline] - #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))] + #[allow(ambiguous_wide_pointer_comparisons)] fn cmp(&self, other: &*mut T) -> Ordering { if self < other { Less @@ -2231,25 +2231,25 @@ impl<T: ?Sized> PartialOrd for *mut T { } #[inline(always)] - #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))] + #[allow(ambiguous_wide_pointer_comparisons)] fn lt(&self, other: &*mut T) -> bool { *self < *other } #[inline(always)] - #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))] + #[allow(ambiguous_wide_pointer_comparisons)] fn le(&self, other: &*mut T) -> bool { *self <= *other } #[inline(always)] - #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))] + #[allow(ambiguous_wide_pointer_comparisons)] fn gt(&self, other: &*mut T) -> bool { *self > *other } #[inline(always)] - #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))] + #[allow(ambiguous_wide_pointer_comparisons)] fn ge(&self, other: &*mut T) -> bool { *self >= *other } diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 77961506e13..427a9f3f494 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -1791,7 +1791,7 @@ impl<T: ?Sized> Eq for NonNull<T> {} #[stable(feature = "nonnull", since = "1.25.0")] impl<T: ?Sized> PartialEq for NonNull<T> { #[inline] - #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))] + #[allow(ambiguous_wide_pointer_comparisons)] fn eq(&self, other: &Self) -> bool { self.as_ptr() == other.as_ptr() } diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 90c346e98bc..eff1b9b59b1 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -842,7 +842,7 @@ impl<T, E> Result<T, E> { /// .expect("failed to parse number"); /// ``` #[inline] - #[stable(feature = "result_option_inspect", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "result_option_inspect", since = "1.76.0")] pub fn inspect<F: FnOnce(&T)>(self, f: F) -> Self { if let Ok(ref t) = self { f(t); @@ -864,7 +864,7 @@ impl<T, E> Result<T, E> { /// } /// ``` #[inline] - #[stable(feature = "result_option_inspect", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "result_option_inspect", since = "1.76.0")] pub fn inspect_err<F: FnOnce(&E)>(self, f: F) -> Self { if let Err(ref e) = self { f(e); diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs index 3689312e6ae..e1b77e34f21 100644 --- a/library/core/src/tuple.rs +++ b/library/core/src/tuple.rs @@ -8,146 +8,6 @@ use crate::marker::{StructuralEq, StructuralPartialEq}; // // Also provides implementations for tuples with lesser arity. For example, tuple_impls!(A B C) // will implement everything for (A, B, C), (A, B) and (A,). -#[cfg(bootstrap)] -macro_rules! tuple_impls { - // Stopping criteria (1-ary tuple) - ($T:ident) => { - tuple_impls!(@impl $T); - }; - // Running criteria (n-ary tuple, with n >= 2) - ($T:ident $( $U:ident )+) => { - tuple_impls!($( $U )+); - tuple_impls!(@impl $T $( $U )+); - }; - // "Private" internal implementation - (@impl $( $T:ident )+) => { - maybe_tuple_doc! { - $($T)+ @ - #[stable(feature = "rust1", since = "1.0.0")] - impl<$($T: PartialEq),+> PartialEq for ($($T,)+) - where - last_type!($($T,)+): ?Sized - { - #[inline] - fn eq(&self, other: &($($T,)+)) -> bool { - $( ${ignore(T)} self.${index()} == other.${index()} )&&+ - } - #[inline] - fn ne(&self, other: &($($T,)+)) -> bool { - $( ${ignore(T)} self.${index()} != other.${index()} )||+ - } - } - } - - maybe_tuple_doc! { - $($T)+ @ - #[stable(feature = "rust1", since = "1.0.0")] - impl<$($T: Eq),+> Eq for ($($T,)+) - where - last_type!($($T,)+): ?Sized - {} - } - - maybe_tuple_doc! { - $($T)+ @ - #[unstable(feature = "structural_match", issue = "31434")] - impl<$($T: ConstParamTy),+> ConstParamTy for ($($T,)+) {} - } - - maybe_tuple_doc! { - $($T)+ @ - #[unstable(feature = "structural_match", issue = "31434")] - impl<$($T),+> StructuralPartialEq for ($($T,)+) {} - } - - maybe_tuple_doc! { - $($T)+ @ - #[unstable(feature = "structural_match", issue = "31434")] - impl<$($T),+> StructuralEq for ($($T,)+) {} - } - - maybe_tuple_doc! { - $($T)+ @ - #[stable(feature = "rust1", since = "1.0.0")] - impl<$($T: PartialOrd),+> PartialOrd for ($($T,)+) - where - last_type!($($T,)+): ?Sized - { - #[inline] - fn partial_cmp(&self, other: &($($T,)+)) -> Option<Ordering> { - lexical_partial_cmp!($( ${ignore(T)} self.${index()}, other.${index()} ),+) - } - #[inline] - fn lt(&self, other: &($($T,)+)) -> bool { - lexical_ord!(lt, Less, $( ${ignore(T)} self.${index()}, other.${index()} ),+) - } - #[inline] - fn le(&self, other: &($($T,)+)) -> bool { - lexical_ord!(le, Less, $( ${ignore(T)} self.${index()}, other.${index()} ),+) - } - #[inline] - fn ge(&self, other: &($($T,)+)) -> bool { - lexical_ord!(ge, Greater, $( ${ignore(T)} self.${index()}, other.${index()} ),+) - } - #[inline] - fn gt(&self, other: &($($T,)+)) -> bool { - lexical_ord!(gt, Greater, $( ${ignore(T)} self.${index()}, other.${index()} ),+) - } - } - } - - maybe_tuple_doc! { - $($T)+ @ - #[stable(feature = "rust1", since = "1.0.0")] - impl<$($T: Ord),+> Ord for ($($T,)+) - where - last_type!($($T,)+): ?Sized - { - #[inline] - fn cmp(&self, other: &($($T,)+)) -> Ordering { - lexical_cmp!($( ${ignore(T)} self.${index()}, other.${index()} ),+) - } - } - } - - maybe_tuple_doc! { - $($T)+ @ - #[stable(feature = "rust1", since = "1.0.0")] - impl<$($T: Default),+> Default for ($($T,)+) { - #[inline] - fn default() -> ($($T,)+) { - ($($T::default(),)+) - } - } - } - - #[stable(feature = "array_tuple_conv", since = "1.71.0")] - impl<T> From<[T; ${count(T)}]> for ($(${ignore(T)} T,)+) { - #[inline] - #[allow(non_snake_case)] - fn from(array: [T; ${count(T)}]) -> Self { - let [$($T,)+] = array; - ($($T,)+) - } - } - - #[stable(feature = "array_tuple_conv", since = "1.71.0")] - impl<T> From<($(${ignore(T)} T,)+)> for [T; ${count(T)}] { - #[inline] - #[allow(non_snake_case)] - fn from(tuple: ($(${ignore(T)} T,)+)) -> Self { - let ($($T,)+) = tuple; - [$($T,)+] - } - } - } -} - -// Recursive macro for implementing n-ary tuple functions and operations -// -// Also provides implementations for tuples with lesser arity. For example, tuple_impls!(A B C) -// will implement everything for (A, B, C), (A, B) and (A,). -#[cfg(not(bootstrap))] macro_rules! tuple_impls { // Stopping criteria (1-ary tuple) ($T:ident) => { diff --git a/library/core/tests/async_iter/mod.rs b/library/core/tests/async_iter/mod.rs new file mode 100644 index 00000000000..0c30bd1dfea --- /dev/null +++ b/library/core/tests/async_iter/mod.rs @@ -0,0 +1,17 @@ +use core::async_iter::{self, AsyncIterator, IntoAsyncIterator}; +use core::pin::pin; +use core::task::Poll; + +#[test] +fn into_async_iter() { + let async_iter = async_iter::from_iter(0..3); + let mut async_iter = pin!(async_iter.into_async_iter()); + + let waker = core::task::Waker::noop(); + let mut cx = &mut core::task::Context::from_waker(&waker); + + assert_eq!(async_iter.as_mut().poll_next(&mut cx), Poll::Ready(Some(0))); + assert_eq!(async_iter.as_mut().poll_next(&mut cx), Poll::Ready(Some(1))); + assert_eq!(async_iter.as_mut().poll_next(&mut cx), Poll::Ready(Some(2))); + assert_eq!(async_iter.as_mut().poll_next(&mut cx), Poll::Ready(None)); +} diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index c531117bed5..b53cf459244 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -4,6 +4,8 @@ #![feature(array_windows)] #![feature(ascii_char)] #![feature(ascii_char_variants)] +#![feature(async_iter_from_iter)] +#![feature(async_iterator)] #![feature(bigint_helper_methods)] #![feature(cell_update)] #![feature(const_align_offset)] @@ -55,6 +57,7 @@ #![feature(maybe_uninit_write_slice)] #![feature(maybe_uninit_uninit_array_transpose)] #![feature(min_specialization)] +#![feature(noop_waker)] #![feature(numfmt)] #![feature(num_midpoint)] #![feature(isqrt)] @@ -111,7 +114,6 @@ #![feature(slice_flatten)] #![feature(error_generic_member_access)] #![feature(error_in_core)] -#![cfg_attr(bootstrap, feature(trait_upcasting))] #![feature(utf8_chunks)] #![feature(is_ascii_octdigit)] #![feature(get_many_mut)] @@ -126,6 +128,7 @@ mod any; mod array; mod ascii; mod asserting; +mod async_iter; mod atomic; mod bool; mod cell; diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 4310e108303..38050cf684f 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -411,8 +411,6 @@ impl File { /// # Examples /// /// ```no_run - /// #![feature(file_create_new)] - /// /// use std::fs::File; /// use std::io::Write; /// @@ -422,7 +420,7 @@ impl File { /// Ok(()) /// } /// ``` - #[unstable(feature = "file_create_new", issue = "105135")] + #[stable(feature = "file_create_new", since = "CURRENT_RUSTC_VERSION")] pub fn create_new<P: AsRef<Path>>(path: P) -> io::Result<File> { OpenOptions::new().read(true).write(true).create_new(true).open(path.as_ref()) } diff --git a/library/std/src/hash/mod.rs b/library/std/src/hash/mod.rs index bd9bbf29875..e5ef9e33597 100644 --- a/library/std/src/hash/mod.rs +++ b/library/std/src/hash/mod.rs @@ -87,5 +87,5 @@ pub(crate) mod random; #[stable(feature = "rust1", since = "1.0.0")] pub use core::hash::*; -#[stable(feature = "std_hash_exports", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "std_hash_exports", since = "1.76.0")] pub use self::random::{DefaultHasher, RandomState}; diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 76081833e05..70b9aab9161 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -308,7 +308,6 @@ // // Library features (core): // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(c_str_literals))] #![feature(char_internals)] #![feature(core_intrinsics)] #![feature(core_io_borrowed_buf)] diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index cf3f5bc983e..57e63927c95 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -1001,6 +1001,7 @@ tool_doc!( "cargo-test-macro", "cargo-test-support", "cargo-util", + "cargo-util-schemas", "crates-io", "mdman", "rustfix", diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 56bdc9aaef1..753b41abaf4 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -1221,11 +1221,6 @@ impl<'a> Builder<'a> { cmd.arg("-Dwarnings"); } cmd.arg("-Znormalize-docs"); - - // Remove make-related flags that can cause jobserver problems. - cmd.env_remove("MAKEFLAGS"); - cmd.env_remove("MFLAGS"); - cmd.args(linker_args(self, compiler.host, LldThreads::Yes)); cmd } diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index 636692a0954..55eed95492d 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -36,6 +36,11 @@ root_dir="`dirname $src_dir`" objdir=$root_dir/obj dist=$objdir/build/dist + +if [ -d "$root_dir/.git" ]; then + IS_GIT_SOURCE=1 +fi + source "$ci_dir/shared.sh" CACHE_DOMAIN="${CACHE_DOMAIN:-ci-caches.rust-lang.org}" @@ -194,6 +199,14 @@ else args="$args --env SCCACHE_DIR=/sccache --volume $HOME/.cache/sccache:/sccache" fi +# By default, container volumes are bound as read-only; therefore doing experimental work +# or debugging within the container environment (such as fetching submodules and +# building them) is not possible. Setting READ_ONLY_SRC to 0 enables this capability by +# binding the volumes in read-write mode. +if [ "$READ_ONLY_SRC" != "0" ]; then + SRC_MOUNT_OPTION=":ro" +fi + # Run containers as privileged as it should give them access to some more # syscalls such as ptrace and whatnot. In the upgrade to LLVM 5.0 it was # discovered that the leak sanitizer apparently needs these syscalls nowadays so @@ -228,7 +241,7 @@ if [ -f /.dockerenv ]; then docker cp . checkout:/checkout args="$args --volumes-from checkout" else - args="$args --volume $root_dir:/checkout:ro" + args="$args --volume $root_dir:/checkout$SRC_MOUNT_OPTION" args="$args --volume $objdir:/checkout/obj" args="$args --volume $HOME/.cargo:/cargo" args="$args --volume $HOME/rustsrc:$HOME/rustsrc" @@ -249,9 +262,13 @@ if [ "$dev" = "1" ] then # Interactive + TTY args="$args -it" - command="/bin/bash" + if [ $IS_GIT_SOURCE -eq 1 ]; then + command=(/bin/bash -c 'git config --global --add safe.directory /checkout;bash') + else + command=(/bin/bash) + fi else - command="/checkout/src/ci/run.sh" + command=(/checkout/src/ci/run.sh) fi if [ "$CI" != "" ]; then @@ -301,7 +318,7 @@ docker \ --init \ --rm \ rust-ci \ - $command + "${command[@]}" cat $objdir/${SUMMARY_FILE} >> "${GITHUB_STEP_SUMMARY}" diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index 800d8920951..3af370bf006 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -471,6 +471,11 @@ jobs: <<: *job-linux-4c - name: x86_64-gnu-integration + env: + # Only run this job on the nightly channel. Fuchsia requires + # nightly features to compile, and this job would fail if + # executed on beta and stable. + CI_ONLY_WHEN_CHANNEL: nightly <<: *job-linux-16c - name: x86_64-gnu-debug diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index fadd64a0353..1c8e1d1e316 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -38,6 +38,7 @@ - [\*-unknown-fuchsia](platform-support/fuchsia.md) - [\*-kmc-solid_\*](platform-support/kmc-solid.md) - [csky-unknown-linux-gnuabiv2\*](platform-support/csky-unknown-linux-gnuabiv2.md) + - [hexagon-unknown-none-elf](platform-support/hexagon-unknown-none-elf.md) - [loongarch\*-unknown-linux-\*](platform-support/loongarch-linux.md) - [loongarch\*-unknown-none\*](platform-support/loongarch-none.md) - [m68k-unknown-linux-gnu](platform-support/m68k-unknown-linux-gnu.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 59ef7441024..09070168b67 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -230,6 +230,7 @@ target | std | host | notes [`aarch64-unknown-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | ARM64 QNX Neutrino 7.1 RTOS | `aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD [`aarch64-unknown-hermit`](platform-support/hermit.md) | ✓ | | ARM64 Hermit +`aarch64-unknown-illumos` | ✓ | ✓ | ARM64 illumos `aarch64-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (ILP32 ABI) [`aarch64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | ARM64 NetBSD [`aarch64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | ARM64 OpenBSD @@ -265,6 +266,7 @@ target | std | host | notes `bpfel-unknown-none` | * | | BPF (little endian) `csky-unknown-linux-gnuabiv2` | ✓ | | C-SKY abiv2 Linux (little endian) `csky-unknown-linux-gnuabiv2hf` | ✓ | | C-SKY abiv2 Linux, hardfloat (little endian) +[`hexagon-unknown-none-elf`](platform-support/hexagon-unknown-none-elf.md)| * | Bare Hexagon (v60+, HVX) `hexagon-unknown-linux-musl` | ? | | `i386-apple-ios` | ✓ | | 32-bit x86 iOS [^x86_32-floats-return-ABI] [`i586-pc-nto-qnx700`](platform-support/nto-qnx.md) | * | | 32-bit x86 QNX Neutrino 7.0 RTOS [^x86_32-floats-return-ABI] diff --git a/src/doc/rustc/src/platform-support/hexagon-unknown-none-elf.md b/src/doc/rustc/src/platform-support/hexagon-unknown-none-elf.md new file mode 100644 index 00000000000..06423f0f8fa --- /dev/null +++ b/src/doc/rustc/src/platform-support/hexagon-unknown-none-elf.md @@ -0,0 +1,266 @@ +# `hexagon-unknown-none-elf` + +**Tier: 3** + +Rust for baremetal Hexagon DSPs. + +| Target | Descriptions | +| ------------------------ | ----------------------------------------- | +| hexagon-unknown-none-elf | Hexagon 32-bit (freestanding, hardfloat) | + +## Target maintainers + +- [Brian Cain](https://github.com/androm3da), `bcain@quicinc.com` + +## Requirements + +This target is cross-compiled. There is no support for `std`. There is no +default allocator, but it's possible to use `alloc` by supplying an allocator. + +By default, code generated with this target should run on Hexagon DSP hardware. + +- `-Ctarget-cpu=hexagonv73` adds support for instructions defined up to Hexagon V73. + +Functions marked `extern "C"` use the [Hexagon architecture calling convention](https://lists.llvm.org/pipermail/llvm-dev/attachments/20190916/21516a52/attachment-0001.pdf). + +This target generates PIC ELF binaries. + +## Building the target + +You can build Rust with support for the target by adding it to the `target` +list in `config.toml`: + +```toml +[build] +build-stage = 1 +host = ["<target for your host>"] +target = ["<target for your host>", "hexagon-unknown-none-elf"] + +[target.hexagon-unknown-none-elf] + +cc = "hexagon-unknown-none-elf-clang" +cxx = "hexagon-unknown-none-elf-clang++" +linker = "hexagon-unknown-none-elf-clang" +llvm-libunwind = 'in-tree' +``` + +Replace `<target for your host>` with `x86_64-unknown-linux-gnu` or whatever +else is appropriate for your host machine. + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for this target. To compile for +this target, you will either need to build Rust with the target enabled (see +"Building the target" above), or build your own copy of `core` by using +`build-std` or similar. + +## Testing + +Since `hexagon-unknown-none-elf` supports a variety of different environments and +does not support `std`, this target does not support running the Rust test suite. + +## Cross-compilation toolchains and C code + +This target has been tested using `qemu-system-hexagon`. + +A common use case for `hexagon-unknown-none-elf` is building libraries that +link against C code and can be used in emulation or on a device with a +Hexagon DSP. + +The Hexagon SDK has libraries which are useful to link against when running +on a device. + + +# Standalone OS + +The script below will build an executable against "hexagon standalone OS" +which is suitable for emulation or bare-metal on-device testing. + +First, run `cargo new --bin demo1_hexagon` then add the source below as +`src/main.rs`. This program demonstrates the console output via semihosting. + +```rust,ignore (platform-specific,eh-personality-is-unstable) +#![no_std] +#![no_main] + +extern "C" { + fn putchar(ch: i32); + fn _exit(code: i32) -> !; +} + +#[no_mangle] +extern "C" fn main() -> i32 { + let message = "Hello, this is Rust!"; + for b in message.bytes() { + unsafe { + putchar(b as i32); + } + } + 0 +} + +#[panic_handler] +fn panic(_panic: &core::panic::PanicInfo) -> ! { + unsafe { + _exit(1); + } +} + +``` + +Next, save the script below as `build.sh` and edit it to suit your +environment. + +* `hex_toolchain` below refers to the [hexagon toolchain using exclusively +public open source repos](https://github.com/quic/toolchain_for_hexagon/releases). +* `cc` below refers to clang. You can use `clang` from your distribution, as +long as it's at least `clang-17`. Or you can use +`hexagon-unknown-none-elf-clang` from one of the [hexagon open source toolchain +releases](https://github.com/quic/toolchain_for_hexagon/releases). + +```sh +# Hexagon SDK, required for target libraries: +hex_sdk_root=/local/mnt/workspace/Qualcomm/Hexagon_SDK/5.3.0.0 +hex_sdk_toolchain=${hex_sdk_root}/tools/HEXAGON_Tools/8.6.06 + +sdk_libs=${hex_sdk_toolchain}/Tools/target/hexagon/lib +q6_arch=v65 +g0_lib_path=${sdk_libs}/${q6_arch}/G0 +pic_lib_path=${sdk_libs}/${q6_arch}/G0/pic + +cargo build --target=hexagon-unknown-none-elf -Zbuild-std + +# Builds an executable against "hexagon standalone OS" suitable for emulation: +${cc} --target=hexagon-unknown-none-elf -o testit \ + -fuse-ld=lld \ + -m${q6_arch} \ + -nodefaultlibs \ + -nostartfiles \ + ${g0_lib_path}/crt0_standalone.o \ + ${g0_lib_path}/crt0.o \ + ${g0_lib_path}/init.o \ + -L${sdk_libs}/${q6_arch}/ \ + -L${sdk_libs}/ \ + testit.c \ + target/hexagon-unknown-none-elf/debug/libmin_ex_lib_lin.rlib \ + target/hexagon-unknown-none-elf/debug/deps/libcore-*.rlib \ + target/hexagon-unknown-none-elf/debug/deps/libcompiler_builtins-*.rlib \ + -Wl,--start-group \ + -Wl,--defsym,_SDA_BASE_=0,--defsym,__sbss_start=0,--defsym,__sbss_end=0 \ + -lstandalone \ + ${g0_lib_path}/libc.a \ + -lgcc \ + -lc_eh \ + -Wl,--end-group \ + ${g0_lib_path}/fini.o \ + +${hex_toolchain}/x86_64-linux-gnu/bin/qemu-system-hexagon -monitor none -display none -kernel ./testit +``` + +# QuRT OS + +First, run `cargo new --lib demo2_hexagon` then add the source below as +`src/lib.rs`. This program demonstrates inline assembly and console output +via semihosting. + +```rust,ignore (platform-specific,eh-personality-is-unstable) +#![no_std] +#![no_main] +#![feature(lang_items)] +#![feature(asm_experimental_arch)] + +use core::arch::asm; + +extern "C" { + fn putchar(ch: i32); + fn _exit(code: i32) -> !; +} + +fn hexagon_specific() { + let mut buffer = [0_u8; 128]; + + unsafe { + let mut x = &buffer; + asm!( + "{{\n\t", + " v0=vmem({addr}+#0)\n\t", + " {tmp} = and({tmp}, #1)\n\t", + "}}\n\t", + addr = in(reg) x, + tmp = out(reg) _, + ); + } +} + +#[no_mangle] +extern "C" fn hello() -> i32 { + let message = "Hello, this is Rust!\n"; + for b in message.bytes() { + unsafe { + putchar(b as i32); + } + } + hexagon_specific(); + 0 +} + +#[panic_handler] +fn panic(_panic: &core::panic::PanicInfo) -> ! { + unsafe { + _exit(1); + } +} + +#[lang = "eh_personality"] +fn rust_eh_personality() {} + +``` + +Next, save the script below as `build.sh` and edit it to suit your +environment. The script below will build a shared object against the QuRT +RTOS which is suitable for emulation or on-device testing when loaded via +the fastrpc-shell. + + +```sh +# Hexagon SDK, required for target libraries: +hex_sdk_root=/local/mnt/workspace/Qualcomm/Hexagon_SDK/5.3.0.0 +hex_sdk_toolchain=${hex_sdk_root}/tools/HEXAGON_Tools/8.6.06 + +sdk_libs=${hex_sdk_toolchain}/Tools/target/hexagon/lib +q6_arch=v65 +g0_lib_path=${sdk_libs}/${q6_arch}/G0 +pic_lib_path=${sdk_libs}/${q6_arch}/G0/pic +runelf=${hex_sdk_root}/rtos/qurt/computev65/sdksim_bin/runelf.pbn +rmohs=${hex_sdk_root}/libs/run_main_on_hexagon/ship/hexagon_toolv86_${q6_arch}/run_main_on_hexagon_sim + +# Builds a library suitable for loading into "run_main_on_hexagon_sim" for +# emulation or frpc shell on real target: +${cc} --target=hexagon-unknown-none-elf -o testit.so \ + -fuse-ld=lld \ + -fPIC -shared \ + -nostdlib \ + -Wl,-Bsymbolic \ + -Wl,--wrap=malloc \ + -Wl,--wrap=calloc \ + -Wl,--wrap=free \ + -Wl,--wrap=realloc \ + -Wl,--wrap=memalign \ + -m${q6_arch} \ + testit.c \ + target/hexagon-unknown-none-elf/debug/libmin_ex_lib_lin.rlib \ + target/hexagon-unknown-none-elf/debug/deps/libcore-*.rlib \ + target/hexagon-unknown-none-elf/debug/deps/libcompiler_builtins-*.rlib \ + -Wl,-soname=testit \ + ${pic_lib_path}/libc.so + +# -Bsymbolic above for memory alloc funcs is necessary to access the heap on +# target, but otherwise not required. + +# multi-stage loader: runelf => run_main_on_hexagon_sim => testit.so{`main`} +${hex_toolchain}/x86_64-linux-gnu/bin/qemu-system-hexagon \ + -monitor none \ + -display none \ + -kernel ${runelf} \ + -append "${rmohs} -- ./testit.so" +``` diff --git a/src/doc/rustc/src/platform-support/wasm32-wasi-preview1-threads.md b/src/doc/rustc/src/platform-support/wasm32-wasi-preview1-threads.md index 23b99924899..b719cb53aba 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wasi-preview1-threads.md +++ b/src/doc/rustc/src/platform-support/wasm32-wasi-preview1-threads.md @@ -90,7 +90,7 @@ The target intends to match the corresponding Clang target for its `"C"` ABI. ## Platform requirements -The runtime should support the same set of APIs as any other supported wasi target for interacting with the host environment through the WASI standard. The runtime also should have implemetation of [wasi-threads proposal](https://github.com/WebAssembly/wasi-threads). +The runtime should support the same set of APIs as any other supported wasi target for interacting with the host environment through the WASI standard. The runtime also should have implementation of [wasi-threads proposal](https://github.com/WebAssembly/wasi-threads). This target is not a stable target. This means that there are a few engines which implement the `wasi-threads` feature and if they do they're likely behind a diff --git a/src/doc/rustdoc/src/how-to-write-documentation.md b/src/doc/rustdoc/src/how-to-write-documentation.md index acab1a93690..8994c01f824 100644 --- a/src/doc/rustdoc/src/how-to-write-documentation.md +++ b/src/doc/rustdoc/src/how-to-write-documentation.md @@ -267,6 +267,22 @@ you can wrap it like this: /// more documentation ``` +Please note that if you want to put markdown in the HTML tag and for it to +be interpreted as such, you need to have an empty line between the HTML tags +and your markdown content. For example if you want to use a link: + +```md +/// documentation +/// +/// <div class="warning"> +/// +/// Go to [this link](https://rust-lang.org)! +/// +/// </div> +/// +/// more documentation +``` + [`backtrace`]: https://docs.rs/backtrace/0.3.50/backtrace/ [commonmark markdown specification]: https://commonmark.org/ [commonmark quick reference]: https://commonmark.org/help/ diff --git a/src/doc/rustdoc/src/lints.md b/src/doc/rustdoc/src/lints.md index f15e6e451e7..7d573ac950d 100644 --- a/src/doc/rustdoc/src/lints.md +++ b/src/doc/rustdoc/src/lints.md @@ -415,9 +415,9 @@ warning: 1 warning emitted ## `redundant_explicit_links` -This lint is **warned by default**. It detects explicit links that are same +This lint is **warn-by-default**. It detects explicit links that are the same as computed automatic links. -This usually means the explicit links is removeable. For example: +This usually means the explicit links are removeable. For example: ```rust #![warn(rustdoc::redundant_explicit_links)] // note: unnecessary - warns by default. diff --git a/src/doc/unstable-book/src/compiler-flags/check-cfg.md b/src/doc/unstable-book/src/compiler-flags/check-cfg.md index a5b9169c9f3..8ab6e83d99e 100644 --- a/src/doc/unstable-book/src/compiler-flags/check-cfg.md +++ b/src/doc/unstable-book/src/compiler-flags/check-cfg.md @@ -107,7 +107,7 @@ fn poke_platypus() {} fn tame_lion() {} // This is UNEXPECTED, because 'windows' is a well known condition name, -// and because 'windows' doens't take any values, +// and because 'windows' doesn't take any values, // and will cause a compiler warning (by default). #[cfg(windows = "unix")] fn tame_windows() {} diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index e692f4ef72e..9de547ba6dc 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -195,7 +195,7 @@ where // into a map. Each RegionTarget (either a RegionVid or a Region) maps // to its smaller and larger regions. Note that 'larger' regions correspond // to sub-regions in Rust code (e.g., in 'a: 'b, 'a is the larger region). - for constraint in regions.constraints.keys() { + for (constraint, _) in ®ions.constraints { match *constraint { Constraint::VarSubVar(r1, r2) => { { diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index fb09d399b98..f3d63fad711 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -403,7 +403,7 @@ impl Options { && !matches.opt_present("show-coverage") && !nightly_options::is_unstable_enabled(matches) { - early_dcx.early_error( + early_dcx.early_fatal( "the -Z unstable-options flag must be passed to enable --output-format for documentation generation (see https://github.com/rust-lang/rust/issues/76578)", ); } diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 61376ab31dd..513e94afe29 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -648,10 +648,12 @@ impl FromWithTcx<clean::Trait> for Trait { fn from_tcx(trait_: clean::Trait, tcx: TyCtxt<'_>) -> Self { let is_auto = trait_.is_auto(tcx); let is_unsafe = trait_.unsafety(tcx) == rustc_hir::Unsafety::Unsafe; + let is_object_safe = trait_.is_object_safe(tcx); let clean::Trait { items, generics, bounds, .. } = trait_; Trait { is_auto, is_unsafe, + is_object_safe, items: ids(items, tcx), generics: generics.into_tcx(tcx), bounds: bounds.into_tcx(tcx), diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 52803c2b005..19db429ad8a 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -194,10 +194,10 @@ fn init_logging(early_dcx: &EarlyDiagCtxt) { Ok("always") => true, Ok("never") => false, Ok("auto") | Err(VarError::NotPresent) => io::stdout().is_terminal(), - Ok(value) => early_dcx.early_error(format!( + Ok(value) => early_dcx.early_fatal(format!( "invalid log color value '{value}': expected one of always, never, or auto", )), - Err(VarError::NotUnicode(value)) => early_dcx.early_error(format!( + Err(VarError::NotUnicode(value)) => early_dcx.early_fatal(format!( "invalid log color value '{}': expected one of always, never, or auto", value.to_string_lossy() )), @@ -727,7 +727,7 @@ fn main_args( let matches = match options.parse(&args) { Ok(m) => m, Err(err) => { - early_dcx.early_error(err.to_string()); + early_dcx.early_fatal(err.to_string()); } }; diff --git a/src/librustdoc/lint.rs b/src/librustdoc/lint.rs index 267f1cb0b72..f78743a7917 100644 --- a/src/librustdoc/lint.rs +++ b/src/librustdoc/lint.rs @@ -186,8 +186,8 @@ declare_rustdoc_lint! { } declare_rustdoc_lint! { - /// This lint is **warned by default**. It detects explicit links that are same - /// as computed automatic links. This usually means the explicit links is removeable. + /// This lint is **warn-by-default**. It detects explicit links that are the same + /// as computed automatic links. This usually means the explicit links are removeable. /// This is a `rustdoc` only lint, see the documentation in the [rustdoc book]. /// /// [rustdoc book]: ../../../rustdoc/lints.html#redundant_explicit_links diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs index ce42b9c204b..53c7f0f6e15 100644 --- a/src/librustdoc/passes/lint/check_code_block_syntax.rs +++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs @@ -161,7 +161,7 @@ impl Emitter for BufferEmitter { let fluent_args = to_fluent_args(diag.args()); let translated_main_message = self - .translate_message(&diag.message[0].0, &fluent_args) + .translate_message(&diag.messages[0].0, &fluent_args) .unwrap_or_else(|e| panic!("{e}")); buffer.messages.push(format!("error from rustc: {translated_main_message}")); diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 5d979521885..164f88faa31 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize}; use std::path::PathBuf; /// rustdoc format-version. -pub const FORMAT_VERSION: u32 = 27; +pub const FORMAT_VERSION: u32 = 28; /// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information /// about the language items in the local crate, as well as info about external items to allow @@ -634,6 +634,7 @@ pub struct FnDecl { pub struct Trait { pub is_auto: bool, pub is_unsafe: bool, + pub is_object_safe: bool, pub items: Vec<Id>, pub generics: Generics, pub bounds: Vec<GenericBound>, diff --git a/src/stage0.json b/src/stage0.json index 5625e7219f8..1297eb1f8ec 100644 --- a/src/stage0.json +++ b/src/stage0.json @@ -18,425 +18,423 @@ "tool is executed." ], "compiler": { - "date": "2023-11-13", + "date": "2023-12-22", "version": "beta" }, "rustfmt": { - "date": "2023-11-13", + "date": "2023-12-22", "version": "nightly" }, "checksums_sha256": { - "dist/2023-11-13/cargo-beta-aarch64-apple-darwin.tar.gz": "747e7a7b31217abef7f5e6e451669cbada43ccaecf6e58df2dabb2b059256406", - "dist/2023-11-13/cargo-beta-aarch64-apple-darwin.tar.xz": "4ab42395708f3d2b495217c08f96a80ad5a6415edb226391e0f010927b206b88", - "dist/2023-11-13/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "96a5f6d7d5fb25cb749b4f20405d7eb1aee296ea58915032f589943faaa87819", - "dist/2023-11-13/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "0f350bb1a28c7d822782137d80f0664c7906cdfce050e303559ea98891a0e3c8", - "dist/2023-11-13/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "a02bafa141d71877c806aa7bd9ad6831c4cf99bb62503ec4a7046e2e8a8a7885", - "dist/2023-11-13/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "26b16d1805b6424109dc1586146fec72ad370eb7d6be0e746b627884a17f8ab7", - "dist/2023-11-13/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "b8cfc7a38693863a8b8b2928654a86347c07b8da14356a424dc86a4451e2201f", - "dist/2023-11-13/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "579c0fe919fe22221a545bd75152d7cfdac9f1b6529f9eacf397c0bb4d4db63c", - "dist/2023-11-13/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "a4fa076f7512a74fd3c4cb6f3ae12322049197ba5e719801fc4d72fcf33b5837", - "dist/2023-11-13/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "4574101b1cc23cb87abc038f342a73fb3b46a5a8d18f660ff4ce047a30a507e4", - "dist/2023-11-13/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "cafa333ea302e7066ad642994eb92811b85f41da5f2d8da83bb9c380eef44a77", - "dist/2023-11-13/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "9fb8b43ae9c7c18cee03403cd5b01cd246d5a0ab542e4eb19bbd03fda0e611cb", - "dist/2023-11-13/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "d3f6f85bba4b890fae52c593d8d57ccccaf86dd2d2545afe49d1dc924e7a72b0", - "dist/2023-11-13/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "7380fd4af83d9caad6f9a7d5d03f9ca33fe770fd35cec2e7ff78bd39f5a1e417", - "dist/2023-11-13/cargo-beta-i686-pc-windows-gnu.tar.gz": "15673b84641058cc0a91fedfad9f74c284d87231905980182e535ad7ccd9b31e", - "dist/2023-11-13/cargo-beta-i686-pc-windows-gnu.tar.xz": "2661610cb774326a04fdea7011ffa10a5635ff679ba744c05eb3abc56b8fc8da", - "dist/2023-11-13/cargo-beta-i686-pc-windows-msvc.tar.gz": "e1aee3221f3f17d129cd06f506a9cc384e91d211cc3ac09b927e3c7f069c74df", - "dist/2023-11-13/cargo-beta-i686-pc-windows-msvc.tar.xz": "d2f18bc8e07711ccc9723be50cd8bf42bc710efc50f12ef72921d12af7d2b9f1", - "dist/2023-11-13/cargo-beta-i686-unknown-linux-gnu.tar.gz": "0aac1acdb7cd73b19b9581f2262a22ab43378ad17c68e7b8133d34ab8b56ad6c", - "dist/2023-11-13/cargo-beta-i686-unknown-linux-gnu.tar.xz": "e592ec051931d944f2cbe23d42e3b59ec4b077f6122dca928d065cfab333d91c", - "dist/2023-11-13/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz": "b5905ac53e476ecf1e0ea7d6625c1306cf8de27a2f1ff6b904e58bebfd87d384", - "dist/2023-11-13/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz": "3ee0542b6dec61ae9839f838aa229e13ad8e5ccbc659d6cff5c30f5cc8da1b7e", - "dist/2023-11-13/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "dc469696bbb2c80105c615dbd1e404de4e2552db295c20840f8253fac58b494f", - "dist/2023-11-13/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "0d162454c64f09c54f55c177d1b9f73cef27f399065095830ede9f3879395bcf", - "dist/2023-11-13/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "1c5a563db7c53e639823b56251efdd755c052c4cbc83956c84cd1f6af880ccf6", - "dist/2023-11-13/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "1302079a10c98b469effdda4de7bf8489cc577497c125f609b72f2f8257419fb", - "dist/2023-11-13/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "c739f65c2e06c5843bf619b1028fe6f2c82cbe48e922d1bb30d2379fbe74317d", - "dist/2023-11-13/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "83e25573d9c4713e095e3f2f253228ea558c5826b00319c9622fd47be5787351", - "dist/2023-11-13/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "04bb36ec9d2e636f11f7c5573f4749e3c767dc371fb7dd7e5fb7bc5497a9f02a", - "dist/2023-11-13/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "4d79803c2f04a69f02bfbf9e300b8d48baf381a4fadc9f665f748b81f1c2b126", - "dist/2023-11-13/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "49354596eb8d6be2afd40022504987ccf0e54c205d74ee5b8352260f2e95f9b7", - "dist/2023-11-13/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "1df49a605408c0b72c95f5f1fadc6da14f847622617a70d4ae0df6437505896b", - "dist/2023-11-13/cargo-beta-x86_64-apple-darwin.tar.gz": "3ac3c0170016d6ca3fa18902a1c8714820ce8c743e7dd3674c54dd69f1f84645", - "dist/2023-11-13/cargo-beta-x86_64-apple-darwin.tar.xz": "d403d08162ecf41d53190ea5a3a945c1fc5bd0e2c380dbaac764d03ad8377f0d", - "dist/2023-11-13/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "1003fe8288c982459ee4379a5746d825ff0b6c5d0bebb2b269903da9432b712b", - "dist/2023-11-13/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "07a364faf47204c92d021fbbae57b369ad82ba64fad2173189aea3764568eaa8", - "dist/2023-11-13/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "1a7213217869ffb3c48b557dc8c172be61eee258f7bf34bb2b5f8c9ad96f8521", - "dist/2023-11-13/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "64966d116575a18354d6e884317a6400941994462e305269f25f17ef17605417", - "dist/2023-11-13/cargo-beta-x86_64-unknown-freebsd.tar.gz": "7a1e553ef97d3d88d532060a8dd64234742df04ada95f5d13536b21d380a9d1e", - "dist/2023-11-13/cargo-beta-x86_64-unknown-freebsd.tar.xz": "67f1bb5008080c00f4f22be794b1fa63a88c1503187dc3396260aa73d52a1f7c", - "dist/2023-11-13/cargo-beta-x86_64-unknown-illumos.tar.gz": "436959c6da9c1c4bc49c4df51747729c0cc31b68c5a4dbf0e1875f3535dd1d26", - "dist/2023-11-13/cargo-beta-x86_64-unknown-illumos.tar.xz": "fbe0068c48b9b90467fe22e61d7c0707dbc8b113f07966f6c796821d283fe113", - "dist/2023-11-13/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "aea309719c709ba1a8663dcfd8f4ac379695d65b69115641e6adb57cd24819f0", - "dist/2023-11-13/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "cb0fcf1a9804d106f4168f6f8d2a071bddbfaa55430f3284696982bc6bc6c4f8", - "dist/2023-11-13/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "03062f953a10777d1a26ab13190a5493c989ab560b182c5968cca3df97fd2b48", - "dist/2023-11-13/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "790a859eaf49da5fdef1ea1ebf8b7f1f001bdaa62798a745d791bc915d886094", - "dist/2023-11-13/cargo-beta-x86_64-unknown-netbsd.tar.gz": "f14395b57c0eca7c8ac9012b303c3781e16a2287698f68705fcbbc5c7c5916c9", - "dist/2023-11-13/cargo-beta-x86_64-unknown-netbsd.tar.xz": "2c759c8bfc9cc556eb3464ac7e5589b573c46bd3938ac288ba52549121d3333d", - "dist/2023-11-13/clippy-beta-aarch64-apple-darwin.tar.gz": "258b55f0db78c93f14952fc3e2d9fc49f1121de5268ec49d03d4f197bd7c9773", - "dist/2023-11-13/clippy-beta-aarch64-apple-darwin.tar.xz": "554bd9488a9887c4acfb7c24775365108aef049feb15c93926128f805183f5e1", - "dist/2023-11-13/clippy-beta-aarch64-pc-windows-msvc.tar.gz": "d120adaec65b5f44f40fba38fa10a0cda33769756ac7fc2878d64154acc7e06c", - "dist/2023-11-13/clippy-beta-aarch64-pc-windows-msvc.tar.xz": "1dd23152a87fb8fa60569c304a3bbfd93f97c52d533fe53c8d9a5a4a72912938", - "dist/2023-11-13/clippy-beta-aarch64-unknown-linux-gnu.tar.gz": "41198264d015ccf624e0fca876bee16f8c3cbb07596f5f4d4f271b9843b10e30", - "dist/2023-11-13/clippy-beta-aarch64-unknown-linux-gnu.tar.xz": "1c889aad06c73dd2212403ff2aa5f256eba490cb8f1c81d7c75199a267052648", - "dist/2023-11-13/clippy-beta-aarch64-unknown-linux-musl.tar.gz": "db784d117c156d0e8854518a5df6e9adbf0b2d24f3504358b1a371b8e7954eef", - "dist/2023-11-13/clippy-beta-aarch64-unknown-linux-musl.tar.xz": "a946d40d32be1c5477f1740648e18af5792ceed38fe255e8cf09160acb27d02f", - "dist/2023-11-13/clippy-beta-arm-unknown-linux-gnueabi.tar.gz": "1b760fadecb9f4c4c1780b36d9bd651fa6c8a8fb6b48dc0dfbfb2ecd9359ca92", - "dist/2023-11-13/clippy-beta-arm-unknown-linux-gnueabi.tar.xz": "9e21f778eee57b067f411faa15425317158abd22f7c60dd4fc24214536ff7415", - "dist/2023-11-13/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz": "fbe3d7776b9353782d2690ff1c98a0ce5d8d23de2381ecd3d4eff4ce165b66d5", - "dist/2023-11-13/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz": "bfabf9e2419065173bf709166b0c81db66e1b2514003b28d08ec4410e04525a3", - "dist/2023-11-13/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz": "5371c798687aece2b98e22cf5bca02e568913011393a86a1aa3b0ff79eeabb57", - "dist/2023-11-13/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz": "82723066f2ec52fb5854a397f71df79db54976f4c03113034627c1a5c92ceffb", - "dist/2023-11-13/clippy-beta-i686-pc-windows-gnu.tar.gz": "0214eee5dc37f3a780ca62f1e7a66c5e19d583542dbfca047e383dfacca604b3", - "dist/2023-11-13/clippy-beta-i686-pc-windows-gnu.tar.xz": "cee7d7039b1ee909fa4a188d7fd0bae14d718bad98209d8df2dc087cc28d7a9c", - "dist/2023-11-13/clippy-beta-i686-pc-windows-msvc.tar.gz": "b6f1042f0d4652e941d975af8aeb4a61e335c585c1cd6dad7f85ba5b03c6face", - "dist/2023-11-13/clippy-beta-i686-pc-windows-msvc.tar.xz": "a31c1951abdff06c3709472acede08cd000b940a7a65f9afd664ca276fc724c1", - "dist/2023-11-13/clippy-beta-i686-unknown-linux-gnu.tar.gz": "1e0f2f2ea38988cd0012ceedacfa9828b4b6c6dfd3dca9eee5a98483fd90f439", - "dist/2023-11-13/clippy-beta-i686-unknown-linux-gnu.tar.xz": "f19b56068a40af2aee7c828a4688289a8142f98a81b80d66d12ddc6725209628", - "dist/2023-11-13/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz": "e0f02e3ba303bef68a7cd1ea5effaa126eedbdc892b01dac85f4b3e6d4b2f522", - "dist/2023-11-13/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz": "17a01e484f238bff790ad6cfededa8d9c7df0f6f36af336a1e8a7414a43271f5", - "dist/2023-11-13/clippy-beta-powerpc-unknown-linux-gnu.tar.gz": "ea4bc3aed8739bcecaa97f01972bbbba45e838c811ca0c408824b1409f9ac7c6", - "dist/2023-11-13/clippy-beta-powerpc-unknown-linux-gnu.tar.xz": "9ddb71b1f35f6953aedc6a1f93dde4a9b014255b5bd7d4448e4dd9b1a65c7f5a", - "dist/2023-11-13/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz": "ccb95c3ce3dd4ee2776201ce1bd79122e97916c555126393f1839d301824e746", - "dist/2023-11-13/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz": "9aad65fcefe5789670bc85cd177bd72eac469eb0a33db54685132a7ce5115a83", - "dist/2023-11-13/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz": "eb50e6349423c963fdce3193f361572a47e4d7fe5b90f8a297471c0a5df31feb", - "dist/2023-11-13/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz": "aa72d573b344953b9224ceb6eff484b6f012febfc009bc7773d398a3ffa69ea0", - "dist/2023-11-13/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz": "8546ac9a9e5081384d7ef889254e41998f60c04bbdca319128039e8a4e7cbc68", - "dist/2023-11-13/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz": "15fa574f7f7de2d8fcd124f44b1880a78bdd6a2ba77fe6b392299dd746ea9c63", - "dist/2023-11-13/clippy-beta-s390x-unknown-linux-gnu.tar.gz": "ee27937b85c142ebf46bb59ad9e113414cc9d631179a2f8df2b32980aa57b515", - "dist/2023-11-13/clippy-beta-s390x-unknown-linux-gnu.tar.xz": "e6e99e486418cb23a0cb80a2b145413bfeb62746b60fd9a0ff3959424b7ee07e", - "dist/2023-11-13/clippy-beta-x86_64-apple-darwin.tar.gz": "8a37545cef25abdd3c722a21385b843cb9d8d06fed8f302880beecbcb9373f98", - "dist/2023-11-13/clippy-beta-x86_64-apple-darwin.tar.xz": "f572586fc28bb5b2b77464d89b41c374de4002b453c297a8fc1468cee10db972", - "dist/2023-11-13/clippy-beta-x86_64-pc-windows-gnu.tar.gz": "5add2dab913488a482be6849887d9fa8c3cd197d3c423595a7133b511efcefca", - "dist/2023-11-13/clippy-beta-x86_64-pc-windows-gnu.tar.xz": "1d0d97a6b8703166616b6ae56d2b344e85dfa1db36976585d21cda65362cfff8", - "dist/2023-11-13/clippy-beta-x86_64-pc-windows-msvc.tar.gz": "4069dc9296cdc54af7e14d4ba5fc12ee5e6445be74f39c39526e4ed77378112f", - "dist/2023-11-13/clippy-beta-x86_64-pc-windows-msvc.tar.xz": "fdf4dfaef5f8fb24075bf8b24bdbd71804a49acda40921de84c61bc2250ade6c", - "dist/2023-11-13/clippy-beta-x86_64-unknown-freebsd.tar.gz": "4554eee1b1bd7e5575eaf5e7a815686da88fb395a80084c7a0fad3f338ac83b1", - "dist/2023-11-13/clippy-beta-x86_64-unknown-freebsd.tar.xz": "b0f1718df2a1e88ff4aa239bf4b9dc7a971fbc64cfa1ef8f399760fe09117097", - "dist/2023-11-13/clippy-beta-x86_64-unknown-illumos.tar.gz": "035400e01edb1a91ddcac72fe3ca1ea94465c4fe9047546d057f6867d8b068d1", - "dist/2023-11-13/clippy-beta-x86_64-unknown-illumos.tar.xz": "3ad1b06c3bc1e327ea7a3b30908b48bf6b59b7222101e5a30fb054b1be579087", - "dist/2023-11-13/clippy-beta-x86_64-unknown-linux-gnu.tar.gz": "88d611c40a30922515d09425ecd1a8b87f46131ab61f3c4bf841a41f281134b3", - "dist/2023-11-13/clippy-beta-x86_64-unknown-linux-gnu.tar.xz": "9908227c8a684aa5c24f3272997fc9688044580f792375ec9fc8f775e394953f", - "dist/2023-11-13/clippy-beta-x86_64-unknown-linux-musl.tar.gz": "10a7b2427ee8a4e83d271023e6bd00573266f317789cff3b75e68d7bddc41cbc", - "dist/2023-11-13/clippy-beta-x86_64-unknown-linux-musl.tar.xz": "cb1f3c2be55e11920340344d2f2f796098b7f13c9ddd2fb8a38ac1b29c5d6925", - "dist/2023-11-13/clippy-beta-x86_64-unknown-netbsd.tar.gz": "2b29461b085f0af1bb50d10ef8bf6448550c9b5867a364da3d921daea8e0a13d", - "dist/2023-11-13/clippy-beta-x86_64-unknown-netbsd.tar.xz": "e9d2ff4c8c63a9cfb7d8b12df4942f5b90c33c4fa3f755bbdc3c5df1b2b877fe", - "dist/2023-11-13/rust-std-beta-aarch64-apple-darwin.tar.gz": "818e3554a6bd82c3533e68f8597c09563af1dc08d6b23bbd2323b8ebcce251f6", - "dist/2023-11-13/rust-std-beta-aarch64-apple-darwin.tar.xz": "6f9333c281859e40b1c1c20e9f07ac1633ca2c99e86268b521945b8ed6cf6a50", - "dist/2023-11-13/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "fa4bb7a5d4dcecb2dfd8596e3ad442a5fe05468c939de3b36e44a43e10ea9d30", - "dist/2023-11-13/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "4a8e8ffb4658162c3bbd7b1c819f50181ca88c6afbb61c689c621ee4d29a66c7", - "dist/2023-11-13/rust-std-beta-aarch64-apple-ios.tar.gz": "42d37c57380ea2b97c1ba62d50d49db5e674387b0953f2bdcb323f4383f5f456", - "dist/2023-11-13/rust-std-beta-aarch64-apple-ios.tar.xz": "699f2f3c386f4bde50cc59616339abb95d95f292650b4b1f04cf8d923fccb03a", - "dist/2023-11-13/rust-std-beta-aarch64-linux-android.tar.gz": "b872dd2e1f7af33d327033ee602bcc62a5e49cd6178d0974a0f0ffcba86b457c", - "dist/2023-11-13/rust-std-beta-aarch64-linux-android.tar.xz": "ef121a3a4db77c3935d23887ead6c6399dbe45c739566c8bd66ad4fbf6adef2f", - "dist/2023-11-13/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "055043974520b270fdfa63074e5f44d2881052542549ae215e5701c1d476235a", - "dist/2023-11-13/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "6c320b375bb029c144eebfb01127ac0f1f2e4567df3ea505ad5f48d144115272", - "dist/2023-11-13/rust-std-beta-aarch64-unknown-fuchsia.tar.gz": "9aedfe4d4186d26878ffa73f6562a88e5123a54fc81293315c4e62c9e559b6cf", - "dist/2023-11-13/rust-std-beta-aarch64-unknown-fuchsia.tar.xz": "7f623ca49e51ad78caf64221581e96eb95a489532cea22d91f98794f5a6819eb", - "dist/2023-11-13/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "07bc11565052f5a417f650451f2ff0aa6f0aadd506b664e77789006429746d9e", - "dist/2023-11-13/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "d4bbc5dc49a1f6d53c1928807531679836aa69a4b3715295472e3df4a40da27a", - "dist/2023-11-13/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "493f4f196274a1141904e1aeb9cd32dcc6d4a06283395012d257e2a8d545d7ef", - "dist/2023-11-13/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "594529eb5be03d6f376c75d04260700205f815e33697e6cabd5449754704c748", - "dist/2023-11-13/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "5b9a95cccb9179fe2b62998292a40ec05137ca9423b103392fe4d7a6e6d03402", - "dist/2023-11-13/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "aeab81bc3066bdb94227a31473ded8a623d9bad924a39bb6db6e7d6f4fcb77b2", - "dist/2023-11-13/rust-std-beta-aarch64-unknown-none.tar.gz": "24a9a76b4a2a24c9388d55ff95dc100436ed7047f95c0d6476d66cb9266f6c03", - "dist/2023-11-13/rust-std-beta-aarch64-unknown-none.tar.xz": "0052dac98cec080b2bc15955f7ac93c11db351d32c7f5a1b46e00eef9ca39f81", - "dist/2023-11-13/rust-std-beta-aarch64-unknown-uefi.tar.gz": "3bf855413ee4c57ffa54eebb00b819e57014977bd85c69dd5ec35ec0b64d1b1b", - "dist/2023-11-13/rust-std-beta-aarch64-unknown-uefi.tar.xz": "0dc3b0d4f1cf927b1e1a53755b1f2da81bd4e43c172e446426ce70db6ba22802", - "dist/2023-11-13/rust-std-beta-arm-linux-androideabi.tar.gz": "9f6d485b3e53a3604f80f48149742e22820d64fa4e4bdba0b0206b6d6be78486", - "dist/2023-11-13/rust-std-beta-arm-linux-androideabi.tar.xz": "52efc21d5c92a8bb3eaedfaf87fda75b5b19bf0c65538b718f1fabc3b14e0582", - "dist/2023-11-13/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "5c5089e88d841aeabd4ba279a696a687cb68850185da92b61afbd3739c0a409d", - "dist/2023-11-13/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "55ee23f7747ecfd8c8c6678372109c7068d3363d710519bc607135fe8b5fc46c", - "dist/2023-11-13/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "08afb933ce18021e8bc6a016dcc63f8001bf94f201618b8e004c2f4c4c9bafd8", - "dist/2023-11-13/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "1b16c956b8b05fbbd0d3adf0356dddc64be1a8f099d99f6d8d7f76a0b07d19ba", - "dist/2023-11-13/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "ac49dee872f3cf6d74abb60c6a717a2e8fc8994e8a2a4cf2e89eab7808f9013f", - "dist/2023-11-13/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "5852f7f9f08574a351f5094a5268cddc27afc4b9933c998d0757a838504e9959", - "dist/2023-11-13/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "c9b806a780d1cb75f7892b2d1adca343fcbfc626fd4c364af42c13d8f8e71e82", - "dist/2023-11-13/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "d81d26a77da1d034caafd194e2d36de5be1d4c4f99095d39a378b661dd20f28e", - "dist/2023-11-13/rust-std-beta-armebv7r-none-eabi.tar.gz": "be2105b20ecfd7103613a4e2924e6057806535f467a5aadacdf8f458eff9866f", - "dist/2023-11-13/rust-std-beta-armebv7r-none-eabi.tar.xz": "f130958a449aaeb7fb81864eae5e25e5f1b30c4b59c438e15783eb501ec01e80", - "dist/2023-11-13/rust-std-beta-armebv7r-none-eabihf.tar.gz": "68e2ae2d1d6bb4eadfea2e1baccbe2984c38c13d9b492390ea897cf828976fc0", - "dist/2023-11-13/rust-std-beta-armebv7r-none-eabihf.tar.xz": "08858898e6b3c4855e8dfb015353a76ae5afa056208de6110135967fd752e6ed", - "dist/2023-11-13/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "06726cce8e9d1106443ef1d34fc9ff960cc8bfe7b4553ddd8e8c455360fb7a3b", - "dist/2023-11-13/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "b582686035b5ab0b855886feaa11a6b978cd0b9a1cbefe4afe9083e726c17916", - "dist/2023-11-13/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "2bcbccb51e5d10a766103d132cc10176e0747801a6fc1e3fcdc68b55f8970273", - "dist/2023-11-13/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "979f9c7c3a804552f41836a152fdfd8a68db2c144ff37bba3a85c99c4c7d21c3", - "dist/2023-11-13/rust-std-beta-armv7-linux-androideabi.tar.gz": "e5a563a023c4c90b2908c7de6535e208b412cf8ef67bc870d5a5079d7a2c4ab6", - "dist/2023-11-13/rust-std-beta-armv7-linux-androideabi.tar.xz": "88c84f7196f86a1e20400e9addbf1051ca90c1f6fae06ea711a0f49f5ba3ff1d", - "dist/2023-11-13/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "2a164112ad94b3729b39c2dcb5e6e1ac756e2f30bb0730db679a9aa59ad2cc26", - "dist/2023-11-13/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "c0eb6162b48266df4747833613ecf2a0234a4a7bf75331459bc230e7b868b676", - "dist/2023-11-13/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "2340f23434b411fa3da490cff5a41752d4f557324b3ee28bee2b089030f2e53f", - "dist/2023-11-13/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "fa34f4a1dbd757aebcbdd4e3e3de5053ef268b0a9fba7efa47607596f03b9e70", - "dist/2023-11-13/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "a9c3505a537f119a261dc882c0979c262efe68a5a798ee860924d0a0ad9ac359", - "dist/2023-11-13/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "3cb01b367a700d8ac8df14b6b87a81ff308fa9e4efaa08156ce3ea51b515c2ea", - "dist/2023-11-13/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "a57268eeb2308841c947b26c1492c3d9a36fb47408bb5b7909f0c3d4ab84f27c", - "dist/2023-11-13/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "38d8c2a2c7b8770c517f1cf17bba625dbe2f13c6899f61f3156d769a34515fbc", - "dist/2023-11-13/rust-std-beta-armv7a-none-eabi.tar.gz": "2e2d0f38992ef60701d1ea6ff647f72039e6a7fb483bf9ee4b341120e1d6df43", - "dist/2023-11-13/rust-std-beta-armv7a-none-eabi.tar.xz": "5a3115daef7c1d7138baa27e7bdc9ec3834fcab9e910ae2cbaec47ea833b8318", - "dist/2023-11-13/rust-std-beta-armv7r-none-eabi.tar.gz": "bb61701c8cdc26851b3939db5d9f965bb8167be3d681e006a1a9f0ae21e5a293", - "dist/2023-11-13/rust-std-beta-armv7r-none-eabi.tar.xz": "ca5264eaa211f9fe9fb2a61bb6c7efe9b2ad63a84976ce1a1d0742278003d484", - "dist/2023-11-13/rust-std-beta-armv7r-none-eabihf.tar.gz": "f399d12314de408001e925042b464052809c57c533dafa4694c16e4a4ae1d874", - "dist/2023-11-13/rust-std-beta-armv7r-none-eabihf.tar.xz": "50dd55169e78b93428c19c8dad61e037a019de50cb91ff559c29069de63d8e66", - "dist/2023-11-13/rust-std-beta-asmjs-unknown-emscripten.tar.gz": "e2e512e6a1d5d86ed040c22d7a1fe504ba6f5de30c24065f19c23763cb4c8743", - "dist/2023-11-13/rust-std-beta-asmjs-unknown-emscripten.tar.xz": "3ae3afdae7a52e933e75564476a8b080e414905436fe0e9706932d69900b1fc0", - "dist/2023-11-13/rust-std-beta-i586-pc-windows-msvc.tar.gz": "b06d0dc821d3d67ef20fe1987411b57cdfeb29e6f330d6b9922fd3b854cff28d", - "dist/2023-11-13/rust-std-beta-i586-pc-windows-msvc.tar.xz": "3c22775d9760be3699bfb1f4a0379cbd6838c03e2f8205a85d90c7a476664414", - "dist/2023-11-13/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "cdc0219c4ab66986f4de668b2c7cebd90ccde6958b50ce0dadee81518e67de34", - "dist/2023-11-13/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "09e838ae1922f7170e85c5b95d032f9feae9876f5e11bfc3693624b62b5a358f", - "dist/2023-11-13/rust-std-beta-i586-unknown-linux-musl.tar.gz": "e8b92575033950392e252dd68a0f8da310909bda23b4e40d6323d54211ee2604", - "dist/2023-11-13/rust-std-beta-i586-unknown-linux-musl.tar.xz": "584f829d6f324705c783ad97f67acdb34fe475fed8c4b91817978335d922ba1a", - "dist/2023-11-13/rust-std-beta-i686-linux-android.tar.gz": "0ef6e63ce3999c3035f0fb76bdc314966c4892a0ff7023941b1dc193e5c37a6b", - "dist/2023-11-13/rust-std-beta-i686-linux-android.tar.xz": "67d8dc585cec56aade8fcda986512fefd2c6346f446ab4df0764deb12cee5567", - "dist/2023-11-13/rust-std-beta-i686-pc-windows-gnu.tar.gz": "af77f489643aaf9b38681f038d7b6841122469841f68e1826525849e99081f69", - "dist/2023-11-13/rust-std-beta-i686-pc-windows-gnu.tar.xz": "5456f998f86146cb9a522734eb32ccc75155a10e28f26728909bc5e53e7c7b8b", - "dist/2023-11-13/rust-std-beta-i686-pc-windows-msvc.tar.gz": "2d770b47791453dacf349942b97c9fc8f4cf1c38130a37de6b698663194e6112", - "dist/2023-11-13/rust-std-beta-i686-pc-windows-msvc.tar.xz": "502623d29afe9167e2266b42a89b4224fb232fce73676da71502ca015daf8964", - "dist/2023-11-13/rust-std-beta-i686-unknown-freebsd.tar.gz": "d87ff9aea045e2414e3986227a78b75ac543200063d55022ae08e26e02f62819", - "dist/2023-11-13/rust-std-beta-i686-unknown-freebsd.tar.xz": "3c50e2ac1823ad810c360ff754984d5fa85d108ca38d83158059e95876127d97", - "dist/2023-11-13/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "233e5fac1a76ba28d23a5173e703bd24455307a78ff767dbb049192892dfce0c", - "dist/2023-11-13/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "f307359373a6dc48f5e18f3fff52326cb473c6b17db458c78a640bb488f294ef", - "dist/2023-11-13/rust-std-beta-i686-unknown-linux-musl.tar.gz": "360cecf2a1cd51f88c4da401f27b24f3a6395247b112428df3191990781f4e5b", - "dist/2023-11-13/rust-std-beta-i686-unknown-linux-musl.tar.xz": "d8246447e17987bdb19c6bd500eb575bf9041537fbfef8a6d82c1c98693ce63a", - "dist/2023-11-13/rust-std-beta-i686-unknown-uefi.tar.gz": "b5735aa3bf0c111c5bd652aca5bd8a2249d6a5d8b6152b404cd4f34b82bcd46f", - "dist/2023-11-13/rust-std-beta-i686-unknown-uefi.tar.xz": "f9a8e850c9a72948f31ba398037b389eea987b81213a2d743a04d4b818000e14", - "dist/2023-11-13/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz": "2eb39cd50a93749af784c634ea757e72c4e24347b7258642481aef73829ab87a", - "dist/2023-11-13/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz": "f01b91ea400ec0b9e565e2de689ab6ba48c78ef2f91ebccc2cfaf45c1b8cefbe", - "dist/2023-11-13/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz": "6b141c0f56a27540186a6cc880c3330a5bce099ff002f3681c680c1221a3b1c1", - "dist/2023-11-13/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz": "8f95e17e81d1b3dd039826f3ca483a570c9086b36c5523c277eaf302d0d6ff38", - "dist/2023-11-13/rust-std-beta-loongarch64-unknown-none.tar.gz": "78526ba4e1e78cdbb6943d8406a5bbc5fb8df2e1890d50d613b33bdc701b1c99", - "dist/2023-11-13/rust-std-beta-loongarch64-unknown-none.tar.xz": "bfb7baf432d1fba29933a55498764a4e563dbb75f444a4ef3e2bce71e25b8f84", - "dist/2023-11-13/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "9216385a85d7085474ce36bfc961b84e6a48ded07017ff5a057f502f6b0c7eec", - "dist/2023-11-13/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "f5501192af94ff399de9e74bd8d87ff37a986d369d3a6ed40fff85ab11d93676", - "dist/2023-11-13/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "2350b2f1bebda9335750671e6716dc6b7cee4897507e828fb8a65cc88a057b03", - "dist/2023-11-13/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "f31c185d7532fdaf4a358ef7ead703623fa3c2196f354eabdc7923f6da44db0f", - "dist/2023-11-13/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "22a03f008b066e0667bea31c0b1702d04c3eb57c34f19b2da6410e15eebb6872", - "dist/2023-11-13/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "8016d83a15e9ea72dc3f453671ae85dfcebfb518d1b306da96ae1a870997b337", - "dist/2023-11-13/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "3b166df751af8d54f4555d70407b2da6ade6972c07400a462680a8a40972691a", - "dist/2023-11-13/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "863da3831b4c6990f68a83cf3067b490e383ff1a33f7113a845a1ab8c2e2b714", - "dist/2023-11-13/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "8b571f65ec378563147a64a18fe202ac76a2c13a6ca2987976edbaa358a0e797", - "dist/2023-11-13/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "79d82bc4dc99af74ddebfc72305b32c1c819d9105c59359bb86b9b07d68db515", - "dist/2023-11-13/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "2ab118b25f237453d3aa68b9288c317e4474a469f4ed5e2f0fa10d85495a7c8f", - "dist/2023-11-13/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "25b9e9f41cfd797ffd25c2f5bfaf4ecb295de95db81e72a265e9d54bd5f41406", - "dist/2023-11-13/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "d6b3e8d853108716a2a9c6779a0ec2e7a496b58f98a27e95a5cfcc4c1acde7c4", - "dist/2023-11-13/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "e0f93c480e505d241ba00f4846d94a667df425800c204fdc0a30db2384012a13", - "dist/2023-11-13/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "8cf3de56808a9222c0b59f15616ccfc0c311a6c01c889be0f208ec48c3f92471", - "dist/2023-11-13/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "b46efcf1348f1f718355cfdb4a196001af55248a4c4f4cadf72a159c0369b30d", - "dist/2023-11-13/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "445a73b9646aa7e1bd02789db0c2486ef5b40ae76ba8f79fb7752e8a6e21e251", - "dist/2023-11-13/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "5afe29968b96ea83bb5e9e76b508ba3f51cae9da7c1d5635943b3d5dd00f1340", - "dist/2023-11-13/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "bab78b1672ca3b76a15cd151e9a63941dc226b7a64308290faa21eec777fada5", - "dist/2023-11-13/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "955965774ce971cdcb6b168604e110c7a1226059671d001f551aa1330783f909", - "dist/2023-11-13/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "f0eca14f82d86753444ac617789d4fd922437e62616123d0cdf3593fc2886e25", - "dist/2023-11-13/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "0d4ef0c263c798c5d636519d8893af46eee02339704bdc9c50d04e2029d48f47", - "dist/2023-11-13/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "fb652a85e83ca307eacfbd3155d46ec355bdcd46b2d9c94ae839c6cdbc78c4e3", - "dist/2023-11-13/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "1b8cfaeaf1d5d47760f9ee671b32ebbe81bfaa34074ad7c437602af65e91b1d8", - "dist/2023-11-13/rust-std-beta-sparcv9-sun-solaris.tar.gz": "5e5363302fee2567c27bfbe59a874b9d47c8dd27da502f7b5dda093a8327b936", - "dist/2023-11-13/rust-std-beta-sparcv9-sun-solaris.tar.xz": "fcd48e58e9ef18401d86482636f1bf2dd645e03e3d12896f5ac082ab5dc1990f", - "dist/2023-11-13/rust-std-beta-thumbv6m-none-eabi.tar.gz": "4b7e449d6d81ad8042506d617c27cf3fb3980299cf17a3b6b084f9253c95dfd0", - "dist/2023-11-13/rust-std-beta-thumbv6m-none-eabi.tar.xz": "b5f0cace5ec3a46e5cec31444e9d6340df5ae43584579d1b6171c7c22a925050", - "dist/2023-11-13/rust-std-beta-thumbv7em-none-eabi.tar.gz": "ebbe4cb796fbe017d0ceea0be022c1a6e6166e66eff943ac9aac548474ba774d", - "dist/2023-11-13/rust-std-beta-thumbv7em-none-eabi.tar.xz": "416e127948af40411b0063e677f2b212a46f784c9a15db9e4f762a487692ba07", - "dist/2023-11-13/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "5737d11a1a1ddb39dbef8f7f3feb752e396cda780180ebbf8d27be015a0ad2b1", - "dist/2023-11-13/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "616c5ffc3410720a3b4fbdbfca8399750bdccc5dfdb9e2a5eac52400186baddc", - "dist/2023-11-13/rust-std-beta-thumbv7m-none-eabi.tar.gz": "57f785f8ded6d3cfdf63658474f3ac65e80cdb00dae57f83a2d40f2c676491c1", - "dist/2023-11-13/rust-std-beta-thumbv7m-none-eabi.tar.xz": "5bed08004eac3bd3fb77bc47035ea3ae2095122f3fe4b83eb1401ed77d6fbc97", - "dist/2023-11-13/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "698e3213fc2e8a3b1fd2609a7bfe31549166f67768e7db6f0f3b8f462dfdb0f7", - "dist/2023-11-13/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "fabc41d905c2594bfddb7e789ca9ff42039ae43219ad70da73ddde5f3903110b", - "dist/2023-11-13/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "87eed169aeec1e8b3adefd3b3765e563a32fa355202e3110f115460198cd67be", - "dist/2023-11-13/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "f6b9bc666d0ada37ca8e9fb695d971e254ab1487d16923a413297d364f0a7827", - "dist/2023-11-13/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "b2ee2d569a0f4cc9f00d476b6197869bd46e6a25054f910bc997d4a47cd216c6", - "dist/2023-11-13/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "04e619d6cc94478bd474f97402ef0147e02078c5f24b4f9c3ab2d904a09cad62", - "dist/2023-11-13/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "49e2121df0ea56468be58522fc74c047b3bee7390242900575dfbe65edb96f54", - "dist/2023-11-13/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "ee743c99bfccb84fca2a1ffb569f1674b5e1710d7b670e3e62cc184c12bd61a6", - "dist/2023-11-13/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "cb9f8fd4fc4f2b27be37ec3777cd64bc638584b1744292b10af969bfb1b50f78", - "dist/2023-11-13/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "d62839e513f8a1fa57b97453d7bf6b15f85616828049a36d74d4de553e5b9856", - "dist/2023-11-13/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "ef29dbc48b483b4e8264e03d9869a87eb5f60f7f7f28dcca1361fadb54b79cdb", - "dist/2023-11-13/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "155f3844de6b49f5db34265320f4f94e45ac0f12f12000589d3a17cddef3ccce", - "dist/2023-11-13/rust-std-beta-wasm32-unknown-unknown.tar.gz": "e8a74c1a40b9bbe0d062d57d7169931d6d32b17ad0c82bc007cae16d400851f3", - "dist/2023-11-13/rust-std-beta-wasm32-unknown-unknown.tar.xz": "20521840fd7d292aece540525ccd11f9179700d3bc5c3be5403b032867e87afc", - "dist/2023-11-13/rust-std-beta-wasm32-wasi-preview1-threads.tar.gz": "7c090f46555efca8a60cf028321756b44ce7a27555204d114fc2661e64f2aa9a", - "dist/2023-11-13/rust-std-beta-wasm32-wasi-preview1-threads.tar.xz": "07b638d2f77fbb4286dd26537a8123fcf4a66f3bd065e541dc736536507127bd", - "dist/2023-11-13/rust-std-beta-wasm32-wasi.tar.gz": "089a845111c76efda5f50d84f3ab796f7e00a6710031a8a3d077d00414823637", - "dist/2023-11-13/rust-std-beta-wasm32-wasi.tar.xz": "1017d96927a3b65d8425e0c79320960b763ff9af3d31ebf71bf6ebcdcc7180d6", - "dist/2023-11-13/rust-std-beta-x86_64-apple-darwin.tar.gz": "98ce9ca7ff9a5d31006196bda22710f4a476b50f1e18759465c6026dec85fd08", - "dist/2023-11-13/rust-std-beta-x86_64-apple-darwin.tar.xz": "52d3637b78762c064e0548850e1ec5854fc0e98d339d7ae7d301ea9bb254ca3c", - "dist/2023-11-13/rust-std-beta-x86_64-apple-ios.tar.gz": "459b9e2b063afbb3c3014c9b6259ee5b3f774c4592393c22090dc1764b2a4eb4", - "dist/2023-11-13/rust-std-beta-x86_64-apple-ios.tar.xz": "3f8125a3565ff9f1bc4e528d6b23c4edc5bb12568418d88ca27ae4a0772dd6fd", - "dist/2023-11-13/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "8d35128421e601daab5fb5bbf2e3f5f23b18453efb39b71d54b36a15ba54c3f6", - "dist/2023-11-13/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "0f6b3cabefb9bc82eb4d8438524b3030a26053cc9b340f2aed4e68270c832c71", - "dist/2023-11-13/rust-std-beta-x86_64-linux-android.tar.gz": "5816f58ee8cbb0832357220ae4d25b87fde5090305a2298f3804faf1d0c87e85", - "dist/2023-11-13/rust-std-beta-x86_64-linux-android.tar.xz": "c0df3bc87d839b95bc1a5f69e2211020c183922a6d65508df90d60371f10e4a4", - "dist/2023-11-13/rust-std-beta-x86_64-pc-solaris.tar.gz": "d4a929235c25fdff8331e359612c6e2158b9984ed5b1a2d22d135c9ff714ad52", - "dist/2023-11-13/rust-std-beta-x86_64-pc-solaris.tar.xz": "d807cf6b57c12c9ab9baa703d2c38fb8817a185c0f1a3d846173d46c83f591ea", - "dist/2023-11-13/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "01e0338a3d36292ad73490c29e8ef11694dbbbc43eeb42faef2b4a824fd2f82e", - "dist/2023-11-13/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "5ebf0b26f4ece70aea9146c48eb2733fc517f387919842d5ec7caede5a7b4295", - "dist/2023-11-13/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "799e830f3151d8227e4c2a2c9c7f68706459b6d39fd9cb1041b3a87628cd7c58", - "dist/2023-11-13/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "4cd37d3f6214d120855ca215baadb9483218317dfc345bd390c86082d9801dfb", - "dist/2023-11-13/rust-std-beta-x86_64-sun-solaris.tar.gz": "b573908c72c8a11c879fc9b97d956f599e5642d38aed8a0a7dac68f988e0ac7a", - "dist/2023-11-13/rust-std-beta-x86_64-sun-solaris.tar.xz": "6493f17b04ea8817693a85268cb21e0b47f95edd4fd00561e104dccdae66812f", - "dist/2023-11-13/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "5dcedf3a1a8c12602932bc6683987a75db68a381019bad8207414843c35552d0", - "dist/2023-11-13/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "28c43fb5b7bf4c254ef61c5bc39da09e81881e01261a8a3346968170c8774581", - "dist/2023-11-13/rust-std-beta-x86_64-unknown-fuchsia.tar.gz": "85f5052ba7d38dc951bbfbfa6f0d932866a8b49f54457ca1611804b1d9014ce6", - "dist/2023-11-13/rust-std-beta-x86_64-unknown-fuchsia.tar.xz": "fbac8d59fd510bd5e4978fcd8e56a1e73de7140726df9c3106784496e744848c", - "dist/2023-11-13/rust-std-beta-x86_64-unknown-illumos.tar.gz": "289dfdbd7607d2275b0ac57ceadbda7ea4c060636f007685e66d7a7170494ad7", - "dist/2023-11-13/rust-std-beta-x86_64-unknown-illumos.tar.xz": "7d3a1849998b3212f226bd9c0a3193c0abca814d73edd0ff3c041d6b2338bc18", - "dist/2023-11-13/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "4d9e48adce6450cd114bf7509694c5ab7bedbf06210a9abd5461412617934133", - "dist/2023-11-13/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "f96c3b0bd75f15b8b6b9a6326c03ff5b4ee9aa16eaf426fdeb2e2213297854a4", - "dist/2023-11-13/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "6c4c00e554ff08bf6fc79df4790e3315c703bd789634f0dab01901a3527ced74", - "dist/2023-11-13/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "7f94911e59d0e7ca49f810124358d6ba8247df2136db1415216b90817200e91e", - "dist/2023-11-13/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "6408769d5540cc5a8cf741886ab9079184ff5562c6761d40b19874dbbc137e0a", - "dist/2023-11-13/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "a6b25bc4020a9f3ed59b16ee8e26ba8deab3d32dc3f771452e21301d1e9e905e", - "dist/2023-11-13/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "ad01d75532a0a05890e69c2d3a77b0c871a5aa50acda7cefce0654a2b634ad27", - "dist/2023-11-13/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "7eeb9cdaba6ffabd6f1aceb6c2eac354bb237b606582f6c88a754bedf5987735", - "dist/2023-11-13/rust-std-beta-x86_64-unknown-none.tar.gz": "2e3292d36d8ce3b383b220106513a5e7cd7e90160c9326dd6d0960678b4b961c", - "dist/2023-11-13/rust-std-beta-x86_64-unknown-none.tar.xz": "078cae8dae258af5fccde5efb2ce3599f5c1cb4a0aac05a9bb7e215e85d19cf7", - "dist/2023-11-13/rust-std-beta-x86_64-unknown-redox.tar.gz": "7f6f2e63a6ef9501630dc02c8a66e805a1d8cae3e457d163cf02c65d3be213aa", - "dist/2023-11-13/rust-std-beta-x86_64-unknown-redox.tar.xz": "0174212e92efc759ae9c75f9a32743a03029b7292f5b6b604b57ed8be9c58304", - "dist/2023-11-13/rust-std-beta-x86_64-unknown-uefi.tar.gz": "228fe781f4206dd1cd22210c22404087eeb5a56b3a56adb9fda90100cea87efc", - "dist/2023-11-13/rust-std-beta-x86_64-unknown-uefi.tar.xz": "4515744a3dcbc08ce672efaf4589874597e0feae691d14d6ba9050c56c8098df", - "dist/2023-11-13/rustc-beta-aarch64-apple-darwin.tar.gz": "4bdddcb1c681df3203a723dc31e683ca0b517d8fec2e98cfde24550c375b3d79", - "dist/2023-11-13/rustc-beta-aarch64-apple-darwin.tar.xz": "28e922e7c6b08c6a33e25038fb86773948c5131a4360a000b488d1be9cf14fba", - "dist/2023-11-13/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "8a10a25a15e933d9807859e58bc1dabe1d3cce515148a91ccf767369b385e6c3", - "dist/2023-11-13/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "8a842f833c006b361bf10e6b68c54a86744c4dde9248d7a2240cef6a46761548", - "dist/2023-11-13/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "f8cf7a5a8ce11f260eb73b2d2fa06714263e3d5355e7dc1288e2bbc2407cf64b", - "dist/2023-11-13/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "4426e7b5da73ff357094f07f0f5dfafa7a627daa3c73101d9424a174acad4794", - "dist/2023-11-13/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "21d8b92246382c25630fd0bc462a485becb309027414311d64268babcbfaaa63", - "dist/2023-11-13/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "221d51e77fbc6af202563fdf557631f75064e5ecd7750cfdf03a9dab6e7748a5", - "dist/2023-11-13/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "659197905941615e7cd8e2c41a09699b0df9ff4540b514e942e66b0e0acb02cd", - "dist/2023-11-13/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "5624af4e8f4f2cb0c11d504d4d1514a75a2c5e35a5fee9e2888e12d6dfd5fa76", - "dist/2023-11-13/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "27bb3004bc4dd6822b67de5f05c90850b1b8b0f0702f1685a572fcf416dd04ab", - "dist/2023-11-13/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "5102179b53fbaa0c416d5305c8b76be4e7ee707d840ab5ccc0a76335debc236a", - "dist/2023-11-13/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "493076756274e9c588700821abf39193c7d7ee51f41034db773f649ceeceb530", - "dist/2023-11-13/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "c487bdb531c75d273026c256a4e5d126aa68ebeb40e2eb602b7b232719e76ada", - "dist/2023-11-13/rustc-beta-i686-pc-windows-gnu.tar.gz": "158a1e8b326c5077c335cac2d031d266d7d5db04a1b2e9d76c9081730166a6de", - "dist/2023-11-13/rustc-beta-i686-pc-windows-gnu.tar.xz": "ba0306b06819ee34b62edb40c9e78a60ab58d6de0493af1bf2dd72ba2d31ae38", - "dist/2023-11-13/rustc-beta-i686-pc-windows-msvc.tar.gz": "0188d1e4f66dc89611b9567356b9fcbe633a857140ebba83ba43c99c22353c6c", - "dist/2023-11-13/rustc-beta-i686-pc-windows-msvc.tar.xz": "1f66b7976350cb06ea1d7e8869c0276676dc82ebf1d23c57adf37c2b36da1c93", - "dist/2023-11-13/rustc-beta-i686-unknown-linux-gnu.tar.gz": "6646a59d419a19aa9fadb55c12faa93524a85e3e1d7f0e7e20ad8007757fbff9", - "dist/2023-11-13/rustc-beta-i686-unknown-linux-gnu.tar.xz": "7fa6483a4bb592ea4e86b7ddbb9e938aceb2fee0ad7a4106f415eed66699bf97", - "dist/2023-11-13/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz": "965c3f1a939386134e563f8c6fd5399221b8bf47f52d62fd640276762ff94dba", - "dist/2023-11-13/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz": "a956879fc43f02d6f3558494c59fbdd67a93d0a51f44a85247cbb0f69a9793dc", - "dist/2023-11-13/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "4474c8e5d3b1931c5330f7b337dfe093110d006466a846bc8b7e06abb9497e67", - "dist/2023-11-13/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "a7dded69245f0b007f6ed5c803cc886d04fdff68884c44e426df3bccc00d9dd3", - "dist/2023-11-13/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "c35144e8205a84e48ff5b32fb7c363d8a18d42f873b47b0a54189f32a422c462", - "dist/2023-11-13/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "22f8c6f103806968ec4dac5a53581cb862cda6b291864e555a93f908971f87bb", - "dist/2023-11-13/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "5eb310b5a54135e443fd7aa571815e289a1bd0f96f2bca1ad719cf156f382531", - "dist/2023-11-13/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "7fdbc3fedaa77d12b04dc9b9602a44d45eea72d29642f1112a839cc90d72c262", - "dist/2023-11-13/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "7e936ba6928cd7116045f9c0dad358661fa867fe32c62c0815a8b392b64ea9fa", - "dist/2023-11-13/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "dd41b7b468837fd8a96dc37c99ad5a29edf185df38b0f82e5582a6200aabc564", - "dist/2023-11-13/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "3bc91d1003d07f9378317cf38eadcba4c69c65c34cf73016ab524f63b5ae77c2", - "dist/2023-11-13/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "30022ac67369c112725c8e327a76100d438ffb3cab27bbe3fd62316de60af5f7", - "dist/2023-11-13/rustc-beta-x86_64-apple-darwin.tar.gz": "848549ae18928e8c2ceafa986fe99d3d103a5a97348f4ed9cf9825096e44d6f8", - "dist/2023-11-13/rustc-beta-x86_64-apple-darwin.tar.xz": "00f5ea9ee85bfb85ff66b1b2ce9b04207334cc731e33b7250d1593f92abb9b63", - "dist/2023-11-13/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "0fe8320e4c07636743156943851a17c606d32f79a773a394983021f987bf33ad", - "dist/2023-11-13/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "b61d7f52522f0576e71ebb1d83b995085b020bc00b3423078210239ebcf2f954", - "dist/2023-11-13/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "e2da8e7a2d7f9a558bdbb4f56273e139ea26dd6778d4006479890163c52dbf9d", - "dist/2023-11-13/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "4ea59ac07b85078514af502538535c1ef98799eb574d2036752ed608353266b2", - "dist/2023-11-13/rustc-beta-x86_64-unknown-freebsd.tar.gz": "5870b4f26a3f47ecc8cf5eaf0e5f062087f71dcd94cedb420e402724a5d340c3", - "dist/2023-11-13/rustc-beta-x86_64-unknown-freebsd.tar.xz": "c2094e3b40e602ab804e875ec1b1ab7e91f0ff499bc6c1e4b2a957ed4d136ab8", - "dist/2023-11-13/rustc-beta-x86_64-unknown-illumos.tar.gz": "ef47a9f5bb410eeb8361db7a71bb3faed4f71024ad0659c359a20346e75fc7b6", - "dist/2023-11-13/rustc-beta-x86_64-unknown-illumos.tar.xz": "444e9b6a42b3219bc2c556b9c2b1c20d8ab6411662fc55d76ee0b1775321cbd8", - "dist/2023-11-13/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "f492e76a0ad4182607d27145ad45bb8ba6f41fa194dc7a2dec121cdb7fafd918", - "dist/2023-11-13/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "898c58f43f6bc8f259a87dfa7f57c88f1069883604e927f4e1f4808ac8969838", - "dist/2023-11-13/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "fdf79b4d8aeb5b846caeb19ba7bb4b7e614cc4cb48d3d129470ee2c914afcc85", - "dist/2023-11-13/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "17666599cd367e20a1439b91ae19e3d3214c6aed5ae36016efe34938e9e6ddde", - "dist/2023-11-13/rustc-beta-x86_64-unknown-netbsd.tar.gz": "e3085637e043c5bf132411cea9421fbb6f062fa6dca6b73592512dd739d94cc0", - "dist/2023-11-13/rustc-beta-x86_64-unknown-netbsd.tar.xz": "ac4d1228639906c873f5ab4c12b770ea2c053380e68e46d0afa70bac48cdf16b", - "dist/2023-11-13/rustc-nightly-aarch64-apple-darwin.tar.gz": "1b113b6dc4c3bb4997be30a939f3ef1d699c5052d7387da92a7d17a5bbb3de98", - "dist/2023-11-13/rustc-nightly-aarch64-apple-darwin.tar.xz": "2ae2b64171c7ad6fe7c769a3507900ff024cfc6f621b4d566022000ba1d0febf", - "dist/2023-11-13/rustc-nightly-aarch64-pc-windows-msvc.tar.gz": "b7617099a6409b869f0b186acf775df723c11d0c625db9bdedfa2ef45cefe5db", - "dist/2023-11-13/rustc-nightly-aarch64-pc-windows-msvc.tar.xz": "e73652ac663242b0e10abdec32234ad6fb6c899bb5251488d7b19b17c8ccdff9", - "dist/2023-11-13/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz": "6569fab33d672526354484ec648a7e3287b3c1e43420e11a8e15fe9d5b3d6bc4", - "dist/2023-11-13/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz": "215070976901d265554415ee06df6f377691fbf9287548379a31dcb4beb52042", - "dist/2023-11-13/rustc-nightly-aarch64-unknown-linux-musl.tar.gz": "d3b0eec2524ae12b5c62f3d8e7ec924063e5a867975bea3048b14af2e04a60e9", - "dist/2023-11-13/rustc-nightly-aarch64-unknown-linux-musl.tar.xz": "222e74a5a6d0564d81d97a2c95e9aeeb0f17201505f18f6a073f6ed7d6167148", - "dist/2023-11-13/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz": "20de495b3f5140777d268fcfb17031ef0ee6b28ba483612f8d8544922d42c1eb", - "dist/2023-11-13/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz": "2eb1a8ba2d86fd43a3276e676524a2d34bfff9b12c8531308e5c9ef3a47400a6", - "dist/2023-11-13/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz": "7e3b4243ada8f8d2b95c8e3920dbb92c5712a14033128bb3b5ce65ff83998d7e", - "dist/2023-11-13/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz": "bc6261b5cfc43a2f5d308dd086cad7d4c983cb4b8e57843789fb6271c2221d07", - "dist/2023-11-13/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "366dbc3bd8290cbd17cf831dca5e75a6b92c8b2e256c4cdbf98f6cb13d857538", - "dist/2023-11-13/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "a6584f803d16b4338c1d2535d1ba359932e4d7b539953b579c39c5171f902ea7", - "dist/2023-11-13/rustc-nightly-i686-pc-windows-gnu.tar.gz": "095b37bf7bb69726ff58296da5b597478a5af64682d8e69b7076154123c758cb", - "dist/2023-11-13/rustc-nightly-i686-pc-windows-gnu.tar.xz": "5d5727b6b7c52b7d46a161e31c2637f8de33080ff92424edf1a287d4499b33e2", - "dist/2023-11-13/rustc-nightly-i686-pc-windows-msvc.tar.gz": "06b287a308d728c990c1f7e63dc33e90823a2e74fed57cde8e6c1de1e265a26e", - "dist/2023-11-13/rustc-nightly-i686-pc-windows-msvc.tar.xz": "4f5a923e4193280cd5acbb81e6d578d55b119085963a7915e89a2c9c324ad550", - "dist/2023-11-13/rustc-nightly-i686-unknown-linux-gnu.tar.gz": "2a9b18c971ddd81ce45162d224f3d83954f47d2e4f20c9259aa2f03840b4c42d", - "dist/2023-11-13/rustc-nightly-i686-unknown-linux-gnu.tar.xz": "40769cf6e32903769166a1d47a99de93052c820e53770b7d253452c0f5122e1f", - "dist/2023-11-13/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz": "67eb782c10ce7abc56124f789023cebc5772a01f1ef1adf107a90120a4f065c5", - "dist/2023-11-13/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz": "eca35c310f253e95aa324ab8772f1ab6335020e609f632162707222bd9a0de35", - "dist/2023-11-13/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz": "218a990d7d01b093e59bcfaed89eb3b53d4a50d5e3a82f53e079df11660ed2a4", - "dist/2023-11-13/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz": "007cb6841bcecbe98bbff8b3542cd39afec275fad5d2eb45af733409b6b4802b", - "dist/2023-11-13/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz": "765aa9f6aaed661607ad4a54015df14b67da611a99efcf080036116467c2ca0d", - "dist/2023-11-13/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz": "8d3ff5b8df0befe504be38d8dfb0807980e2be4673f244c4633e3c5d118ce4d9", - "dist/2023-11-13/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "0e74f7782fb99fc29e663634dd2f08cc47b50f714e04a8544eef4eb4defa4db8", - "dist/2023-11-13/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "b1381bc7ecb0c08e65ff32152681c0007a55117df2f52f8cb33cb4abea7f14d7", - "dist/2023-11-13/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "69318b9a4f6e1da3e6751e6e4e089a2180cd4068f54a4e965f9fae8a45bf9c89", - "dist/2023-11-13/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "7c64b2d0a8a9d24ed41235e17e45e75668dca40ef32cca47a9ce428de94a2922", - "dist/2023-11-13/rustc-nightly-s390x-unknown-linux-gnu.tar.gz": "44fd98bb055b90813a346592b7dbc40633b339de09fa1184cc177968f08efcd4", - "dist/2023-11-13/rustc-nightly-s390x-unknown-linux-gnu.tar.xz": "c968ae5d316b3783af6449fbabbf034743711175cdce7922734034b7916ad251", - "dist/2023-11-13/rustc-nightly-x86_64-apple-darwin.tar.gz": "e0540ab928f55092b8e70426bb7d098e74cabbedcebe6ff77ab485262cfedb5b", - "dist/2023-11-13/rustc-nightly-x86_64-apple-darwin.tar.xz": "c37789b8a4f187492506e340a679cfc047332ebf5694ae764cb2474afd1281bc", - "dist/2023-11-13/rustc-nightly-x86_64-pc-windows-gnu.tar.gz": "e0980059f71c1af5388c65f6f8f317bb55c5788a7bfbfaf472358f30faefb14f", - "dist/2023-11-13/rustc-nightly-x86_64-pc-windows-gnu.tar.xz": "39a13cf1d38638bdd98355f2494221304fd9928558719a2dc36e06699a97dc68", - "dist/2023-11-13/rustc-nightly-x86_64-pc-windows-msvc.tar.gz": "6e22b7936652eec3ac0c1da277ba9ef89d805defc4fc3abea61f2ce68bcf784f", - "dist/2023-11-13/rustc-nightly-x86_64-pc-windows-msvc.tar.xz": "464cf4f724210a72cff14a6924ffd896cf160bc7ab8831e3580593a2f7e54a31", - "dist/2023-11-13/rustc-nightly-x86_64-unknown-freebsd.tar.gz": "c3a0ef4295a245c46e39c6a644a9a237e81dc95443930ec4230227b8bbdf2927", - "dist/2023-11-13/rustc-nightly-x86_64-unknown-freebsd.tar.xz": "6cf9e31f4e5a5276c426b3a3ba6d9ba1f9c7b253d30fb2dacea92c9dba19c53d", - "dist/2023-11-13/rustc-nightly-x86_64-unknown-illumos.tar.gz": "15cc5b822d9fa3d832899a07f5a373c6705907f26a5d90c97cad472eb6fbb383", - "dist/2023-11-13/rustc-nightly-x86_64-unknown-illumos.tar.xz": "5cf0eb4e4dc8cf25c02fa8cb9bb60c27212a77088a6fde5a97a6dd11d21b9c5c", - "dist/2023-11-13/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz": "dbdbe9ad1b19a9f746d1831fb20be9581dbe7701544bedccb08458fb89719c33", - "dist/2023-11-13/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz": "e1d08f9cb45c86de3217d8c3bb7fa6f7ef201ac826b19b2750aa770f6b665cac", - "dist/2023-11-13/rustc-nightly-x86_64-unknown-linux-musl.tar.gz": "2b30ecd41818e8e39b286bf1ea69353416bf79b38f3119bdb98c2ac4594a5f76", - "dist/2023-11-13/rustc-nightly-x86_64-unknown-linux-musl.tar.xz": "ad42102fab1902fc1273e776345cdda9e40a5a39574421397405b7657741128a", - "dist/2023-11-13/rustc-nightly-x86_64-unknown-netbsd.tar.gz": "a7b7dcf01dedf0c88443ca2baa49b84ff2027b8bc68502af0f53647fe2005bdf", - "dist/2023-11-13/rustc-nightly-x86_64-unknown-netbsd.tar.xz": "27410cfafe573d12e7fe5c2649cfbb6487a8df172867bf665bf3b3d67dfd44ef", - "dist/2023-11-13/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "fe2710bc7ab0f0a5e4797b011ea47ae797ae3824bd03d59d8c5a92222f750703", - "dist/2023-11-13/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "3cc0c843aa31d9262aff93b597673fe5c0a78bc9fc66a92899c498f566dca806", - "dist/2023-11-13/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "31d23f4bb53bdc6b93a07e50de1a8b5398c5f8e747f4da6b6bafa499a6ef9b83", - "dist/2023-11-13/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "b4d8b84c9fbe2635fb88c9d26a6f86b51651f07a2f8f139d332b49749e364525", - "dist/2023-11-13/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "dd24bd46bf4c24678d7bbee6f7b8e3bb6417131acb3f19c8293b84658e259d37", - "dist/2023-11-13/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "77cfd74f88a8266e3540bec0a4ea669694cb171145ee368158953d47ca74106d", - "dist/2023-11-13/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "63c3c7d5e72813514df27bed4d9daa2d3eefbc50176dba2ae48cc1aa85bd58d0", - "dist/2023-11-13/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "d01d0ce2aa536d635f3d69f6ca7c15b351a2dbace08a1c2aaf8718e6ea07829d", - "dist/2023-11-13/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "8eb1391c5657980cc8a810c1d5b14a28421b4bf81511e4a6e31a3aef15f2c689", - "dist/2023-11-13/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "9eac418607a5f9b1818439a608179ab907a0c2333ec05b18fcf6a36c0d1f67d9", - "dist/2023-11-13/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "d1221f9a330abfd4ffaec357d589148e0484200328cbc1db3224096be012ab30", - "dist/2023-11-13/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "51b2891e0296ce41fa57468cb97b9bb4a3e0a251ba7a5095ad828e5aa175d8e4", - "dist/2023-11-13/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "0d1c59d8947b77f2078122a3fc9c53b3179ba87caea53fa9156d3af913ac42fb", - "dist/2023-11-13/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "607811fe589646c251f14ea1981465000259605e9ddff8ffccdfd0936f851d16", - "dist/2023-11-13/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "044e8b5bff3a8d3259023706c0ef03c8068704534dd8f804c4f53466e35807eb", - "dist/2023-11-13/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "a27ea67409922132ab294a734828980a279ab5cd8a3d8c26b590e313e7da2ed5", - "dist/2023-11-13/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "0bd3c933ed3345fee541549127e20dd63f52a533f2f22523d1db096132ce0aaa", - "dist/2023-11-13/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "4334d49822f9a85d43fbfa463b55d4b9c424ef058c4146852a252162fdbc198e", - "dist/2023-11-13/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "5015ca31e974c16050e44c6ac6dffcbfa82b7532951842dd2745139463c5edb6", - "dist/2023-11-13/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "40380de3945ea3dee9dd05e4dc2d2c12a7d621d9bdfa59233faa2437e80db915", - "dist/2023-11-13/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz": "478ebf6629bf890c8d3726f090b8fcbc9cc5d5d828ec3554287668491e2bbf8e", - "dist/2023-11-13/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz": "3a130b2b7e06f6c16325bf36b8f5c702335c745471bf946a9d0ac2202af65fbb", - "dist/2023-11-13/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "002db7233067339672abc2e210d98897a3870842cbf1e487ae5c111d5bc949cc", - "dist/2023-11-13/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "a514b43eb0c1d8e2d20b6ff77b611e126d06522758f6d31b6fbd94639a6f04aa", - "dist/2023-11-13/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "7d21d10b85ec4f720ffca74184758eb568050776f1d3592dc65075b9c83c9f8a", - "dist/2023-11-13/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "2a335532b528ca936903bcaacfec2f34ecb37ddc88bc8c0762fb12c1bdd71d9c", - "dist/2023-11-13/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "73f983755c3f413abb0be9112776ee4ea3a6a122abc37e4f0aa81021dc7dd67a", - "dist/2023-11-13/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "dc164f3dcc898851265f3353f0400953637ea7b5684e91cac6961c2dedb50d03", - "dist/2023-11-13/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "b81877958bad0de48add2148ced0cbee5a66233386d0b50e9fef6ea844ac808d", - "dist/2023-11-13/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "4f755394b456a00a929d89aaa7814e70882f7ffd62489a833be4707ae687c465", - "dist/2023-11-13/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "8d1a9321201939ae453f21fdfe9498e1edcad176b9490531655f47fe7c3c9269", - "dist/2023-11-13/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "1fa1f0161620cd73e1a0bf39ab5225c77e9f3e0888cc0d59b71dab260f7cca9a", - "dist/2023-11-13/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "b6bd3c9eacbb7d10d16e82a9946a77442495259951705dd7c9685f02919c1c0c", - "dist/2023-11-13/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "777f05162f4c6396cf0ca75fed5ff37539534f179a399e3032f0b1b327cf53fe", - "dist/2023-11-13/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "dd5c0eccf137eb8c92211c062057b7fd4a8c49d60953498d3b123d91e1359e29", - "dist/2023-11-13/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "9d90e65fd32c86c77e96b0c46d47d1c2a04090f22d1ba3934bd0507fb8fc09c6", - "dist/2023-11-13/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "a33338f00147ee970b14cd24be361216d3f9ffb963952aa8c5b6731fb6cb3505", - "dist/2023-11-13/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "399cb9ff66482ec0200b4c8750d344ee77900972838b11895f9b542a43e75931", - "dist/2023-11-13/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "46ff40a2afdd62b0b9e3d39ba1ca7ba43a9719ac23cb7b8ec324f0a60859805b", - "dist/2023-11-13/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "c14de41967e9b30a166516944c399f490be89cb9217255e9d22d33fb03489d9a", - "dist/2023-11-13/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "df917224a72d311e8e26632413507dce4e4d3203c049545959c481905939da37", - "dist/2023-11-13/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "1f19725221ec719718a5836bd911f0f04e4a604e71d2557ff28713e5cc58b8e8", - "dist/2023-11-13/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "cb50baa37637b79cda8e7f7fd6a77fedde6ede21063fc3c01c7c61558998df4f", - "dist/2023-11-13/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "a1bf9051bdd85fa33041b84378af684ed974671f17694e00d6f370a27b0563d9", - "dist/2023-11-13/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "5a2df248d0586d4ea49dceaa9400ee9ac4b0cb1a97076b6ec366a9b55217fee9", - "dist/2023-11-13/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "06d4e6d2a909cefef0988d4ef35cd9ae6ed6d87b83a08a91ef2966ebe5989803", - "dist/2023-11-13/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "aba0a7d2d67413990bf0ae9b8f4fd580a43f708b01ae8403fce0c4eff1f35b54", - "dist/2023-11-13/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "53891c1cbf7ff0f648188a655a6dd7c253997f230f4bd7eaa1881bce54128be7" + "dist/2023-12-22/cargo-beta-aarch64-apple-darwin.tar.gz": "80a4c4d72f7f436105084047a5806c5665749ecb84ff06bb25e759b56049e610", + "dist/2023-12-22/cargo-beta-aarch64-apple-darwin.tar.xz": "0290ccea9da40123cb5ce9d8c22721e015de77525e267003faaca4a161179da0", + "dist/2023-12-22/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "85c79d51b2d8480343546a6164fea3f1992a4b8de3c6a45a4952b0eb2ee467ab", + "dist/2023-12-22/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "f9174eac9ee6dcd60c24ce5ac5341f16ebb5d704f79bef585e963576a7c7c624", + "dist/2023-12-22/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "76fdafa72f31538fe1747da8ff63a16af91affddc0564a8a3bc1d96bed242466", + "dist/2023-12-22/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "22ae3c0460073037beee67f0bd9d86af0b72c90d9ee6bf14bb6f09e9cbdf2471", + "dist/2023-12-22/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "8731388fe7335a9c31b33ed3bbd5a4e29402e0bfd0ee4b0842974a9416859c8b", + "dist/2023-12-22/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "38f8907aab9795465b8be1d0e38ad3b812ea6ea6e3672773b43e4312677916ea", + "dist/2023-12-22/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "19e329bd134d01c73dd74a10ee63e35782692cb54ee9dd81556b3920fc055b3b", + "dist/2023-12-22/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "b3f4fab444cb5bd462a36f8fb3d90a20042389a5f809bf431dc51645430b6dfa", + "dist/2023-12-22/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "cdc61bec25e556c6d0ef1150c1a01225eae4e325bce94bd49d43ff1d2b2f4049", + "dist/2023-12-22/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "082ed52b5bc4e8b4ac16e9a7af81ad774827e41af63532599ee41724b6907378", + "dist/2023-12-22/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "7624915c4adfb8af8d294f581a3ca4796d53a76f7ccb6546c858e0f785adb252", + "dist/2023-12-22/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "c224a28f4ffec2b820ac26e21e4bf1e6ecc67f47598e91d34a4e922c21cd967a", + "dist/2023-12-22/cargo-beta-i686-pc-windows-gnu.tar.gz": "d936b84681f2b5fd7da75c99eab6c40ae5464b1ac97733cf5774ae7783fad941", + "dist/2023-12-22/cargo-beta-i686-pc-windows-gnu.tar.xz": "fa2864c6cbbe940a81a497fcb307afbd7c6c0551346676daf2fa0b488dc72489", + "dist/2023-12-22/cargo-beta-i686-pc-windows-msvc.tar.gz": "1b6ed32c7f3b3c0b2f09e43ab04ecf62aa11c778911b860ee0a82cd22fa8ef0c", + "dist/2023-12-22/cargo-beta-i686-pc-windows-msvc.tar.xz": "35cf7cf47a49af4b68171264943adcee5c907d8d4fbb021a0716e10ba946655c", + "dist/2023-12-22/cargo-beta-i686-unknown-linux-gnu.tar.gz": "cc993cf80d125d5ac25210dee1706bd23aa94f949fb94aa22409f434bafe3c35", + "dist/2023-12-22/cargo-beta-i686-unknown-linux-gnu.tar.xz": "60e2bcf98f9969bae7f61987bc30e2358c832033ea98be6f8e08e8b95e8b2409", + "dist/2023-12-22/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz": "08dbad235465958534802c1609f881561767a63a3373033678caa29b7384e1af", + "dist/2023-12-22/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz": "cbb79d6e06e12b7bc278d6b3a220380e1d4e863c60eed3462ca4f310b25bf247", + "dist/2023-12-22/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "f25b99291e3d7ed8891ec1196a3bd747cfc755b3c0bb27cbef0fb1aabeecd950", + "dist/2023-12-22/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "0c496d22b1f641ea4bef847a1efe7b69737b0c1d7ca2920ae0a1e87ca99c00e1", + "dist/2023-12-22/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "9d9800913636d33b9976416fa128d6e734c98978c91fdb846a16c9f2b014a77e", + "dist/2023-12-22/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "668dda14116c4d54f43653efccdd2a4d211dfea1a08ae5fe02fd69d21b6d9783", + "dist/2023-12-22/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "ec8b813a83d0999a2181c3e026cc43c0004bcdef621ef07c9741b71ed60858a7", + "dist/2023-12-22/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "dda9fac6999682ad9bfbeca1cc26b4b083c99558c531e2137bca4b22331527a1", + "dist/2023-12-22/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "ff1153a92dbdf499e6cbcea37d6be513e1c844d303032f9f1f2c9af45dd43b26", + "dist/2023-12-22/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "3b8247891ac28674ff4d647da93e267e2400f948b60c870227683463466bc983", + "dist/2023-12-22/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "239486637406a61f1aa25925f82131a31d133972e7926dfa54152285ed83917f", + "dist/2023-12-22/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "7e9d66d61387aa45a1141187806bc181251b1164bbc48e6b52d8770d746507b6", + "dist/2023-12-22/cargo-beta-x86_64-apple-darwin.tar.gz": "3d47e067fedaa2f96cbb33b23315d52d7f5a3379cccca560db312e6cfbbcab39", + "dist/2023-12-22/cargo-beta-x86_64-apple-darwin.tar.xz": "7d7b2239cdf1e946ee97ee81ce69f2fe2f3695a82c0434a4a853218547ee58b3", + "dist/2023-12-22/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "34b195423b12f4253dbcb47fe9bd55e1bdb302c86096ee9f8248e65c218c5ebc", + "dist/2023-12-22/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "d7ebbe5c54ee55ee320e7a57e323d7277afe7c56ec31465fb8012cd436412ef4", + "dist/2023-12-22/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "41c1b391e8f132d8bb18d79e52cf2c7e0443417854943608383073cbb977b1ce", + "dist/2023-12-22/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "f75987c83543c4994dffc7dfb0bfb57390fbbdf79165360d94fd6513b3bf8abd", + "dist/2023-12-22/cargo-beta-x86_64-unknown-freebsd.tar.gz": "56d4ada9b370a6fb3b1a654aebd710194eab8e6a2f7f46df9f191a4ae2d75d9e", + "dist/2023-12-22/cargo-beta-x86_64-unknown-freebsd.tar.xz": "5337096841f04ba7337e8b35df5197fe078832fc417cbe7b4de454c45ae797bc", + "dist/2023-12-22/cargo-beta-x86_64-unknown-illumos.tar.gz": "e1ad1e2044a8b3329349a33a70400491cb79f5e7c847a626c96415f240e6720a", + "dist/2023-12-22/cargo-beta-x86_64-unknown-illumos.tar.xz": "f3546d9d207dc59c67dc8e13ccb0abc3fba14ca5feed4f75e0f3c28e31c9ad5f", + "dist/2023-12-22/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "0497f21e775ab847657c6815275d2a8cf03e4d9b4e75975eaa5eeef7fa84b62e", + "dist/2023-12-22/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "5fc2c06ff83063e7c992729f2dc5dc62771c5e0adeb04b0fb4e12f73b166d29c", + "dist/2023-12-22/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "ce5cdea30636dcb14385ead3ca2d31ded9d3f243234c82b3326551c0cf03d599", + "dist/2023-12-22/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "086662482440baad1b5cb738301a186de41ba6512bae1d77369d65e37c56d818", + "dist/2023-12-22/cargo-beta-x86_64-unknown-netbsd.tar.gz": "b59d49075a3a3fa2aaa8264d3a0c4444400dffe4780bb5efb350d9d558dfe5a9", + "dist/2023-12-22/cargo-beta-x86_64-unknown-netbsd.tar.xz": "bd940fc6505c603a2d0e4743af3aa1df6ef903676f31bf4f06083cf86ba0f4d4", + "dist/2023-12-22/clippy-beta-aarch64-apple-darwin.tar.gz": "42e4c7e85b516b54bc9a92fdcbaf31a280121a6264ffc00bc4330bb3f3d1ef09", + "dist/2023-12-22/clippy-beta-aarch64-apple-darwin.tar.xz": "1858bb5aa212dc68c694e044dd138f58a94ef236e29623b46c275cb9765d1433", + "dist/2023-12-22/clippy-beta-aarch64-pc-windows-msvc.tar.gz": "8ec1c0c20dd3381bb2177e3ff28c777a7de6aff5fa557cf3b4e7ebc6aee7de84", + "dist/2023-12-22/clippy-beta-aarch64-pc-windows-msvc.tar.xz": "cfa8fd15c5b0ff1570a99ea15004f88a8ddd50f6d367082cf6464523355666c1", + "dist/2023-12-22/clippy-beta-aarch64-unknown-linux-gnu.tar.gz": "eb81038f1cc56601719a6165da2ba71f357f00ea3380e46f0a1283174efaa9d2", + "dist/2023-12-22/clippy-beta-aarch64-unknown-linux-gnu.tar.xz": "dc4c69b81fd186e40b6df3900d0c555214b999f3c1ca5a2697d93503357c7194", + "dist/2023-12-22/clippy-beta-aarch64-unknown-linux-musl.tar.gz": "e2fde1d65c46011d3ce80e1e46e13dcf7b5673009398296cd4126b1e4a9b2cb0", + "dist/2023-12-22/clippy-beta-aarch64-unknown-linux-musl.tar.xz": "b6a422245e574c149b984655f023ca3721c1b5d5a08245292872d86e4b77980d", + "dist/2023-12-22/clippy-beta-arm-unknown-linux-gnueabi.tar.gz": "4b3ece564b22857b0741080ce20f190dedbd72fa8c7a284921e4c3c481fdd264", + "dist/2023-12-22/clippy-beta-arm-unknown-linux-gnueabi.tar.xz": "bab8dbbf290576dd9f77c9685f5f1bab114215c85c83512d87839a08a3adce6e", + "dist/2023-12-22/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz": "732adcc6849929efa239a8f5c638fd68324d8f05330b518b8b0804351ae6889a", + "dist/2023-12-22/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz": "5d726d8da3909f1ca58e1b5b50067205b90bf1a7689c516abce66a14b68fd524", + "dist/2023-12-22/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz": "c939f4d6675dfbe0ed0d0353fd9a26b0f96f53c0118257d306eb46c883438b8d", + "dist/2023-12-22/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz": "fa1a7abcdaa6f0347811849dd4dbdcd438d0e47824541b22b1c64fba8c6c1482", + "dist/2023-12-22/clippy-beta-i686-pc-windows-gnu.tar.gz": "c1b16be465960d03658eb10c6d65ba363ecb75d17eee49e2da0d055a97d1ebfc", + "dist/2023-12-22/clippy-beta-i686-pc-windows-gnu.tar.xz": "e5997892281f08da9445b53c564edd678b7b768624bd29ef55a0bfa6a2022cc6", + "dist/2023-12-22/clippy-beta-i686-pc-windows-msvc.tar.gz": "92400c8693ba05a186c6913f69e838cd6668eec60864e5ff857e1da2cd8469dd", + "dist/2023-12-22/clippy-beta-i686-pc-windows-msvc.tar.xz": "550430a61f5e17fc30207b843f99a0f56d6fa07c6c458ab560149027b69599cf", + "dist/2023-12-22/clippy-beta-i686-unknown-linux-gnu.tar.gz": "a99bd3961497a6266e3fc9d4109a0c1304a6759f6d7062a5175afb5459658346", + "dist/2023-12-22/clippy-beta-i686-unknown-linux-gnu.tar.xz": "b8471bfaaf94b61523ac88db9c91c20f67bf24a16367795b2c925abff783fab7", + "dist/2023-12-22/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz": "601760057229682f332e4b005441111eb1573c7c9a9e286f0699019df3b2d4fa", + "dist/2023-12-22/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz": "45b7f4d75ed4838d3de0ed8c70d2ce6a248881c609bc4b883a549f11d12067fa", + "dist/2023-12-22/clippy-beta-powerpc-unknown-linux-gnu.tar.gz": "6c4fd05f37c0e95046dc87c24734820920a3ec62f3507643f42691ba349f2418", + "dist/2023-12-22/clippy-beta-powerpc-unknown-linux-gnu.tar.xz": "0aab738f846ad507138c0a5d40823a0db7d89ff130f24e550f337e085dc3ea8e", + "dist/2023-12-22/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz": "007d761b7eb5d5ed5911090ac55af2288e9a97cc4affc5ca488ebde7cc3ab0e6", + "dist/2023-12-22/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz": "ba9ecc14573a882641685cd6570e515a31fa9f3a9973dcef58f3db809b932fa0", + "dist/2023-12-22/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz": "efcf9a7bc03f8e984c6ab3fa2bc269fa5387168992c9fd2b8ab09bbd7111c6c9", + "dist/2023-12-22/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz": "1df14e1f3cf785c9cf5477b584fdf11f1f7e12431a5092cc5cdf6c2878bf4275", + "dist/2023-12-22/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz": "8527bf2c96fba74c09d7b1051616631d0b4e6bace8fe44c8c76f295c9a4eb55e", + "dist/2023-12-22/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz": "cc58fbe8d4d7d0011045f64025bf75e2042b7967b7fb1f297cfe8a0175197258", + "dist/2023-12-22/clippy-beta-s390x-unknown-linux-gnu.tar.gz": "c1e41ba2a77f6c0d33751b12522310bed37a032fc01947b9d78e8492a2c74ca2", + "dist/2023-12-22/clippy-beta-s390x-unknown-linux-gnu.tar.xz": "a90903f78305533e5315b3dcb26218a91e1733cda5e2fadcada80fe06b3e1a17", + "dist/2023-12-22/clippy-beta-x86_64-apple-darwin.tar.gz": "73839c078dbc472a8c5d87686eb7e09db0030d567079359f9a750a52d1d300b8", + "dist/2023-12-22/clippy-beta-x86_64-apple-darwin.tar.xz": "fbc52b8be57b032d04e885b325deb3c2d61bce1773fdd68e7b0889a1ba9a167e", + "dist/2023-12-22/clippy-beta-x86_64-pc-windows-gnu.tar.gz": "5a618cf8c09bec0e593449648bced16153b6783f98e41d685e5912418710fff6", + "dist/2023-12-22/clippy-beta-x86_64-pc-windows-gnu.tar.xz": "f6a7c30cb183c8cecf22d95487250c121d5fe1cacf2bc4e64bc160b4c4cdd566", + "dist/2023-12-22/clippy-beta-x86_64-pc-windows-msvc.tar.gz": "58b5ae0e2f46d4f7e64491a4ffcc9180e8616cc82b095526546942b0c6e43583", + "dist/2023-12-22/clippy-beta-x86_64-pc-windows-msvc.tar.xz": "aa146f4c9357bd167e4aed6919a1dc780fb57ddb9e83a4332442cb779cc61e1c", + "dist/2023-12-22/clippy-beta-x86_64-unknown-freebsd.tar.gz": "56b1d7fbdc1e47e8a31243cbbac747b1980b61d45f2daf260d49362f1413f3e2", + "dist/2023-12-22/clippy-beta-x86_64-unknown-freebsd.tar.xz": "c0e5ca26067fbd0279a36c03f68e07757817aa2207a69250224f6cb44cb9711c", + "dist/2023-12-22/clippy-beta-x86_64-unknown-illumos.tar.gz": "404cb75b4ae6f2f0f456f77b4e639ddd692c3f47d6f32b168b275dcc999db4c3", + "dist/2023-12-22/clippy-beta-x86_64-unknown-illumos.tar.xz": "b6c156a01ce3f64fd781669c351df169c0c0485b0282ec33d1c541e7990e1ef7", + "dist/2023-12-22/clippy-beta-x86_64-unknown-linux-gnu.tar.gz": "6a2e75e81a2678cb97a47e695b74dbbf0737cf615bb94d1679318bcbe77a0fff", + "dist/2023-12-22/clippy-beta-x86_64-unknown-linux-gnu.tar.xz": "6273b5b834766a93c2f65a3cf2283bf1669c1dd9b9f1cbbab497ea250532ef43", + "dist/2023-12-22/clippy-beta-x86_64-unknown-linux-musl.tar.gz": "bf4ec57ca170ccb4ab3fc4d42907418011e5dce9ff3fbbfc341e70744e9f0c8e", + "dist/2023-12-22/clippy-beta-x86_64-unknown-linux-musl.tar.xz": "d875bfbdc53bcca521707e3d08fe3b2c2c2dfeab81634c285228ca91278fd659", + "dist/2023-12-22/clippy-beta-x86_64-unknown-netbsd.tar.gz": "43ae50703b81f0fdf726b4790afd539f2d5a1dc56507df2726bee693f121550b", + "dist/2023-12-22/clippy-beta-x86_64-unknown-netbsd.tar.xz": "894acb6cf32ef66d2b79f24ebdbf37dc8d51f36d9ec326a294cbf4be3128ce77", + "dist/2023-12-22/rust-std-beta-aarch64-apple-darwin.tar.gz": "81e9bbeea89702fa3843a5e6bed8b5d3d5bb035d94adb335dfa91d084842fe17", + "dist/2023-12-22/rust-std-beta-aarch64-apple-darwin.tar.xz": "1457fbc52b8e8e6c751b69b6b5b3401bbac86f5aed500885fd86128963e6f8ca", + "dist/2023-12-22/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "e2574432b2b7e8b056f8d9864142be20fb83ec516bd27f7f937c04c2d9648218", + "dist/2023-12-22/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "91fb8193d61c741ee39e1429c8c6e7dc51cb10d5ed1d5f63c4572dd1941f26e1", + "dist/2023-12-22/rust-std-beta-aarch64-apple-ios.tar.gz": "6a1b2b7d583e105daca8294fbd4e3f17bcf345ab536eb4e74962a2efc65c9eef", + "dist/2023-12-22/rust-std-beta-aarch64-apple-ios.tar.xz": "3c54c2a8b24186c5100898a33837141119d77cfd5363acbb8508630752198208", + "dist/2023-12-22/rust-std-beta-aarch64-linux-android.tar.gz": "c9534e00a3b99390a80f23fe580bcca0eb17b8bf5c0731158e8e719ab17bef74", + "dist/2023-12-22/rust-std-beta-aarch64-linux-android.tar.xz": "bbb5bdcd5c698d2b089cf57dc071814aa91e51e76fae5a321b0f3bee837dcbc1", + "dist/2023-12-22/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "c862de6118465dbc356c69c23d1a755243d86945522cb6a87bd25321a5cf1346", + "dist/2023-12-22/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "f8fe6f868c007b3a32b2e20fa397d2aeaa18c1af52bfbf90d181b0dede6235cb", + "dist/2023-12-22/rust-std-beta-aarch64-unknown-fuchsia.tar.gz": "3ef167b633f128d5e8b28480169fdaa559c742db7091445b33b7225dd0ab6b17", + "dist/2023-12-22/rust-std-beta-aarch64-unknown-fuchsia.tar.xz": "d6027f6826ee84962b4f516204c5e48c4d11a738349d20071d71eb249ab19294", + "dist/2023-12-22/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "2885ebe19250cc078804941bd33d71ac0ba52c8f55c03db0a9d2f7b4b86501b4", + "dist/2023-12-22/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "fe587aec91d8586f5ea93783541b3b1dc005cc9fa92d07a42e93c6cf3570224e", + "dist/2023-12-22/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "b2278c605233768efdbf272b6c1c64b5770330603f0d6ad2e9fc725790c65593", + "dist/2023-12-22/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "40cfe524fc6a97a894d8fab0bcab8a00b72781ed1f8c3273d26e784162959d1f", + "dist/2023-12-22/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "77d9010f59baee9e88fc883cc085f04282b731cdabaf2e3eeb4ccbb8e950c526", + "dist/2023-12-22/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "4b633e678448b03b868dcd038a2a2c4dc78cb600324283b38ed942ee439174cc", + "dist/2023-12-22/rust-std-beta-aarch64-unknown-none.tar.gz": "901d032bf3dac71e52c727264daf42c923adcb12c771f135aef0aaa7784a9c63", + "dist/2023-12-22/rust-std-beta-aarch64-unknown-none.tar.xz": "dd7856ab1d91d92c09f65c8e6fdcada0ffaf63890c656e9bf5e7fe1c5f83cf32", + "dist/2023-12-22/rust-std-beta-aarch64-unknown-uefi.tar.gz": "c64dbbdd967193c3ed53c58e0545a93411e63c83bf0274d40691d1c5e5c58a2c", + "dist/2023-12-22/rust-std-beta-aarch64-unknown-uefi.tar.xz": "bf28490141ed88753548a96615742e7dd13efb6bf7ed98e7cc548409a79100df", + "dist/2023-12-22/rust-std-beta-arm-linux-androideabi.tar.gz": "aa84489eaaf4ae64a56f64a4f7e2240d41ae77e6532bdaf35eb2163632afd051", + "dist/2023-12-22/rust-std-beta-arm-linux-androideabi.tar.xz": "a3cf5b44498c85fbd8f66a776e5947e9b552a8b8110b19b4611ff042d040294f", + "dist/2023-12-22/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "aa4f3fa1994f51228853c8abd1080ac0804d7fe782a2c9a533427555c1ed5db7", + "dist/2023-12-22/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "72340fd4f0110ef21cea8e7a54182cf65b616e6c4834624b7971ad8a9c00b4b2", + "dist/2023-12-22/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "5b0b9392fcf9673e69954141470bd4eca00867a303b4f24354f27cf09da1cb8c", + "dist/2023-12-22/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "326ea10b82742012a648cf5eb9eb7b6e09087a324e3ff9955df5031233f45d6d", + "dist/2023-12-22/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "a7b7a2cde45cfc3d4d74031c36dcb8ea8214f4517e96b5a09bc46f898faf967e", + "dist/2023-12-22/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "b178e41c2ad6089e3448209cab7808e93aba7700aa3571f062dcdab74e4753b9", + "dist/2023-12-22/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "0de36da3bec6c34a6e56162b92f88b42ed76e596459a6d1416748b9fa8e8225e", + "dist/2023-12-22/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "381006c411b222254b5bc55302096678a47fd085de06615558dce5085da47f22", + "dist/2023-12-22/rust-std-beta-armebv7r-none-eabi.tar.gz": "464271fe1c2fe699167afbfe9cdb2ed2bb3a38671d616f6f28d6b7fd4fc72cf4", + "dist/2023-12-22/rust-std-beta-armebv7r-none-eabi.tar.xz": "13dc946ac5dd45104c51010bc8a0bf5af64d549cf6b59f8b8b0ac9b06dc5d0f1", + "dist/2023-12-22/rust-std-beta-armebv7r-none-eabihf.tar.gz": "2e01997df04b9635d840ca177e4ef379232955cc586e2196c26ea1e18b66f883", + "dist/2023-12-22/rust-std-beta-armebv7r-none-eabihf.tar.xz": "a11c1e8c52ba653e5c58baf886b6b1383c622632959d09321ba1dddc2a91caf2", + "dist/2023-12-22/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "b036abe1c19e3f86b80ee670196194ccddf0bfa5261d4ba9fc7994aecb5a487d", + "dist/2023-12-22/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "a9b90e4b43353feba58dfab424ae36441077fbb6b8469bc071c058f0bd85aa81", + "dist/2023-12-22/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "0faac13a81d60fd9315c6ea6c929b1fcb9366b23119b658dc05f10a0b4b2e2b6", + "dist/2023-12-22/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "62023710833973795681275bf34c45a309327f6e76934603c58b07f204e67a20", + "dist/2023-12-22/rust-std-beta-armv7-linux-androideabi.tar.gz": "f48e6eb32ae56fb09a9860f529cb65ca4168d068b6bfa6b1b3164590628ef635", + "dist/2023-12-22/rust-std-beta-armv7-linux-androideabi.tar.xz": "dad3d32a6314f7c9de8003476f9667d19f452a331e6363bf25c2ed255a8b0063", + "dist/2023-12-22/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "b8d045889b709783387752e6275c6818c353431bb7b9599e9aa88c6e373072c8", + "dist/2023-12-22/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "4750a55e19b27b34e59daa2d1b0f6655ba9d8c491780c785a7adbcc160eda425", + "dist/2023-12-22/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "829c608b0f7f4f6bf73688a30e51d69228b69a9487137751e0bf641f7e8e227a", + "dist/2023-12-22/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "4e4d1b1d10b1b7931e2a801cc3d3edb68c91d5f58baaf99fa2f88b9174f2b294", + "dist/2023-12-22/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "cab9b7f30fd074005c59ab5dd4d59c498367671373f5662047c8e16c19236141", + "dist/2023-12-22/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "b281e7c3a32523de34c2f7ed646d19f4f32b1db905a222aa1301f8bc57e312f2", + "dist/2023-12-22/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "ebed7143f8cbbf5eb2b99328c6246ecdc51905a90c4c832a13d76f6467e2014a", + "dist/2023-12-22/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "6c06418750cabc38f46e434890c2422df9be5177ed1f4b04dc7f67e45cad307b", + "dist/2023-12-22/rust-std-beta-armv7a-none-eabi.tar.gz": "06d20a34ef000ab381025c0458bd327d3a2bb13a77f3485334cdb63e51a7354f", + "dist/2023-12-22/rust-std-beta-armv7a-none-eabi.tar.xz": "741edc509d401328adcf462aba08744614ad655fa42f89c9818aa1dc715e2d3e", + "dist/2023-12-22/rust-std-beta-armv7r-none-eabi.tar.gz": "0a5c38d1a7a9d653e32750a5f600f1887422d4e90360b6f1d98df45084436822", + "dist/2023-12-22/rust-std-beta-armv7r-none-eabi.tar.xz": "ae960df5549284a7976129da79916287d84f1d9dece2bb8ada6a3f3cc3246509", + "dist/2023-12-22/rust-std-beta-armv7r-none-eabihf.tar.gz": "9280fff8012234559ad644edbe9827c2ef6931d95fa96b5f6a4aa7321215f5d2", + "dist/2023-12-22/rust-std-beta-armv7r-none-eabihf.tar.xz": "3bed6d2a89baf609089c431e73d36b73417541f63c8f2bbb190bdf706cd85e93", + "dist/2023-12-22/rust-std-beta-i586-pc-windows-msvc.tar.gz": "b8bb7b950134f5e3ba3257ffc55d2b0e4b483955e74f6a146017c1c818359ab4", + "dist/2023-12-22/rust-std-beta-i586-pc-windows-msvc.tar.xz": "3c3b4771cd51159d35cf5de21e9bf625453972a53207ca3e6a027901b3eeb7c8", + "dist/2023-12-22/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "ed89e574db830d882f1f12f9b570bbc5f4c89776808ec05cbfcb498eb947e6d2", + "dist/2023-12-22/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "8c32678710cec0971aa6f740cbb525c0c174f6552d181466b7d49d5822d671c5", + "dist/2023-12-22/rust-std-beta-i586-unknown-linux-musl.tar.gz": "2ebc2381b980637844cca7be78a01d204472328897bb02c28b8b5c32bd8d20bc", + "dist/2023-12-22/rust-std-beta-i586-unknown-linux-musl.tar.xz": "df48e6af6cc9df2fba7af56b4cccd07e53a0030de964c11e83b7cdaff1bff4f1", + "dist/2023-12-22/rust-std-beta-i686-linux-android.tar.gz": "25e6cadd083ba7f02525e411677ebf8470bebae19c0f5fdba453140ddf97a3d1", + "dist/2023-12-22/rust-std-beta-i686-linux-android.tar.xz": "bdc722479c73b6fcc6ba401d6f747acbfbdebb074e911bd44a20c8c3ce8192b3", + "dist/2023-12-22/rust-std-beta-i686-pc-windows-gnu.tar.gz": "6a8b46606ecb46d16f2d45ae82faaf155ad617b1b81259eed93b77a267b5265c", + "dist/2023-12-22/rust-std-beta-i686-pc-windows-gnu.tar.xz": "97c58f4e4cee06dd38ad9e3a56ce505434ee77f0f0db30432d04739d301a194b", + "dist/2023-12-22/rust-std-beta-i686-pc-windows-msvc.tar.gz": "1012704d42aaaddbf0679013ea578245e88200afd55d1d510dbe58bdd14b8ef9", + "dist/2023-12-22/rust-std-beta-i686-pc-windows-msvc.tar.xz": "cdb291df9fc41e038b38a3a421b791a2c39be3bc9686c5d6e93cbaef95c2ff6b", + "dist/2023-12-22/rust-std-beta-i686-unknown-freebsd.tar.gz": "20df3466ef1a82ca986a3239efba9d984535c64d5663f2b3b92b9d6ec2972b25", + "dist/2023-12-22/rust-std-beta-i686-unknown-freebsd.tar.xz": "6a63dcb9f7312432c6bf290dc3fea10d56a17472cab65c7d82fde30c800d8b5e", + "dist/2023-12-22/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "8d3ae5e37ab866b93bee661773301956d8e6e2294910d0ff04f782f2c7271dd6", + "dist/2023-12-22/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "9963bba2883125aded9c6639dda498c3effd574fa032d2268455948df3243979", + "dist/2023-12-22/rust-std-beta-i686-unknown-linux-musl.tar.gz": "64e13948dc71571be5c3a4e367d961bcc0bc38167680e86a55b2d1357a45b7ba", + "dist/2023-12-22/rust-std-beta-i686-unknown-linux-musl.tar.xz": "ca54983531703de8f7350e00bad2cde13dc996d9de1c0ca1728b50a015dcb344", + "dist/2023-12-22/rust-std-beta-i686-unknown-uefi.tar.gz": "a4e3c395607d9ca189c130e371c49ba0a08d1974c56c656a23870d0ca08f0cf7", + "dist/2023-12-22/rust-std-beta-i686-unknown-uefi.tar.xz": "20e6ceea5246322840b3fc76b01b16ef32d829ae4e587a052512c39c3c3babca", + "dist/2023-12-22/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz": "6e4dd7fa56112a879917ea24bfbd45dca625ee812908867e427f23d56deb910b", + "dist/2023-12-22/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz": "23862a72211645d29557d3a1dda63948335d15a9796c139a0676124905e72906", + "dist/2023-12-22/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz": "6abd7c64f58bbcbf04b643a9787f0fef1fe80b89b82143b6251b57afa560cff0", + "dist/2023-12-22/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz": "53fa4d33241b73653523810e441bed53dcac8c3fb7b7de88c125cb8ab8eb66df", + "dist/2023-12-22/rust-std-beta-loongarch64-unknown-none.tar.gz": "bb94b1d2391e11f268c0e4c127c06b356e9d79aaa6c68862dd7f97a8fd756e61", + "dist/2023-12-22/rust-std-beta-loongarch64-unknown-none.tar.xz": "663d531002d8be8e61fe4b9353a53b3a44056056b18bbd76749762a40416f7fa", + "dist/2023-12-22/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "3a25dd389b4501e9fe76057b70cb120e1d1d3caacdce82abc834297c487e50ce", + "dist/2023-12-22/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "6be12fd4e79600805cd6d04a5bd1d236dd7f12832d4407d3fcd72ce6bd84101f", + "dist/2023-12-22/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "6edc5d7fb15d71cbd097a09eb264b92f5b1e55f7ef0426c5c8399731f4ebb70d", + "dist/2023-12-22/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "beb17c9ca9e789ced8c4046135cde5b613a0b41c9b5aeefb3b7ee5d25701add6", + "dist/2023-12-22/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "6f13eb2dac5f4d59dbe44a4d862f94f763fce0bf4ea0f128c0006c04b922f294", + "dist/2023-12-22/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "75e629ca2f90c7e8a78fc16d13cab337816feba3e30564e26b3d38f13b7dffd0", + "dist/2023-12-22/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "e2ffac9803e2c604c56649096e734cff0a53632883c05cb9f1fd79f6ce420162", + "dist/2023-12-22/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "85e0193a7bfa284ac4dae84f4079605ba5c2f7c7c2e4f57ac74721aff44d05b8", + "dist/2023-12-22/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "41c57fa6eafdc2bc4389da8257b57e48af4250377b02760d06ebc38c83086534", + "dist/2023-12-22/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "02d46a445f52d078982866ee9430f8020e15d82f58d8f1edfedcd2f0ade51f36", + "dist/2023-12-22/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "6fdfd4e5ce8dc13cbce7cfb1543dafb54e80ffee0ed40935c3734787519a9673", + "dist/2023-12-22/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "5a645c8703ba10256605770ffdbb8abbef62746171f19edbbc069d02be501529", + "dist/2023-12-22/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz": "0cdefa18bc524ef66ddabf83fa2efceced02ad1a5271c9d95f91ec01178055e7", + "dist/2023-12-22/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz": "388dc6fba431953f581388d95cd860224e2d1203811ec86e66aca391650ce053", + "dist/2023-12-22/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "b3f756e69c0c1f257869cfa6ef239368a512c81b59c18a69851b2e5a73ec484d", + "dist/2023-12-22/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "61d020bea165d8abc361335e393c2c3bb1e59b6fdb0f6f65326392ec7dc3ea35", + "dist/2023-12-22/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "94e83a4ba2d141e9fc0d824a6f5e077796fd53b7b32578a1bf6e63cda1f9ee4d", + "dist/2023-12-22/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "9679bfb1664e6d14882e68940fe8960773f56f4867904a3259189f9eb96952ca", + "dist/2023-12-22/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "807b24b0568e83cc807e29ae6062a766f72ef48e12f9f257d78f6db4b9ee5621", + "dist/2023-12-22/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "d3898d851c5f728a9894e7755d0b6ff06133823b1773e5c80b29155f6e1152a6", + "dist/2023-12-22/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "9ecdd32e65c85130f8a1c82c8fd9d613a4c59b1e4fafd01771089a052d4a481c", + "dist/2023-12-22/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "a6b5ef2065cd5cef17e48791dae08090b755c00caca4efc1aa5eac9c2783e92e", + "dist/2023-12-22/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "df756fb3868a3ed347a92df37fc4aac696560d645696d5d86a15d84bde257546", + "dist/2023-12-22/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "777dac6ecbefe1e266c7bfd04644f428ae25318e80137a36d404009442ea208e", + "dist/2023-12-22/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "6802baa472bbf3f766346f24cf7b001cf87ea7f974bd1e1abdcc56b4c2b39bdd", + "dist/2023-12-22/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "5db8e7c4904c55a5d362669375bf72482e27042b7a156bd8b9d1c322b2bf521a", + "dist/2023-12-22/rust-std-beta-sparcv9-sun-solaris.tar.gz": "0ddd12279d34cc6190e0b1e163cee51d94be809fefa4adf801fea0f217a3519a", + "dist/2023-12-22/rust-std-beta-sparcv9-sun-solaris.tar.xz": "96ed998c6f254c9a5fe560474480db553cd7428cca65ba9a7732136bce191e48", + "dist/2023-12-22/rust-std-beta-thumbv6m-none-eabi.tar.gz": "aa36baeedb2b567f75a0fa550f2ebb507f135d4fe784343a576216237a87d643", + "dist/2023-12-22/rust-std-beta-thumbv6m-none-eabi.tar.xz": "0792a2de23b8c8e552565bcf691ca604760d5201ae247ec14122df11d3819f30", + "dist/2023-12-22/rust-std-beta-thumbv7em-none-eabi.tar.gz": "93a045ef6b38b1de7347880d299dcaf6f721af301fc811e47388b0b94c6290a6", + "dist/2023-12-22/rust-std-beta-thumbv7em-none-eabi.tar.xz": "c6f13b394ad21bd6058fae6845543d5f265e8124fd43ce16885800c4bd62a370", + "dist/2023-12-22/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "8ee5dc194cfd20626671d6b7924b68246d4cc820ca669d8fa9778086b043c3dc", + "dist/2023-12-22/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "f702b3ece0c74a4391e4ce954456babba8d170a1ffff438222a9bfd22df139a3", + "dist/2023-12-22/rust-std-beta-thumbv7m-none-eabi.tar.gz": "3cd3bc99d559a56ac8795c3602c59652877bac85e0a847c981c9ec2b1a86039b", + "dist/2023-12-22/rust-std-beta-thumbv7m-none-eabi.tar.xz": "0d8132f6922844c017fa0c0c3ec463e4a55e3fed7603fb2e8374ecf5c1405e52", + "dist/2023-12-22/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "ab1bc71bd1b00c0d38a3a0a3be1e5fc5a494219d2d37181da53b042b3b896c67", + "dist/2023-12-22/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "5cd28af392967e42e43f51233637ff690a524d840c50a328d5d52c594977b316", + "dist/2023-12-22/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "647b9db01306e225ee1867e194531028215a9fdb02b3f8713c07c39dd41d0c85", + "dist/2023-12-22/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "9a6ee652c9e15708f2aab76a20918f414875a8a52323a49d727b58aacc22d1f0", + "dist/2023-12-22/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "c16e452e889c9d56d417c871ac4f9290275df11563d458e1abc52e4ac3db0414", + "dist/2023-12-22/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "23a74836c303dc91e6ed9fd2078e130184ac19ac230946bd95e59c53666534bf", + "dist/2023-12-22/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "c8d01ed9cfe9938ed078e3f14ef9f4fa5367534ebe115f243fee8095ef3c174f", + "dist/2023-12-22/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "a24e99a9d45b19db342d5c5f903ad90a27be9c996278b76823121fd09d5a298c", + "dist/2023-12-22/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "e417661f5c42593e75b09b4a3531965e46f5dbd631809d6364e59d47a894b1c3", + "dist/2023-12-22/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "081ec9d8504af85ce93bc60ae5f3eaad8bd06864b084a97911e126564720b3f7", + "dist/2023-12-22/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "1df5182c5103454eb69f05b3e6c9aefe1374e43659f3e4cf68f0ac07052670eb", + "dist/2023-12-22/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "863278bd1a5281e6b04232e35df48a1dac7e909d3b51922cb328304cb6db9af2", + "dist/2023-12-22/rust-std-beta-wasm32-unknown-unknown.tar.gz": "6d80b9f8875f677a8e472c431d6df15babba2a9af62622da5a073ca9da467f69", + "dist/2023-12-22/rust-std-beta-wasm32-unknown-unknown.tar.xz": "cc9bf2bd9db87859e17ffd0b9a3ffb8c073e521fc035b75639a7e77fd04a210b", + "dist/2023-12-22/rust-std-beta-wasm32-wasi-preview1-threads.tar.gz": "7b2db2cb1fb7b35cecee218780fdc223464522bf4e5ac0e3c3342396bea77755", + "dist/2023-12-22/rust-std-beta-wasm32-wasi-preview1-threads.tar.xz": "ed893747e7165c97b2a2abfe4793493056cda613040eb5783ba0c4a57560f42c", + "dist/2023-12-22/rust-std-beta-wasm32-wasi.tar.gz": "cfd98053e598d830055a35702de43866b6c94b48a36c63c1683a302482bc4cc4", + "dist/2023-12-22/rust-std-beta-wasm32-wasi.tar.xz": "f57bc02b197d8f4c0d119f4ecaed6c405cc85bac7d00a55f2dc39e97ebc8411b", + "dist/2023-12-22/rust-std-beta-x86_64-apple-darwin.tar.gz": "70405814aefa163d60eabc777b882233797d075ef5a3052285a6aa4acf7c9c0a", + "dist/2023-12-22/rust-std-beta-x86_64-apple-darwin.tar.xz": "c26043ff5bb98223083aa58f659f3ef069f5cc97e5f3c1a62664197e3d8bae66", + "dist/2023-12-22/rust-std-beta-x86_64-apple-ios.tar.gz": "37a2b083652163adfd848872c7b42570ad6fb365ec679a1c89a8248c517021a4", + "dist/2023-12-22/rust-std-beta-x86_64-apple-ios.tar.xz": "cbba44d048a5c48dd4162dced5414eca2416047f2387708e46a2045553a45fa4", + "dist/2023-12-22/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "17e93708f7c0b4328d24db2ad2a82c3001c1bc03def829b7e182e5407fe74b82", + "dist/2023-12-22/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "761b39d8ab6b9061c0afd4fa2faaa88c7cda6322d615e57863b51a5a2826d70e", + "dist/2023-12-22/rust-std-beta-x86_64-linux-android.tar.gz": "f45d09e9a6c383c6cf9cff99d0046639d26636be78e194354e951fa99388e479", + "dist/2023-12-22/rust-std-beta-x86_64-linux-android.tar.xz": "fe323b71cfbb300f881d05879d03491aca507a644b261c16f148690dbb20a01e", + "dist/2023-12-22/rust-std-beta-x86_64-pc-solaris.tar.gz": "0dce2b6572bde41461086c6394121de7b97329f8192562684954542baef1ff05", + "dist/2023-12-22/rust-std-beta-x86_64-pc-solaris.tar.xz": "164fa2c995df0d6446c218e037025de1b225d92a51155b5b54328f67493e8202", + "dist/2023-12-22/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "848e55f4583bd589ae457d37b8d7367adafc24b87c35a08065114b3acdd731f9", + "dist/2023-12-22/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "c900770454c026b80f9b80bb745a84381f91492d552fcc7ba013e5fd46b2a63d", + "dist/2023-12-22/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "577f8db6e8654e9f3d97c83bbfa2eaa89fb0fe8c9362b976b9796297d189b6a8", + "dist/2023-12-22/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "5d2523bb1b31b4b43c527b8307ac8e00ad7e957fa652fe0628cb8e6796404d20", + "dist/2023-12-22/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "5a185ac2058969ed6aedbd864cf7037fe999eacfb9e11eb21f89696d6341741c", + "dist/2023-12-22/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "7f6e73e0cc5fae9b9e9142427decf8c4d48289033412d452a40c1a345f4311a8", + "dist/2023-12-22/rust-std-beta-x86_64-unknown-fuchsia.tar.gz": "c1974528eeea3346e070192f3729fbcc4fc9d6bbdb0c0b9ba73763758a695124", + "dist/2023-12-22/rust-std-beta-x86_64-unknown-fuchsia.tar.xz": "b4da6ab7e3bef63c2f381f7506ff0f65f302e0ed14d4f78016968b0cff3a5f5f", + "dist/2023-12-22/rust-std-beta-x86_64-unknown-illumos.tar.gz": "3f50aa342f03ad5235112560fe0f3c64f5139d09291e3ab6859d8169ff43d631", + "dist/2023-12-22/rust-std-beta-x86_64-unknown-illumos.tar.xz": "799eeb21df5ff213c8ec1f6250497665924b865b34d9c1a5f914eed48255278c", + "dist/2023-12-22/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "ac88a7247dec36da73d30cb58c067cd1bd6c5bc70e5820d031963fced0907c28", + "dist/2023-12-22/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "3de39c55f71a295ff38bce9843965309a40dbfe1c888f13dbde3935d26ebdfc0", + "dist/2023-12-22/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "eeae5e12254e54c87ed818e8449c2489717d1c3c25858c6e8a1a7502e57172e0", + "dist/2023-12-22/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "0d54e6882ffce573f70954d98e1f0c9f0758c5d6262e546ed95c055798d26bef", + "dist/2023-12-22/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "da056f4b1d8544382b90cae7061be549b2e06e3e880feb9d788200c022ab297c", + "dist/2023-12-22/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "f340687b51519830a1e566c84c0114581c817ac32e80f90b8baf0fbe960fdd5d", + "dist/2023-12-22/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "6ea1fedb7db6f51b79164ad39246dc2c86f743346feb760f4835c870be3931b2", + "dist/2023-12-22/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "7fe78fc5dfcb2d85b521dba2c9640233615fab04a8a1b8b27a2e0efabc5b5b60", + "dist/2023-12-22/rust-std-beta-x86_64-unknown-none.tar.gz": "8eb08022fd4b78b50784ab9671a81b69c899ff2e73d9ae08b6ea44ed018b2c8a", + "dist/2023-12-22/rust-std-beta-x86_64-unknown-none.tar.xz": "6ab096ba0bad97de603be50a05e16a33bffbaf4a97853d9f838721075b18aab8", + "dist/2023-12-22/rust-std-beta-x86_64-unknown-redox.tar.gz": "84632635271947ff93b1afdd35779e7c307182d964e3b2aff60e57c0ab02a9eb", + "dist/2023-12-22/rust-std-beta-x86_64-unknown-redox.tar.xz": "b21150ef965377a699410a0350395e0daf57e3ab8a3d90654482b17960dfd26b", + "dist/2023-12-22/rust-std-beta-x86_64-unknown-uefi.tar.gz": "7a703ac3b26a1ec21a64f6517f03938e458db5d46977f02f9359febe7e3e4a79", + "dist/2023-12-22/rust-std-beta-x86_64-unknown-uefi.tar.xz": "83607ae59dddf457d655a2e60ad6d7b500a144fec4d41a7f684555204754e2d2", + "dist/2023-12-22/rustc-beta-aarch64-apple-darwin.tar.gz": "4988d34a6c048ee278f0d675e05260a0ab7f635c09c8ac6964ea97dcd244b9a7", + "dist/2023-12-22/rustc-beta-aarch64-apple-darwin.tar.xz": "a5a218eea6a3edf9b8af70046525fa6259ebf391d6e91f0630f6ae441a227a82", + "dist/2023-12-22/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "0980f8dfdc522146433cab04f2b83378b0c5bdb632cd02e280469ddff02e8bbf", + "dist/2023-12-22/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "25cf2c04a79313040860831dcce67a123ee362e09bb185a16af171163ec8b087", + "dist/2023-12-22/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "e21656abc9b9111baf5fdf9aebbf29b4ac8123c163dfb979b5f047c530020f29", + "dist/2023-12-22/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "3087de6766ffa175dbf7c53153b24cbc29db1fccc06170fd70bd3dc3a97bae62", + "dist/2023-12-22/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "e2464b82f2e1c4450d4f9f6fca8c5d2315e6227651d7485cd487d39fbe7f940c", + "dist/2023-12-22/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "9d4909db94be068ef943eba3709195a028e3928198a87f38e72a6fe013e592db", + "dist/2023-12-22/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "9217ecb54faf8c2964476c3c7a9ec6955b276c4c5b89e5ff13d76fe4863ba8ef", + "dist/2023-12-22/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "fad7556560de459c4cbb59071a35746ee520ca15b5972e926039d46847a47888", + "dist/2023-12-22/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "69d94023fd5d8a48873ecde6892ee1be354fb56a91c9bc16b32d7b8bf090ad07", + "dist/2023-12-22/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "14ab98c13452b8b7e5ba8853b957355487c61f0a89d385c2ec8d16d8fec382aa", + "dist/2023-12-22/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "85190846421ade8edb5da369977598641bfac215754bdbdceccb181adf49d2b4", + "dist/2023-12-22/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "5b0de94607e7e1192463dd1c8615cf035040cf1a51ccf4d08459f659e14aebb4", + "dist/2023-12-22/rustc-beta-i686-pc-windows-gnu.tar.gz": "dfb48dd8d18099b63eab2e0f6e01dd520e6d137725596af611d68092f7d2228b", + "dist/2023-12-22/rustc-beta-i686-pc-windows-gnu.tar.xz": "f9bdb3dac14ded817c6f406767ef140838cedd74b9b2b6daed6419cf096245da", + "dist/2023-12-22/rustc-beta-i686-pc-windows-msvc.tar.gz": "a01af2a20955790992eb248a290161184429d43c8ddd65d8fd18dbb6499edd6f", + "dist/2023-12-22/rustc-beta-i686-pc-windows-msvc.tar.xz": "334b999f3e7c6c8deed7807e398338393f32c641989bd61c631a79a3a7441d67", + "dist/2023-12-22/rustc-beta-i686-unknown-linux-gnu.tar.gz": "334126bcfc14e8ffa5df43c4265b844db5a2b72458f5b3328f6863ea59580b12", + "dist/2023-12-22/rustc-beta-i686-unknown-linux-gnu.tar.xz": "aefe562ff063ab5eea83fdb58577e6ffbbf9cdf111e5390ee29640e5169c2c7c", + "dist/2023-12-22/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz": "1a9eea2e8fa598c438de05d33d0af4f7b648fc50ff25013b3926c6125dc75542", + "dist/2023-12-22/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz": "1f0d707a8d96071b1154ff1ffca518a9573d7c1d95835bd35bc3660a8a4d6cb8", + "dist/2023-12-22/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "6cf83e99462198dfd6fd4b7d5dc4ccffbbfc433d5e3b082028420ad7e2da6144", + "dist/2023-12-22/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "295e22e887c9b2d686628fc927d6560e0f71f2330517242d36d1d98159d43a6d", + "dist/2023-12-22/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "3b970b0cf7243e766a773c9f30557d8d20da668467b85c5cc60fd2f7e927cb09", + "dist/2023-12-22/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "dd4470357d4351081c9c1526c6a4c66642b11c88f8ac194ae7f0414593b2e561", + "dist/2023-12-22/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "7684ac7d4a96678d599bed67a11338531f09b500769d94b2b70cf1b1854a0e33", + "dist/2023-12-22/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "b9f98f6003605d179d298ca1080448784601f9648817e5c84371e54eaafcf36f", + "dist/2023-12-22/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "376b86e4cb259c5c85286203c00405570a77346441037e175c631b2753f4f421", + "dist/2023-12-22/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "d4d1b511f2ce2dd2dbbcdde760879b0ce87ac1c191f73d9b264403c328d3c505", + "dist/2023-12-22/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "b46bd2d835f98a293f259d90659334bd289cfff34d4fac544be2add0b4072014", + "dist/2023-12-22/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "6c3e19a3b0dd8deef825f9c6ecba405df6b8a390f6366991c1947f09401f7192", + "dist/2023-12-22/rustc-beta-x86_64-apple-darwin.tar.gz": "5c735a5d0ae69383db88bbc0d7ea5a6f2300c82ce81d1a4b4f987157ac03dd6f", + "dist/2023-12-22/rustc-beta-x86_64-apple-darwin.tar.xz": "5f483a58253a0d6fa58503bd5bf58f8a79c32e49228bb4645a7931c61465d27e", + "dist/2023-12-22/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "ef3db1dbcb14174dc39670810c417b6395e092a92622d49d9bcf4074a02bd32c", + "dist/2023-12-22/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "d73c50be69cc0a817273c75ca86ba094509c9168bd445cfe81690bac48a613a7", + "dist/2023-12-22/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "4476c15df06fdfaf90a426a438cc10e5c0afb4e15ff4394d501cd8f8202f95a5", + "dist/2023-12-22/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "8066766e26df9171bb66e07001c1f3d279f84f48e90ac7cd80ef0439e6de29bb", + "dist/2023-12-22/rustc-beta-x86_64-unknown-freebsd.tar.gz": "7128054459be36bf501225ef22c105edf599ed4732829bd35c20d6831278c799", + "dist/2023-12-22/rustc-beta-x86_64-unknown-freebsd.tar.xz": "a4d6429df3ea63c4f58af3311f3cb986546932a73ae363a768ea6cb630a9b59c", + "dist/2023-12-22/rustc-beta-x86_64-unknown-illumos.tar.gz": "adbb9d176605339353b9c84f53da7301c262966a43e9c25fb5dc408591a5e30e", + "dist/2023-12-22/rustc-beta-x86_64-unknown-illumos.tar.xz": "69bacc4bdb3466862ab86a524516e88e1af3e6379a6bd5b38a5d872534d7584b", + "dist/2023-12-22/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "49b58d45a5eeed663619b6976ef5a97d1d69ee6d1426046f5cf352ce2730aa81", + "dist/2023-12-22/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "9896fc9d8a363a1684abc892f70f71047f43a27eca362911cc39474582a3df7f", + "dist/2023-12-22/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "f5e9ea5090e1a1f1478c1b6c9f4c2975955630717d00304105e7c2b4d30b5793", + "dist/2023-12-22/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "121f57a07ac943c6d48d4519d863e873501edb57d04d8e2842c847510dff73e1", + "dist/2023-12-22/rustc-beta-x86_64-unknown-netbsd.tar.gz": "0ba119cb9e004e008daf53d6f2687ac48b5cadcea81c69f8b7a0f967be0939ae", + "dist/2023-12-22/rustc-beta-x86_64-unknown-netbsd.tar.xz": "81b8265afce99ba1fd7db811611da0f7296b066c2db0f4e65bababaad3f04ea6", + "dist/2023-12-22/rustc-nightly-aarch64-apple-darwin.tar.gz": "101130c9df70b39a6eb8b63ce1c457d8060c961d4ab845f4edb7b02e1b68e5e2", + "dist/2023-12-22/rustc-nightly-aarch64-apple-darwin.tar.xz": "ac84e13cc222d4bfc6670b2bec5407c77792ebf82c51e812ceb3bc972a9cfe24", + "dist/2023-12-22/rustc-nightly-aarch64-pc-windows-msvc.tar.gz": "8ca4faf6ccf792534c95b8091786d8b2b79ba99bfcd2537e2cb7fd97a3fc46ba", + "dist/2023-12-22/rustc-nightly-aarch64-pc-windows-msvc.tar.xz": "97db2f021e7aacdac1c81ab72264eede6cb72cd83f1c317ae84a3ff39b05584e", + "dist/2023-12-22/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz": "c274e2470c8cc801495f7a656a10250024173d5927b7ffa2e9251e0b776da5f4", + "dist/2023-12-22/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz": "024917a1f37a2db0bc8519dbcdecde7321c5d460886b76817791ea484595c44e", + "dist/2023-12-22/rustc-nightly-aarch64-unknown-linux-musl.tar.gz": "bcd861c8f6c7f7355f7d6196c405061e90a2907adbca52400b8dcea7bc9b42f1", + "dist/2023-12-22/rustc-nightly-aarch64-unknown-linux-musl.tar.xz": "19c52eecdf2dd4fb0b6a5c240c440c6d47148e7264d7efaa77ac484a8429802b", + "dist/2023-12-22/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz": "38fe3274425db7e9142530be734b473fb5742ea10d05deec24168730d8e65d0f", + "dist/2023-12-22/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz": "1fe18e92829eb2b87264dee5631329804a7da8177cb15043fcac27c1913a0b89", + "dist/2023-12-22/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz": "41a723fbfbcc9c003b59fe17e0bef28d69ed89f165c42afcd00e3617a7da6915", + "dist/2023-12-22/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz": "7f834044d638e8e15d8900c38b8ec1fc6e4ef98efddf3ab7342b24e59525c6a0", + "dist/2023-12-22/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "814402e50600573b6fd79ba3a84fb8c441d71eb2f3eff0257565fd514830ab10", + "dist/2023-12-22/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "2f2650f7ad3d86dd63bd887f6e5e5e5051ffdeef672ee8dbc96c738acde79e21", + "dist/2023-12-22/rustc-nightly-i686-pc-windows-gnu.tar.gz": "6cded96f43ea2aeb2c15ae5e58521301110d6a2f8e8870ff2d6e5e1d8d5d13ff", + "dist/2023-12-22/rustc-nightly-i686-pc-windows-gnu.tar.xz": "2682f11a1375b1b93a9f7110f121340a4994f736c263d37037fb29a5b6df69a1", + "dist/2023-12-22/rustc-nightly-i686-pc-windows-msvc.tar.gz": "9322ff47c86859ba405d6584407b3ad514e6ee1b7a47525a0e20a918875defca", + "dist/2023-12-22/rustc-nightly-i686-pc-windows-msvc.tar.xz": "1dd7be7fd7e51ee9e8c053b2c7c222031aa436497e591ad87a5ee2f2289022f5", + "dist/2023-12-22/rustc-nightly-i686-unknown-linux-gnu.tar.gz": "35e96a4ff0436ed31bb62e06b8898e3048cf11d3ae85f1097741f6b6d2ac0304", + "dist/2023-12-22/rustc-nightly-i686-unknown-linux-gnu.tar.xz": "a8d4be1c79031e6ae2ebf594929cc4cbdd2e0655110ce2a9983e1adee1474b3a", + "dist/2023-12-22/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz": "7a2b50a5309770784a47662b5616026e735cb12ebd785c578c3a16965167ca3b", + "dist/2023-12-22/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz": "8cf64de71cd3566683e487832c3f4143f306d4fe9658fa1e16b794d3ee25552b", + "dist/2023-12-22/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz": "f1890a35bb23fdc85736e18a7230eb4ac68f1d1772a8b1defde1c6fc53b547db", + "dist/2023-12-22/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz": "5a1cbf44eec83fe1172cef13a38c2f23c2cc2753847ad9577b4cbbc0793ba96b", + "dist/2023-12-22/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz": "b5e7b7d42a233010142806953ba10820f45be90574c885d9218d41865310d606", + "dist/2023-12-22/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz": "073c15e2528c30fc51e7964649cd84fc54ce7d6e71f32c4bd5e25028cfe66f01", + "dist/2023-12-22/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "0a579f70e0e6752e5ee257fcc2c77a4986d608262089427f3ae38ad1ff1d8864", + "dist/2023-12-22/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "d9491f667829d36df5db42ad40e0ee6bd0f5d53d854d8648462c357fcc709ca1", + "dist/2023-12-22/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "01bc45a98dc4791b14498d58681a894e3646ea0588fbaf23465dad1034cf7dc4", + "dist/2023-12-22/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "4eca6ca78604697090e48c262aab864a14cdd15607272699cfb9f93b0fb3b9e7", + "dist/2023-12-22/rustc-nightly-s390x-unknown-linux-gnu.tar.gz": "c77f35e12eb4e664c3f59575401c20071e3489de8a80e47601321823d1c79b09", + "dist/2023-12-22/rustc-nightly-s390x-unknown-linux-gnu.tar.xz": "61f3c129cfabbc5e814ea0ebb183d6674dafa593f56c017262aa60d241041983", + "dist/2023-12-22/rustc-nightly-x86_64-apple-darwin.tar.gz": "2ef95843d229f3b5d5efe1d2cd1cf9a5d2a5500b9f8d00a6ba5eef55a8689643", + "dist/2023-12-22/rustc-nightly-x86_64-apple-darwin.tar.xz": "ee3ac1b167da164384d1e3ac8b6fbde9668b68705afa1a047a1049e90b5bf66d", + "dist/2023-12-22/rustc-nightly-x86_64-pc-windows-gnu.tar.gz": "a98e2f3976a5b64f802616c045861571c61eef332c7206e0bfb10fca580c6bf6", + "dist/2023-12-22/rustc-nightly-x86_64-pc-windows-gnu.tar.xz": "549caf445a9b4886c47bdf82628e365afe8cea59739a3b41308c828c4eb9e7e0", + "dist/2023-12-22/rustc-nightly-x86_64-pc-windows-msvc.tar.gz": "db9bb6ae1770056cd787162ab24e54bad0dc2c8bd2861c8c3ded642f9e963643", + "dist/2023-12-22/rustc-nightly-x86_64-pc-windows-msvc.tar.xz": "bc410fb240404e3c193e39667485919660d58b7a5774301f9d0cb21ff744eaa1", + "dist/2023-12-22/rustc-nightly-x86_64-unknown-freebsd.tar.gz": "e113660740b61a1e20d72813e7ef076b7a894f5db3576abae812f501eebec409", + "dist/2023-12-22/rustc-nightly-x86_64-unknown-freebsd.tar.xz": "a0bacdf5523cbc5b59f49fbf99eaa571609faa4aa8765a09f9f091ba3f4f5686", + "dist/2023-12-22/rustc-nightly-x86_64-unknown-illumos.tar.gz": "29f8ee90239986050d96d1fbce42f0ec104653a44c49d050d5965ebbf8e94ff0", + "dist/2023-12-22/rustc-nightly-x86_64-unknown-illumos.tar.xz": "c4c04dc8d91f53db3420114a6020c76771b6dddf43f322ec0575c69a6bba7be8", + "dist/2023-12-22/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz": "f40e5ba829e2e731e44fa0452433cca7ca0f41d717f45809c32804d172ee3e7f", + "dist/2023-12-22/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz": "5ca6206e9c4c7274f988026dae50774cf0b197b016d81adf15ca29816f9177fc", + "dist/2023-12-22/rustc-nightly-x86_64-unknown-linux-musl.tar.gz": "40c913469dbe202d27fc4f3f9f8072c415d2d788d62773de486f0a429d17ac21", + "dist/2023-12-22/rustc-nightly-x86_64-unknown-linux-musl.tar.xz": "bde66e4076b615d14e3e799604c8904d4506854e03cf5ac2be39a5839721f1a1", + "dist/2023-12-22/rustc-nightly-x86_64-unknown-netbsd.tar.gz": "5538e8852c23f7070af754e1b19b7c685857f57cf33ed9ec9263a92bf57a14f2", + "dist/2023-12-22/rustc-nightly-x86_64-unknown-netbsd.tar.xz": "2d6558de20de87ce02de647115fee7bcce5f017baf2dc4593a1c91ae53281813", + "dist/2023-12-22/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "3d5878aac23fb995cb29aeaf2579b30ce96d5f3571f53e21e20094d4cad69800", + "dist/2023-12-22/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "80866c0ab8848d31a250c0904222ef0dd19ef45fd1f1a48ff381c914ef6c1ab6", + "dist/2023-12-22/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "4082f5613caab9091d4134dee83f5cfbe401d59a2a1b2000f28c7094584f08dc", + "dist/2023-12-22/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "94230b1d3582e83967306da3f869970d190fae1c22ce61fd5708f8591165d9c7", + "dist/2023-12-22/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "7d59a37a6fbf86c16376f593a54adcbbdf214aa8d49561fd7337d27f437e49dd", + "dist/2023-12-22/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "6c6be9be98fe01756c077cd3f6ef23104e681476e0a4de006223273f3f9a1fd3", + "dist/2023-12-22/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "706b95856289e67c29999ffa4e3afce266c017da8fc66db95695571ae4560ecc", + "dist/2023-12-22/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "9f768f3c40aa3f9d130c4725eff036e1503b372161f136878f4877db44e3600d", + "dist/2023-12-22/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "6e276261f45d28a2110d3de8ae3de4888d041c831d63960bc242e0b0b7765dd5", + "dist/2023-12-22/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "e9b4bfb081445a4506f10249c7441f2d0424778f3ac0fbf5b5ac3b87ba9ef66d", + "dist/2023-12-22/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "f1aec801b69d4b67a58ae93741ffa018d0a49943e593592139abb6b217561366", + "dist/2023-12-22/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "f23b01ec072adf8c29943846ff90f2a1ced0619dcf9c3d517f4cfad64d726e02", + "dist/2023-12-22/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "b61d903932f63625e4163f9a0b7e83606bfdfda4706e68d9387af62f611a32bc", + "dist/2023-12-22/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "21bbc61820a28141db13095dc778524dd4ba1981d6c66caee45b0b72f7267016", + "dist/2023-12-22/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "bf8307795424917a3975b1cf4b0b490cf80a17154d66df2a8d869d1a3291ca5e", + "dist/2023-12-22/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "b651f28f2dabc67abaf2ee7e17cac5508f400bab82f8267ef9ae2ce2399f5c5f", + "dist/2023-12-22/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "deacde8dd4f34e24d981a585061922708af11d4638733eb49dbc1087ffd901ea", + "dist/2023-12-22/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "cefc12a2fa8b66dd66265d159b3ee16cfc87a8c183d7a158e4e610fd747cecb7", + "dist/2023-12-22/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "4996bcacbf363fd93440ff18eaeb09081d1e9e510ddcebc5f84c2a3292d5d0fe", + "dist/2023-12-22/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "dd6b37586054ac9ab7714f0712e1cd833df33820fc661fa3ffa52cbcaa31073b", + "dist/2023-12-22/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz": "2fcfbc0448df994daa9a625bfc75e69054105a6c120beefa84c3843ab36dc4d7", + "dist/2023-12-22/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz": "94282e425b30fff90c9429e1f0d2aa5cc69094a147c8dd4521b30fa98eade494", + "dist/2023-12-22/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "25445ecbc332fd305e81075c18c27efdf2027fdb2d263f921eb716cc3ea60609", + "dist/2023-12-22/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "9a55fa07a1a9c3b0c31b00d9b33b0ff727046b4f322e6297ffa290e7741de015", + "dist/2023-12-22/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "01b05f33dbfd00aa3ae500db2204f08e5908a4833c3a26f0473bed9605003bb8", + "dist/2023-12-22/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "946bad6ff6d59ee175d7defcd1567b2aaf5c197bbca8985b04b91eb58f3e6277", + "dist/2023-12-22/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "bc2df359ed8ac189459139a0bcd3556484588bb053a4c2a0e1f7c8fedf39849f", + "dist/2023-12-22/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "a870d941baff83185c43bade890a8c87bfb16e0549fbc74cacfec561740a72c7", + "dist/2023-12-22/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "3fdd608ac91db883b2829f38bfbbb332ac327ab070570384d182e47f875bbecb", + "dist/2023-12-22/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "0a503de10365cc8eea4405e2db265e95d0d6a52556c95e3ca8e06735551ca0c6", + "dist/2023-12-22/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "82e85800015ada8c40c613eef01a4120feb60a35e069ace15d018dcd6603554b", + "dist/2023-12-22/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "21de46c078d31ac953cb41271b020817ef9c3cc55cde7b6b280f0425d8fc7400", + "dist/2023-12-22/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "5886fcf2485728376b7fe7c6a2cf9331f4bb0cab204efe5458ab2ef816e48b5c", + "dist/2023-12-22/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "6c775b5604ce3b3680d9cb6c074c97708d6804d40d44ab4d2abcaa8fd8fbc509", + "dist/2023-12-22/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "51bc618c6c7fa1086032655b6cf7c54b30c12ddf28949840e7695c0e65ff9f30", + "dist/2023-12-22/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "911b8becd12efbb1a46edaf55a383ab8c193e077aa08d1bec8c38a0168557dc2", + "dist/2023-12-22/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "27b84d5cfb60f11b03e26c882f20aa1e58fbba568cd6fc32f0970ab91cc9ed44", + "dist/2023-12-22/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "21f62ffdfd1497e5bd32cb43a9fd3c39672c429ef878e35c2019e167444afecd", + "dist/2023-12-22/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "1338e6d90b781578326816eda5b698ab38efa733387e1df84bb56c3ba5c9fdb4", + "dist/2023-12-22/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "9ce18c0e954100fedef63baceeac4a01fa0b0f810dd5175e5fe61070151c8161", + "dist/2023-12-22/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "8493b82ddec3ea06c8a1b9bb8357c47164ca85856ed538c96678cbaba3361afe", + "dist/2023-12-22/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "cf00b45f38ed847039f7c031e7c1a0a62cf7f00fad5acc05d47edb7e28a0e546", + "dist/2023-12-22/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "96480091ef8533959ba49e01922569a202c8fa2de174be553fab8478cb5c455c", + "dist/2023-12-22/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "c237e0c157dc09ef2c47583f34253ee92db92ead9f77fd8701ddee998acc0aee", + "dist/2023-12-22/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "73b731dbb70e872550e584fc4d3c67b6cbaa2d9a9a97b2ce11bcf6ab3ea5c5fa", + "dist/2023-12-22/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "141fe48890292de4d39547787f4ff44f672d3a5de35ed775cb80d7c3684bec73", + "dist/2023-12-22/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "52b2bab5830100dc4d4fc53ffcae560d7801382dcb4af19d2554e2551312fd0c", + "dist/2023-12-22/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "2071421241ed9e5e00fd5f877863a3a145616a8585db472b35ea902affaee4ee" } } diff --git a/src/tools/cargo b/src/tools/cargo -Subproject 1a2666ddd14cf0a255d4ddb61c63531c259a7b3 +Subproject 363a2d11320faf531f6aacd1ea067c6bc08343b diff --git a/src/tools/clippy/clippy_lints/src/async_yields_async.rs b/src/tools/clippy/clippy_lints/src/async_yields_async.rs index 3e5a01c45df..28e6614f03f 100644 --- a/src/tools/clippy/clippy_lints/src/async_yields_async.rs +++ b/src/tools/clippy/clippy_lints/src/async_yields_async.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::source::snippet; use clippy_utils::ty::implements_trait; use rustc_errors::Applicability; -use rustc_hir::{Body, BodyId, CoroutineKind, CoroutineSource, ExprKind, QPath}; +use rustc_hir::{Body, BodyId, CoroutineKind, CoroutineSource, CoroutineDesugaring, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; @@ -45,10 +45,9 @@ declare_lint_pass!(AsyncYieldsAsync => [ASYNC_YIELDS_ASYNC]); impl<'tcx> LateLintPass<'tcx> for AsyncYieldsAsync { fn check_body(&mut self, cx: &LateContext<'tcx>, body: &'tcx Body<'_>) { - use CoroutineSource::{Block, Closure}; // For functions, with explicitly defined types, don't warn. // XXXkhuey maybe we should? - if let Some(CoroutineKind::Async(Block | Closure)) = body.coroutine_kind { + if let Some(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Block | CoroutineSource::Closure)) = body.coroutine_kind { if let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait() { let body_id = BodyId { hir_id: body.value.hir_id, diff --git a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs index 9894a163961..dff6e884fa1 100644 --- a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs +++ b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs @@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::{match_def_path, paths}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::DefId; -use rustc_hir::{Body, CoroutineKind, CoroutineSource}; +use rustc_hir::{Body, CoroutineKind, CoroutineDesugaring}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::mir::CoroutineLayout; use rustc_session::impl_lint_pass; @@ -194,8 +194,7 @@ impl LateLintPass<'_> for AwaitHolding { } fn check_body(&mut self, cx: &LateContext<'_>, body: &'_ Body<'_>) { - use CoroutineSource::{Block, Closure, Fn}; - if let Some(CoroutineKind::Async(Block | Closure | Fn)) = body.coroutine_kind { + if let Some(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) = body.coroutine_kind { let def_id = cx.tcx.hir().body_owner_def_id(body.id()); if let Some(coroutine_layout) = cx.tcx.mir_coroutine_witnesses(def_id) { self.check_interior_types(cx, coroutine_layout); diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs index eaaaea0be9f..8982ce5e196 100644 --- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs +++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs @@ -3,7 +3,7 @@ use clippy_utils::source::{position_before_rarrow, snippet_block, snippet_opt}; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; use rustc_hir::{ - Block, Body, Closure, CoroutineKind, CoroutineSource, Expr, ExprKind, FnDecl, FnRetTy, GenericArg, GenericBound, + Block, Body, Closure, CoroutineKind, CoroutineSource, CoroutineDesugaring, Expr, ExprKind, FnDecl, FnRetTy, GenericArg, GenericBound, ImplItem, Item, ItemKind, LifetimeName, Node, Term, TraitRef, Ty, TyKind, TypeBindingKind, }; use rustc_lint::{LateContext, LateLintPass}; @@ -178,7 +178,7 @@ fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) .. } = block_expr && let closure_body = cx.tcx.hir().body(body) - && closure_body.coroutine_kind == Some(CoroutineKind::Async(CoroutineSource::Block)) + && closure_body.coroutine_kind == Some(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Block)) { return Some(closure_body); } diff --git a/src/tools/clippy/clippy_lints/src/needless_continue.rs b/src/tools/clippy/clippy_lints/src/needless_continue.rs index 4b9ab50e4fd..ff72b5e69ef 100644 --- a/src/tools/clippy/clippy_lints/src/needless_continue.rs +++ b/src/tools/clippy/clippy_lints/src/needless_continue.rs @@ -220,7 +220,11 @@ where F: FnMut(&ast::Block, Option<&ast::Label>), { if let ast::ExprKind::While(_, loop_block, label) - | ast::ExprKind::ForLoop(_, _, loop_block, label) + | ast::ExprKind::ForLoop { + body: loop_block, + label, + .. + } | ast::ExprKind::Loop(loop_block, label, ..) = &expr.kind { func(loop_block, label.as_ref()); diff --git a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs index a4d3aaf0de9..350707d3a13 100644 --- a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs @@ -3,7 +3,7 @@ use clippy_utils::path_res; use clippy_utils::source::snippet; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{Block, Body, CoroutineKind, CoroutineSource, Expr, ExprKind, LangItem, MatchSource, QPath}; +use rustc_hir::{Block, Body, CoroutineKind, CoroutineSource, CoroutineDesugaring, Expr, ExprKind, LangItem, MatchSource, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; @@ -86,7 +86,7 @@ impl LateLintPass<'_> for NeedlessQuestionMark { } fn check_body(&mut self, cx: &LateContext<'_>, body: &'_ Body<'_>) { - if let Some(CoroutineKind::Async(CoroutineSource::Fn)) = body.coroutine_kind { + if let Some(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Fn)) = body.coroutine_kind { if let ExprKind::Block( Block { expr: diff --git a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs index 19d9d64b31e..4b3fe9c0bb5 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs @@ -5,7 +5,7 @@ use clippy_utils::peel_blocks; use clippy_utils::source::{snippet, walk_span_to_context}; use clippy_utils::visitors::for_each_expr; use rustc_errors::Applicability; -use rustc_hir::{Closure, CoroutineKind, CoroutineSource, Expr, ExprKind, MatchSource}; +use rustc_hir::{Closure, CoroutineKind, CoroutineSource, CoroutineDesugaring, Expr, ExprKind, MatchSource}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::UpvarCapture; @@ -71,7 +71,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantAsyncBlock { fn desugar_async_block<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { if let ExprKind::Closure(Closure { body, def_id, .. }) = expr.kind && let body = cx.tcx.hir().body(*body) - && matches!(body.coroutine_kind, Some(CoroutineKind::Async(CoroutineSource::Block))) + && matches!(body.coroutine_kind, Some(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Block))) { cx.typeck_results() .closure_min_captures diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs index 8bac2e40e01..9312a9c89b7 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs @@ -5,7 +5,7 @@ use clippy_utils::sugg::Sugg; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::intravisit::{Visitor as HirVisitor, Visitor}; -use rustc_hir::{intravisit as hir_visit, CoroutineKind, CoroutineSource, Node}; +use rustc_hir::{intravisit as hir_visit, CoroutineKind, CoroutineSource, CoroutineDesugaring, Node}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_middle::lint::in_external_macro; @@ -67,7 +67,7 @@ fn is_async_closure(cx: &LateContext<'_>, body: &hir::Body<'_>) -> bool { if let hir::ExprKind::Closure(innermost_closure_generated_by_desugar) = body.value.kind && let desugared_inner_closure_body = cx.tcx.hir().body(innermost_closure_generated_by_desugar.body) // checks whether it is `async || whatever_expression` - && let Some(CoroutineKind::Async(CoroutineSource::Closure)) = desugared_inner_closure_body.coroutine_kind + && let Some(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Closure)) = desugared_inner_closure_body.coroutine_kind { true } else { diff --git a/src/tools/clippy/clippy_lints/src/redundant_else.rs b/src/tools/clippy/clippy_lints/src/redundant_else.rs index 001686c84f8..fb434fb7450 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_else.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_else.rs @@ -111,7 +111,7 @@ impl<'ast> Visitor<'ast> for BreakVisitor { ExprKind::If(_, ref then, Some(ref els)) => self.check_block(then) && self.check_expr(els), ExprKind::If(_, _, None) // ignore loops for simplicity - | ExprKind::While(..) | ExprKind::ForLoop(..) | ExprKind::Loop(..) => false, + | ExprKind::While(..) | ExprKind::ForLoop { .. } | ExprKind::Loop(..) => false, _ => { walk_expr(self, expr); return; diff --git a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs index 8b9d9bade91..60e9d262e7e 100644 --- a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs +++ b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs @@ -554,7 +554,7 @@ fn ident_difference_expr_with_base_location( | (Closure(_), Closure(_)) | (Match(_, _), Match(_, _)) | (Loop(_, _, _), Loop(_, _, _)) - | (ForLoop(_, _, _, _), ForLoop(_, _, _, _)) + | (ForLoop { .. }, ForLoop { .. }) | (While(_, _, _), While(_, _, _)) | (If(_, _, _), If(_, _, _)) | (Let(_, _, _, _), Let(_, _, _, _)) diff --git a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs index 65600009c1d..77adcdd0e6b 100644 --- a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs +++ b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs @@ -293,7 +293,7 @@ fn extend_with_struct_pat( qself1: &Option<P<ast::QSelf>>, path1: &ast::Path, fps1: &mut [ast::PatField], - rest1: bool, + rest1: ast::PatFieldsRest, start: usize, alternatives: &mut ThinVec<P<Pat>>, ) -> bool { diff --git a/src/tools/clippy/clippy_lints/src/unused_async.rs b/src/tools/clippy/clippy_lints/src/unused_async.rs index 9c8c44c0a16..f71fe4e1e92 100644 --- a/src/tools/clippy/clippy_lints/src/unused_async.rs +++ b/src/tools/clippy/clippy_lints/src/unused_async.rs @@ -86,7 +86,13 @@ impl<'a, 'tcx> Visitor<'tcx> for AsyncFnVisitor<'a, 'tcx> { } fn visit_body(&mut self, b: &'tcx Body<'tcx>) { - let is_async_block = matches!(b.coroutine_kind, Some(rustc_hir::CoroutineKind::Async(_))); + let is_async_block = matches!( + b.coroutine_kind, + Some(rustc_hir::CoroutineKind::Desugared( + rustc_hir::CoroutineDesugaring::Async, + _ + )) + ); if is_async_block { self.async_depth += 1; diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index c271e498665..7fe76b946a4 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -169,9 +169,22 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool { (Let(lp, le, _, _), Let(rp, re, _, _)) => eq_pat(lp, rp) && eq_expr(le, re), (If(lc, lt, le), If(rc, rt, re)) => eq_expr(lc, rc) && eq_block(lt, rt) && eq_expr_opt(le, re), (While(lc, lt, ll), While(rc, rt, rl)) => eq_label(ll, rl) && eq_expr(lc, rc) && eq_block(lt, rt), - (ForLoop(lp, li, lt, ll), ForLoop(rp, ri, rt, rl)) => { - eq_label(ll, rl) && eq_pat(lp, rp) && eq_expr(li, ri) && eq_block(lt, rt) - }, + ( + ForLoop { + pat: lp, + iter: li, + body: lt, + label: ll, + kind: lk, + }, + ForLoop { + pat: rp, + iter: ri, + body: rt, + label: rl, + kind: rk, + }, + ) => eq_label(ll, rl) && eq_pat(lp, rp) && eq_expr(li, ri) && eq_block(lt, rt) && lk == rk, (Loop(lt, ll, _), Loop(rt, rl, _)) => eq_label(ll, rl) && eq_block(lt, rt), (Block(lb, ll), Block(rb, rl)) => eq_label(ll, rl) && eq_block(lb, rb), (TryBlock(l), TryBlock(r)) => eq_block(l, r), diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs index 9b2bc8df1f3..c86362c427c 100644 --- a/src/tools/clippy/clippy_utils/src/sugg.rs +++ b/src/tools/clippy/clippy_utils/src/sugg.rs @@ -197,7 +197,7 @@ impl<'a> Sugg<'a> { | ast::ExprKind::Continue(..) | ast::ExprKind::Yield(..) | ast::ExprKind::Field(..) - | ast::ExprKind::ForLoop(..) + | ast::ExprKind::ForLoop { .. } | ast::ExprKind::Index(..) | ast::ExprKind::InlineAsm(..) | ast::ExprKind::OffsetOf(..) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 5d53a4d28f2..ca80328f3ac 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2445,6 +2445,7 @@ impl<'test> TestCx<'test> { "-Copt-level=1", &zdump_arg, "-Zvalidate-mir", + "-Zlint-mir", "-Zdump-mir-exclude-pass-number", ]); if let Some(pass) = &self.props.mir_unit_test { diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index f67ac80c526..6af13147997 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -767453eb7ca188e991ac5568c17b984dd4893e77 +3166bbef9248fce2695899e21203f42a21046551 diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index a70a9d4602e..4c284ff81ee 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -3,7 +3,7 @@ use std::num::NonZeroU64; use log::trace; -use rustc_errors::DiagnosticMessage; +use rustc_errors::{DiagnosticBuilder, DiagnosticMessage, Level}; use rustc_span::{SpanData, Symbol, DUMMY_SP}; use rustc_target::abi::{Align, Size}; @@ -453,11 +453,13 @@ pub fn report_msg<'tcx>( ) { let span = stacktrace.first().map_or(DUMMY_SP, |fi| fi.span); let sess = machine.tcx.sess; - let mut err = match diag_level { - DiagLevel::Error => sess.struct_span_err(span, title).forget_guarantee(), - DiagLevel::Warning => sess.struct_span_warn(span, title), - DiagLevel::Note => sess.dcx().struct_span_note(span, title), + let level = match diag_level { + DiagLevel::Error => Level::Error { lint: false }, + DiagLevel::Warning => Level::Warning(None), + DiagLevel::Note => Level::Note, }; + let mut err = DiagnosticBuilder::<()>::new(sess.dcx(), level, title); + err.set_span(span); // Show main message. if span != DUMMY_SP { diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 1eb40ab826c..4e9febf0205 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -11,7 +11,6 @@ #![feature(round_ties_even)] #![feature(let_chains)] #![feature(lint_reasons)] -#![cfg_attr(bootstrap, feature(trait_upcasting))] // Configure clippy and other lints #![allow( clippy::collapsible_else_if, diff --git a/src/tools/rustfmt/src/closures.rs b/src/tools/rustfmt/src/closures.rs index f698f494ae5..5bf29441b54 100644 --- a/src/tools/rustfmt/src/closures.rs +++ b/src/tools/rustfmt/src/closures.rs @@ -448,7 +448,7 @@ fn is_block_closure_forced(context: &RewriteContext<'_>, expr: &ast::Expr) -> bo fn is_block_closure_forced_inner(expr: &ast::Expr, version: Version) -> bool { match expr.kind { - ast::ExprKind::If(..) | ast::ExprKind::While(..) | ast::ExprKind::ForLoop(..) => true, + ast::ExprKind::If(..) | ast::ExprKind::While(..) | ast::ExprKind::ForLoop { .. } => true, ast::ExprKind::Loop(..) if version == Version::Two => true, ast::ExprKind::AddrOf(_, _, ref expr) | ast::ExprKind::Try(ref expr) @@ -473,7 +473,7 @@ fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool { | ast::ExprKind::Block(..) | ast::ExprKind::While(..) | ast::ExprKind::Loop(..) - | ast::ExprKind::ForLoop(..) + | ast::ExprKind::ForLoop { .. } | ast::ExprKind::TryBlock(..) => false, _ => true, } diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index a68bd6694ba..7808f891336 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -3,7 +3,7 @@ use std::cmp::min; use itertools::Itertools; use rustc_ast::token::{Delimiter, Lit, LitKind}; -use rustc_ast::{ast, ptr, token}; +use rustc_ast::{ast, ptr, token, ForLoopKind}; use rustc_span::{BytePos, Span}; use crate::chains::rewrite_chain; @@ -134,7 +134,7 @@ pub(crate) fn format_expr( } ast::ExprKind::Let(ref pat, ref expr, _span, _) => rewrite_let(context, shape, pat, expr), ast::ExprKind::If(..) - | ast::ExprKind::ForLoop(..) + | ast::ExprKind::ForLoop { .. } | ast::ExprKind::Loop(..) | ast::ExprKind::While(..) => to_control_flow(expr, expr_type) .and_then(|control_flow| control_flow.rewrite(context, shape)), @@ -682,9 +682,15 @@ fn to_control_flow(expr: &ast::Expr, expr_type: ExprType) -> Option<ControlFlow< expr.span, )) } - ast::ExprKind::ForLoop(ref pat, ref cond, ref block, label) => { - Some(ControlFlow::new_for(pat, cond, block, label, expr.span)) - } + ast::ExprKind::ForLoop { + ref pat, + ref iter, + ref body, + label, + kind, + } => Some(ControlFlow::new_for( + pat, iter, body, label, expr.span, kind, + )), ast::ExprKind::Loop(ref block, label, _) => { Some(ControlFlow::new_loop(block, label, expr.span)) } @@ -771,6 +777,7 @@ impl<'a> ControlFlow<'a> { block: &'a ast::Block, label: Option<ast::Label>, span: Span, + kind: ForLoopKind, ) -> ControlFlow<'a> { ControlFlow { cond: Some(cond), @@ -778,7 +785,10 @@ impl<'a> ControlFlow<'a> { else_block: None, label, pat: Some(pat), - keyword: "for", + keyword: match kind { + ForLoopKind::For => "for", + ForLoopKind::ForAwait => "for await", + }, matcher: "", connector: " in", allow_single_line: false, @@ -1364,7 +1374,7 @@ pub(crate) fn can_be_overflowed_expr( || context.config.overflow_delimited_expr() } ast::ExprKind::If(..) - | ast::ExprKind::ForLoop(..) + | ast::ExprKind::ForLoop { .. } | ast::ExprKind::Loop(..) | ast::ExprKind::While(..) => { context.config.combine_control_expr() && context.use_block_indent() && args_len == 1 diff --git a/src/tools/rustfmt/src/matches.rs b/src/tools/rustfmt/src/matches.rs index ef509b56837..5a00984d4c0 100644 --- a/src/tools/rustfmt/src/matches.rs +++ b/src/tools/rustfmt/src/matches.rs @@ -591,7 +591,7 @@ fn can_flatten_block_around_this(body: &ast::Expr) -> bool { ast::ExprKind::If(..) => false, // We do not allow collapsing a block around expression with condition // to avoid it being cluttered with match arm. - ast::ExprKind::ForLoop(..) | ast::ExprKind::While(..) => false, + ast::ExprKind::ForLoop { .. } | ast::ExprKind::While(..) => false, ast::ExprKind::Loop(..) | ast::ExprKind::Match(..) | ast::ExprKind::Block(..) diff --git a/src/tools/rustfmt/src/overflow.rs b/src/tools/rustfmt/src/overflow.rs index d81bf24dbd1..f46583b1c89 100644 --- a/src/tools/rustfmt/src/overflow.rs +++ b/src/tools/rustfmt/src/overflow.rs @@ -409,7 +409,7 @@ impl<'a> Context<'a> { // When overflowing the expressions which consists of a control flow // expression, avoid condition to use multi line. ast::ExprKind::If(..) - | ast::ExprKind::ForLoop(..) + | ast::ExprKind::ForLoop { .. } | ast::ExprKind::Loop(..) | ast::ExprKind::While(..) | ast::ExprKind::Match(..) => { diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs index e8f7b422ada..8303c03e1eb 100644 --- a/src/tools/rustfmt/src/parse/session.rs +++ b/src/tools/rustfmt/src/parse/session.rs @@ -370,7 +370,7 @@ mod tests { fn build_diagnostic(level: DiagnosticLevel, span: Option<MultiSpan>) -> Diagnostic { let mut diag = Diagnostic::new(level, ""); - diag.message.clear(); + diag.messages.clear(); if let Some(span) = span { diag.span = span; } diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs index 8504999b8ff..0fa6edaa5d7 100644 --- a/src/tools/rustfmt/src/patterns.rs +++ b/src/tools/rustfmt/src/patterns.rs @@ -259,9 +259,15 @@ impl Rewrite for Pat { None, None, ), - PatKind::Struct(ref qself, ref path, ref fields, ellipsis) => { - rewrite_struct_pat(qself, path, fields, ellipsis, self.span, context, shape) - } + PatKind::Struct(ref qself, ref path, ref fields, rest) => rewrite_struct_pat( + qself, + path, + fields, + rest == ast::PatFieldsRest::Rest, + self.span, + context, + shape, + ), PatKind::MacCall(ref mac) => { rewrite_macro(mac, None, context, shape, MacroPosition::Pat) } diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index a5a4244903c..cd2582e66be 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -537,28 +537,19 @@ impl Rewrite for ast::Lifetime { impl Rewrite for ast::GenericBound { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> { match *self { - ast::GenericBound::Trait(ref poly_trait_ref, trait_bound_modifier) => { + ast::GenericBound::Trait(ref poly_trait_ref, modifiers) => { let snippet = context.snippet(self.span()); let has_paren = snippet.starts_with('(') && snippet.ends_with(')'); - let rewrite = match trait_bound_modifier { - ast::TraitBoundModifier::None => poly_trait_ref.rewrite(context, shape), - ast::TraitBoundModifier::Maybe => poly_trait_ref - .rewrite(context, shape.offset_left(1)?) - .map(|s| format!("?{}", s)), - ast::TraitBoundModifier::MaybeConst(_) => poly_trait_ref - .rewrite(context, shape.offset_left(7)?) - .map(|s| format!("~const {}", s)), - ast::TraitBoundModifier::MaybeConstMaybe => poly_trait_ref - .rewrite(context, shape.offset_left(8)?) - .map(|s| format!("~const ?{}", s)), - ast::TraitBoundModifier::Negative => poly_trait_ref - .rewrite(context, shape.offset_left(1)?) - .map(|s| format!("!{}", s)), - ast::TraitBoundModifier::MaybeConstNegative => poly_trait_ref - .rewrite(context, shape.offset_left(8)?) - .map(|s| format!("~const !{}", s)), - }; - rewrite.map(|s| if has_paren { format!("({})", s) } else { s }) + let mut constness = modifiers.constness.as_str().to_string(); + if !constness.is_empty() { + constness.push(' '); + } + let polarity = modifiers.polarity.as_str(); + let shape = shape.offset_left(constness.len() + polarity.len())?; + poly_trait_ref + .rewrite(context, shape) + .map(|s| format!("{constness}{polarity}{s}")) + .map(|s| if has_paren { format!("({})", s) } else { s }) } ast::GenericBound::Outlives(ref lifetime) => lifetime.rewrite(context, shape), } diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs index 7d7bbf11529..642b6603b1e 100644 --- a/src/tools/rustfmt/src/utils.rs +++ b/src/tools/rustfmt/src/utils.rs @@ -295,7 +295,7 @@ pub(crate) fn semicolon_for_stmt( ) -> bool { match stmt.kind { ast::StmtKind::Semi(ref expr) => match expr.kind { - ast::ExprKind::While(..) | ast::ExprKind::Loop(..) | ast::ExprKind::ForLoop(..) => { + ast::ExprKind::While(..) | ast::ExprKind::Loop(..) | ast::ExprKind::ForLoop { .. } => { false } ast::ExprKind::Break(..) | ast::ExprKind::Continue(..) | ast::ExprKind::Ret(..) => { @@ -476,7 +476,7 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr | ast::ExprKind::ConstBlock(..) | ast::ExprKind::Gen(..) | ast::ExprKind::Loop(..) - | ast::ExprKind::ForLoop(..) + | ast::ExprKind::ForLoop { .. } | ast::ExprKind::TryBlock(..) | ast::ExprKind::Match(..) => repr.contains('\n'), ast::ExprKind::Paren(ref expr) diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs index 3e67bac499b..094efa981d3 100644 --- a/src/tools/tidy/src/error_codes.rs +++ b/src/tools/tidy/src/error_codes.rs @@ -27,7 +27,7 @@ const ERROR_DOCS_PATH: &str = "compiler/rustc_error_codes/src/error_codes/"; const ERROR_TESTS_PATH: &str = "tests/ui/error-codes/"; // Error codes that (for some reason) can't have a doctest in their explanation. Error codes are still expected to provide a code example, even if untested. -const IGNORE_DOCTEST_CHECK: &[&str] = &["E0464", "E0570", "E0601", "E0602", "E0640", "E0717"]; +const IGNORE_DOCTEST_CHECK: &[&str] = &["E0464", "E0570", "E0601", "E0602", "E0717"]; // Error codes that don't yet have a UI test. This list will eventually be removed. const IGNORE_UI_TEST_CHECK: &[&str] = diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index cb40c6e3a38..8b0e80a94b0 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -494,7 +494,7 @@ pub fn check(path: &Path, bad: &mut bool) { let mut err = |_| { tidy_error!(bad, "{}: leading newline", file.display()); }; - suppressible_tidy_err!(err, skip_leading_newlines, "mising leading newline"); + suppressible_tidy_err!(err, skip_leading_newlines, "missing leading newline"); } let mut err = |msg: &str| { tidy_error!(bad, "{}: {}", file.display(), msg); diff --git a/tests/codegen/overaligned-constant.rs b/tests/codegen/overaligned-constant.rs index c94dfd85e7d..89e49738991 100644 --- a/tests/codegen/overaligned-constant.rs +++ b/tests/codegen/overaligned-constant.rs @@ -17,7 +17,7 @@ fn main() { // CHECK: [[full:%_.*]] = alloca %SmallStruct, align 8 // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[full]], ptr align 8 @0, i64 32, i1 false) // CHECK: %b.0 = load i32, ptr @0, align 4, - // CHECK: %b.1 = load i32, ptr getelementptr inbounds ({ i32, i32 }, ptr @0, i32 0, i32 1), align 4 + // CHECK: %b.1 = load i32, ptr getelementptr inbounds ({{.*}}), align 4 let mut s = S(1); s.0 = 3; diff --git a/tests/mir-opt/reference_prop.rs b/tests/mir-opt/reference_prop.rs index 1b9c8fe15c2..8adfbb4535b 100644 --- a/tests/mir-opt/reference_prop.rs +++ b/tests/mir-opt/reference_prop.rs @@ -1,3 +1,4 @@ +// compile-flags: -Zlint-mir=no // unit-test: ReferencePropagation // needs-unwind diff --git a/tests/rustdoc-json/traits/is_object_safe.rs b/tests/rustdoc-json/traits/is_object_safe.rs new file mode 100644 index 00000000000..131c5fc57a5 --- /dev/null +++ b/tests/rustdoc-json/traits/is_object_safe.rs @@ -0,0 +1,19 @@ +#![no_std] + +// @has "$.index[*][?(@.name=='FooUnsafe')]" +// @is "$.index[*][?(@.name=='FooUnsafe')].inner.trait.is_object_safe" false +pub trait FooUnsafe { + fn foo() -> Self; +} + +// @has "$.index[*][?(@.name=='BarUnsafe')]" +// @is "$.index[*][?(@.name=='BarUnsafe')].inner.trait.is_object_safe" false +pub trait BarUnsafe<T> { + fn foo(i: T); +} + +// @has "$.index[*][?(@.name=='FooSafe')]" +// @is "$.index[*][?(@.name=='FooSafe')].inner.trait.is_object_safe" true +pub trait FooSafe { + fn foo(&self); +} diff --git a/tests/rustdoc/trait-object-safe.rs b/tests/rustdoc/trait-object-safe.rs index 818843f7558..8b028ad2e13 100644 --- a/tests/rustdoc/trait-object-safe.rs +++ b/tests/rustdoc/trait-object-safe.rs @@ -22,6 +22,6 @@ pub trait Safe { } // @has 'foo/struct.Foo.html' -// @!has - '//*[@class="object-safety-info"]' '' -// @!has - '//*[@id="object-safety"]' '' +// @count - '//*[@class="object-safety-info"]' 0 +// @count - '//*[@id="object-safety"]' 0 pub struct Foo; diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.rs b/tests/ui-fulldeps/internal-lints/diagnostics.rs index 4b006151c64..ab42d3b8c1e 100644 --- a/tests/ui-fulldeps/internal-lints/diagnostics.rs +++ b/tests/ui-fulldeps/internal-lints/diagnostics.rs @@ -13,8 +13,8 @@ extern crate rustc_session; extern crate rustc_span; use rustc_errors::{ - AddToDiagnostic, DiagCtxt, Diagnostic, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, - IntoDiagnostic, SubdiagnosticMessage, + AddToDiagnostic, Diagnostic, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, DiagCtxt, + IntoDiagnostic, Level, SubdiagnosticMessage, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::Span; @@ -37,18 +37,18 @@ struct Note { pub struct UntranslatableInIntoDiagnostic; -impl<'a> IntoDiagnostic<'a, ErrorGuaranteed> for UntranslatableInIntoDiagnostic { - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - dcx.struct_err("untranslatable diagnostic") +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UntranslatableInIntoDiagnostic { + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { + DiagnosticBuilder::new(dcx, level, "untranslatable diagnostic") //~^ ERROR diagnostics should be created using translatable messages } } pub struct TranslatableInIntoDiagnostic; -impl<'a> IntoDiagnostic<'a, ErrorGuaranteed> for TranslatableInIntoDiagnostic { - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - dcx.struct_err(crate::fluent_generated::no_crate_example) +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for TranslatableInIntoDiagnostic { + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { + DiagnosticBuilder::new(dcx, level, crate::fluent_generated::no_crate_example) } } diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.stderr b/tests/ui-fulldeps/internal-lints/diagnostics.stderr index d18db3cbbd3..f70240ecf17 100644 --- a/tests/ui-fulldeps/internal-lints/diagnostics.stderr +++ b/tests/ui-fulldeps/internal-lints/diagnostics.stderr @@ -1,8 +1,8 @@ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:42:13 + --> $DIR/diagnostics.rs:42:9 | -LL | dcx.struct_err("untranslatable diagnostic") - | ^^^^^^^^^^ +LL | DiagnosticBuilder::new(dcx, level, "untranslatable diagnostic") + | ^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here --> $DIR/diagnostics.rs:6:9 diff --git a/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr b/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr index 866a53f57fc..2fceeb15ea9 100644 --- a/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr +++ b/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr @@ -33,7 +33,14 @@ error[E0223]: ambiguous associated type --> $DIR/issue-109071.rs:15:22 | LL | fn T() -> Option<Self::Item> {} - | ^^^^^^^^^^ help: use fully-qualified syntax: `<Windows<T> as IntoIterator>::Item` + | ^^^^^^^^^^ + | +help: use fully-qualified syntax + | +LL | fn T() -> Option<<Windows<T> as IntoAsyncIterator>::Item> {} + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | fn T() -> Option<<Windows<T> as IntoIterator>::Item> {} + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: aborting due to 4 previous errors diff --git a/tests/ui/async-await/feature-async-for-loop.rs b/tests/ui/async-await/feature-async-for-loop.rs new file mode 100644 index 00000000000..42247dd14b0 --- /dev/null +++ b/tests/ui/async-await/feature-async-for-loop.rs @@ -0,0 +1,23 @@ +// edition:2021 +// gate-test-async_for_loop + +#![feature(async_iter_from_iter, async_iterator)] + +fn f() { + let _ = async { + for await _i in core::async_iter::from_iter(0..3) { + //~^ ERROR `for await` loops are experimental + } + }; +} + +#[cfg(FALSE)] +fn g() { + let _ = async { + for await _i in core::async_iter::from_iter(0..3) { + //~^ ERROR `for await` loops are experimental + } + }; +} + +fn main() {} diff --git a/tests/ui/async-await/feature-async-for-loop.stderr b/tests/ui/async-await/feature-async-for-loop.stderr new file mode 100644 index 00000000000..38f75821772 --- /dev/null +++ b/tests/ui/async-await/feature-async-for-loop.stderr @@ -0,0 +1,21 @@ +error[E0658]: `for await` loops are experimental + --> $DIR/feature-async-for-loop.rs:8:13 + | +LL | for await _i in core::async_iter::from_iter(0..3) { + | ^^^^^ + | + = note: see issue #118898 <https://github.com/rust-lang/rust/issues/118898> for more information + = help: add `#![feature(async_for_loop)]` to the crate attributes to enable + +error[E0658]: `for await` loops are experimental + --> $DIR/feature-async-for-loop.rs:17:13 + | +LL | for await _i in core::async_iter::from_iter(0..3) { + | ^^^^^ + | + = note: see issue #118898 <https://github.com/rust-lang/rust/issues/118898> for more information + = help: add `#![feature(async_for_loop)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/async-await/for-await-2015.rs b/tests/ui/async-await/for-await-2015.rs new file mode 100644 index 00000000000..c1b7c016d1f --- /dev/null +++ b/tests/ui/async-await/for-await-2015.rs @@ -0,0 +1,10 @@ +// check-pass + +#![feature(async_for_loop)] + +// Make sure we don't break `for await` loops in the 2015 edition, where `await` was allowed as an +// identifier. + +fn main() { + for await in 0..3 {} +} diff --git a/tests/ui/async-await/for-await-consumes-iter.rs b/tests/ui/async-await/for-await-consumes-iter.rs new file mode 100644 index 00000000000..65bb9e88448 --- /dev/null +++ b/tests/ui/async-await/for-await-consumes-iter.rs @@ -0,0 +1,20 @@ +// edition: 2021 +#![feature(async_iterator, async_iter_from_iter, const_waker, async_for_loop, noop_waker)] + +use std::future::Future; + +// a test to make sure `for await` consumes the iterator + +async fn real_main() { + let iter = core::async_iter::from_iter(0..3); + let mut count = 0; + for await i in iter { + } + // make sure iter has been moved and we can't iterate over it again. + for await i in iter { + //~^ ERROR: use of moved value: `iter` + } +} + +fn main() { +} diff --git a/tests/ui/async-await/for-await-consumes-iter.stderr b/tests/ui/async-await/for-await-consumes-iter.stderr new file mode 100644 index 00000000000..a3e5bbcabf5 --- /dev/null +++ b/tests/ui/async-await/for-await-consumes-iter.stderr @@ -0,0 +1,22 @@ +error[E0382]: use of moved value: `iter` + --> $DIR/for-await-consumes-iter.rs:14:20 + | +LL | let iter = core::async_iter::from_iter(0..3); + | ---- move occurs because `iter` has type `FromIter<std::ops::Range<i32>>`, which does not implement the `Copy` trait +LL | let mut count = 0; +LL | for await i in iter { + | ---- `iter` moved due to this method call +... +LL | for await i in iter { + | ^^^^ value used here after move + | +note: `into_async_iter` takes ownership of the receiver `self`, which moves `iter` + --> $SRC_DIR/core/src/async_iter/async_iter.rs:LL:COL +help: you can `clone` the value and consume it, but this might not be your desired behavior + | +LL | for await i in iter.clone() { + | ++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/async-await/for-await-passthrough.rs b/tests/ui/async-await/for-await-passthrough.rs new file mode 100644 index 00000000000..7fa133aaedc --- /dev/null +++ b/tests/ui/async-await/for-await-passthrough.rs @@ -0,0 +1,32 @@ +// run-pass +// edition: 2024 +// compile-flags: -Zunstable-options +#![feature(async_iterator, async_iter_from_iter, const_waker, async_for_loop, noop_waker, + gen_blocks)] + +use std::future::Future; + +async gen fn async_iter() -> i32 { + let iter = core::async_iter::from_iter(0..3); + for await i in iter { + yield i + 1; + } +} + +// make sure a simple for await loop works +async fn real_main() { + let mut count = 1; + for await i in async_iter() { + assert_eq!(i, count); + count += 1; + } + assert_eq!(count, 4); +} + +fn main() { + let future = real_main(); + let waker = std::task::Waker::noop(); + let mut cx = &mut core::task::Context::from_waker(&waker); + let mut future = core::pin::pin!(future); + while let core::task::Poll::Pending = future.as_mut().poll(&mut cx) {} +} diff --git a/tests/ui/async-await/for-await.rs b/tests/ui/async-await/for-await.rs new file mode 100644 index 00000000000..6345ceb0c27 --- /dev/null +++ b/tests/ui/async-await/for-await.rs @@ -0,0 +1,24 @@ +// run-pass +// edition: 2021 +#![feature(async_iterator, async_iter_from_iter, const_waker, async_for_loop, noop_waker)] + +use std::future::Future; + +// make sure a simple for await loop works +async fn real_main() { + let iter = core::async_iter::from_iter(0..3); + let mut count = 0; + for await i in iter { + assert_eq!(i, count); + count += 1; + } + assert_eq!(count, 3); +} + +fn main() { + let future = real_main(); + let waker = std::task::Waker::noop(); + let mut cx = &mut core::task::Context::from_waker(&waker); + let mut future = core::pin::pin!(future); + while let core::task::Poll::Pending = future.as_mut().poll(&mut cx) {} +} diff --git a/tests/ui/const-generics/default-ty-closure.rs b/tests/ui/const-generics/default-ty-closure.rs new file mode 100644 index 00000000000..36128505dda --- /dev/null +++ b/tests/ui/const-generics/default-ty-closure.rs @@ -0,0 +1,6 @@ +// https://github.com/rust-lang/rust/issues/116796 + +struct X<const FN: fn() = { || {} }>; +//~^ ERROR using function pointers as const generic parameters is forbidden + +fn main() {} diff --git a/tests/ui/const-generics/default-ty-closure.stderr b/tests/ui/const-generics/default-ty-closure.stderr new file mode 100644 index 00000000000..9c737c1a19d --- /dev/null +++ b/tests/ui/const-generics/default-ty-closure.stderr @@ -0,0 +1,10 @@ +error: using function pointers as const generic parameters is forbidden + --> $DIR/default-ty-closure.rs:3:20 + | +LL | struct X<const FN: fn() = { || {} }>; + | ^^^^ + | + = note: the only supported types are integers, `bool` and `char` + +error: aborting due to 1 previous error + diff --git a/tests/ui/consts/auxiliary/closure-in-foreign-crate.rs b/tests/ui/consts/auxiliary/closure-in-foreign-crate.rs index edc7fa81abb..411707133a8 100644 --- a/tests/ui/consts/auxiliary/closure-in-foreign-crate.rs +++ b/tests/ui/consts/auxiliary/closure-in-foreign-crate.rs @@ -1,5 +1,5 @@ #![crate_type = "lib"] -#![feature(const_closures, const_trait_impl)] +#![feature(const_closures, const_trait_impl, effects)] #![allow(incomplete_features)] pub const fn test() { diff --git a/tests/ui/consts/const-float-classify.rs b/tests/ui/consts/const-float-classify.rs index 877ce02193c..e8bd095ed25 100644 --- a/tests/ui/consts/const-float-classify.rs +++ b/tests/ui/consts/const-float-classify.rs @@ -1,41 +1,24 @@ // compile-flags: -Zmir-opt-level=0 -// known-bug: #110395 -// FIXME run-pass +// run-pass #![feature(const_float_bits_conv)] #![feature(const_float_classify)] -#![feature(const_trait_impl)] +#![feature(const_trait_impl, effects)] // Don't promote const fn nop<T>(x: T) -> T { x } -// FIXME(const-hack): replace with PartialEq -#[const_trait] -trait MyEq<T> { - fn eq(self, b: T) -> bool; -} - -impl const MyEq<bool> for bool { - fn eq(self, b: bool) -> bool { - self == b - } -} - -impl const MyEq<NonDet> for bool { - fn eq(self, _: NonDet) -> bool { +impl const PartialEq<NonDet> for bool { + fn eq(&self, _: &NonDet) -> bool { true } } -const fn eq<A: ~const MyEq<B>, B>(x: A, y: B) -> bool { - x.eq(y) -} - macro_rules! const_assert { ($a:expr, $b:expr) => { { - const _: () = assert!(eq($a, $b)); - assert!(eq(nop($a), nop($b))); + const _: () = assert!($a == $b); + assert!(nop($a) == nop($b)); } }; } diff --git a/tests/ui/consts/const-float-classify.stderr b/tests/ui/consts/const-float-classify.stderr deleted file mode 100644 index f0c6c69eac4..00000000000 --- a/tests/ui/consts/const-float-classify.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0015]: cannot call non-const fn `<A as MyEq<B>>::eq` in constant functions - --> $DIR/const-float-classify.rs:31:7 - | -LL | x.eq(y) - | ^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/const-try.stderr b/tests/ui/consts/const-try.stderr index 94f4153a29e..37a6598af9e 100644 --- a/tests/ui/consts/const-try.stderr +++ b/tests/ui/consts/const-try.stderr @@ -10,6 +10,7 @@ note: impl defined here, but it is not `const` LL | impl const Try for TryMe { | ^^^^^^^^^^^^^^^^^^^^^^^^ = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable error[E0015]: `?` cannot convert from residual of `TryMe` in constant functions --> $DIR/const-try.rs:33:5 @@ -23,6 +24,7 @@ note: impl defined here, but it is not `const` LL | impl const FromResidual<Error> for TryMe { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable error: aborting due to 2 previous errors diff --git a/tests/ui/consts/const_cmp_type_id.rs b/tests/ui/consts/const_cmp_type_id.rs index 19cee2022ac..cda811144c7 100644 --- a/tests/ui/consts/const_cmp_type_id.rs +++ b/tests/ui/consts/const_cmp_type_id.rs @@ -1,6 +1,6 @@ // known-bug: #110395 #![feature(const_type_id)] -#![feature(const_trait_impl)] +#![feature(const_trait_impl, effects)] use std::any::TypeId; diff --git a/tests/ui/consts/const_cmp_type_id.stderr b/tests/ui/consts/const_cmp_type_id.stderr index 0d915cec07d..84be0b67307 100644 --- a/tests/ui/consts/const_cmp_type_id.stderr +++ b/tests/ui/consts/const_cmp_type_id.stderr @@ -1,34 +1,28 @@ -error[E0015]: cannot call non-const operator in constant functions +error[E0131]: `main` function is not allowed to have generic parameters + --> $DIR/const_cmp_type_id.rs:7:14 + | +LL | const fn main() { + | ^ `main` cannot have generic parameters + +error[E0308]: mismatched types --> $DIR/const_cmp_type_id.rs:8:13 | LL | assert!(TypeId::of::<u8>() == TypeId::of::<u8>()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `host`, found `true` | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/any.rs:LL:COL - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = note: expected constant `host` + found constant `true` -error[E0015]: cannot call non-const operator in constant functions +error[E0308]: mismatched types --> $DIR/const_cmp_type_id.rs:9:13 | LL | assert!(TypeId::of::<()>() != TypeId::of::<u8>()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/any.rs:LL:COL - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const operator in constants - --> $DIR/const_cmp_type_id.rs:10:22 - | -LL | const _A: bool = TypeId::of::<u8>() < TypeId::of::<u16>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `host`, found `true` | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/any.rs:LL:COL - = note: calls in constants are limited to constant functions, tuple structs and tuple variants - = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: expected constant `host` + found constant `true` error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0015`. +Some errors have detailed explanations: E0131, E0308. +For more information about an error, try `rustc --explain E0131`. diff --git a/tests/ui/consts/constifconst-call-in-const-position.stderr b/tests/ui/consts/constifconst-call-in-const-position.stderr index 6eee466611c..42ad4125824 100644 --- a/tests/ui/consts/constifconst-call-in-const-position.stderr +++ b/tests/ui/consts/constifconst-call-in-const-position.stderr @@ -14,6 +14,7 @@ LL | [0; T::a()] | ^^^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable error[E0015]: cannot call non-const fn `<T as Tr>::a` in constants --> $DIR/constifconst-call-in-const-position.rs:16:38 @@ -22,6 +23,7 @@ LL | const fn foo<T: ~const Tr>() -> [u8; T::a()] { | ^^^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable error: aborting due to 2 previous errors; 1 warning emitted diff --git a/tests/ui/consts/issue-73976-monomorphic.stderr b/tests/ui/consts/issue-73976-monomorphic.stderr index ef754b23ff0..465efc7bfc2 100644 --- a/tests/ui/consts/issue-73976-monomorphic.stderr +++ b/tests/ui/consts/issue-73976-monomorphic.stderr @@ -7,6 +7,7 @@ LL | GetTypeId::<T>::VALUE == GetTypeId::<usize>::VALUE note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/any.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable error: aborting due to 1 previous error diff --git a/tests/ui/consts/issue-94675.stderr b/tests/ui/consts/issue-94675.stderr index f51f305ac38..60a56f85c11 100644 --- a/tests/ui/consts/issue-94675.stderr +++ b/tests/ui/consts/issue-94675.stderr @@ -15,6 +15,7 @@ LL | self.bar[0] = baz.len(); note: impl defined here, but it is not `const` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable error: aborting due to 2 previous errors diff --git a/tests/ui/entry-point/return-ty-has-bound-vars.rs b/tests/ui/entry-point/return-ty-has-bound-vars.rs new file mode 100644 index 00000000000..0995ce06160 --- /dev/null +++ b/tests/ui/entry-point/return-ty-has-bound-vars.rs @@ -0,0 +1,3 @@ +// issue-119209 + +fn main<'a>(_: &'a i32) -> &'a () { &() } //~ERROR `main` function return type is not allowed to have generic parameters diff --git a/tests/ui/entry-point/return-ty-has-bound-vars.stderr b/tests/ui/entry-point/return-ty-has-bound-vars.stderr new file mode 100644 index 00000000000..e7aab839f31 --- /dev/null +++ b/tests/ui/entry-point/return-ty-has-bound-vars.stderr @@ -0,0 +1,9 @@ +error[E0131]: `main` function return type is not allowed to have generic parameters + --> $DIR/return-ty-has-bound-vars.rs:3:28 + | +LL | fn main<'a>(_: &'a i32) -> &'a () { &() } + | ^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0131`. diff --git a/tests/ui/generic-const-items/const-trait-impl.stderr b/tests/ui/generic-const-items/const-trait-impl.stderr index e7e90542796..cdcd24eceff 100644 --- a/tests/ui/generic-const-items/const-trait-impl.stderr +++ b/tests/ui/generic-const-items/const-trait-impl.stderr @@ -5,6 +5,7 @@ LL | const CREATE<T: Create>: T = T::create(); | ^^^^^^^^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/higher-ranked-lifetime-error.stderr b/tests/ui/higher-ranked/higher-ranked-lifetime-error.stderr index d0892fd8b09..c25e731d962 100644 --- a/tests/ui/higher-ranked/higher-ranked-lifetime-error.stderr +++ b/tests/ui/higher-ranked/higher-ranked-lifetime-error.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | assert_all::<_, &String>(id); | ^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | - = note: expected reference `&String` - found reference `&String` + = note: expected trait `for<'a> <for<'a> fn(&'a String) -> &'a String {id} as FnMut<(&'a String,)>>` + found trait `for<'a> <for<'a> fn(&'a String) -> &'a String {id} as FnMut<(&'a String,)>>` error: aborting due to 1 previous error diff --git a/tests/ui/mir/lint/no-storage.rs b/tests/ui/mir/lint/no-storage.rs new file mode 100644 index 00000000000..246a0b34e5d --- /dev/null +++ b/tests/ui/mir/lint/no-storage.rs @@ -0,0 +1,30 @@ +// compile-flags: -Zlint-mir --crate-type=lib -Ztreat-err-as-bug +// failure-status: 101 +// dont-check-compiler-stderr +// regex-error-pattern: use of local .*, which has no storage here +#![feature(custom_mir, core_intrinsics)] +extern crate core; +use core::intrinsics::mir::*; + +#[custom_mir(dialect = "built")] +pub fn f(a: bool) { + mir!( + let b: (); + { + match a { true => bb1, _ => bb2 } + } + bb1 = { + StorageLive(b); + Goto(bb3) + } + bb2 = { + Goto(bb3) + } + bb3 = { + b = (); + RET = b; + StorageDead(b); + Return() + } + ) +} diff --git a/tests/ui/mir/validate/storage-live.rs b/tests/ui/mir/lint/storage-live.rs index ed3c26ed6da..f34a2c7de37 100644 --- a/tests/ui/mir/validate/storage-live.rs +++ b/tests/ui/mir/lint/storage-live.rs @@ -1,4 +1,4 @@ -// compile-flags: -Zvalidate-mir -Ztreat-err-as-bug +// compile-flags: -Zlint-mir -Ztreat-err-as-bug // failure-status: 101 // error-pattern: broken MIR in // error-pattern: StorageLive(_1) which already has storage here diff --git a/tests/ui/mir/validate/storage-live.stderr b/tests/ui/mir/lint/storage-live.stderr index 1037ddc88ef..1037ddc88ef 100644 --- a/tests/ui/mir/validate/storage-live.stderr +++ b/tests/ui/mir/lint/storage-live.stderr diff --git a/tests/ui/mir/lint/storage-return.rs b/tests/ui/mir/lint/storage-return.rs new file mode 100644 index 00000000000..a2f63b449b4 --- /dev/null +++ b/tests/ui/mir/lint/storage-return.rs @@ -0,0 +1,19 @@ +// compile-flags: -Zlint-mir -Ztreat-err-as-bug +// failure-status: 101 +// dont-check-compiler-stderr +// error-pattern: has storage when returning +#![feature(custom_mir, core_intrinsics)] +extern crate core; +use core::intrinsics::mir::*; + +#[custom_mir(dialect = "built")] +fn main() { + mir!( + let a: (); + { + StorageLive(a); + RET = a; + Return() + } + ) +} diff --git a/tests/ui/pattern/usefulness/impl-trait.rs b/tests/ui/pattern/usefulness/impl-trait.rs new file mode 100644 index 00000000000..ceb97315e9d --- /dev/null +++ b/tests/ui/pattern/usefulness/impl-trait.rs @@ -0,0 +1,155 @@ +#![feature(never_type)] +#![feature(exhaustive_patterns)] +#![feature(type_alias_impl_trait)] +#![feature(non_exhaustive_omitted_patterns_lint)] +#![deny(unreachable_patterns)] +// Test that the lint traversal handles opaques correctly +#![deny(non_exhaustive_omitted_patterns)] + +fn main() {} + +#[derive(Copy, Clone)] +enum Void {} + +fn return_never_rpit(x: Void) -> impl Copy { + if false { + match return_never_rpit(x) { + _ => {} //~ ERROR unreachable + } + } + x +} +fn friend_of_return_never_rpit(x: Void) { + match return_never_rpit(x) {} + //~^ ERROR non-empty +} + +type T = impl Copy; +fn return_never_tait(x: Void) -> T { + if false { + match return_never_tait(x) { + _ => {} //~ ERROR unreachable + } + } + x +} +fn friend_of_return_never_tait(x: Void) { + match return_never_tait(x) {} + //~^ ERROR non-empty +} + +fn option_never(x: Void) -> Option<impl Copy> { + if false { + match option_never(x) { + None => {} + Some(_) => {} //~ ERROR unreachable + } + match option_never(x) { + None => {} + _ => {} //~ ERROR unreachable + } + } + Some(x) +} + +fn option_never2(x: Void) -> impl Copy { + if false { + match option_never2(x) { + None => {} + Some(_) => {} //~ ERROR unreachable + } + match option_never2(x) { + None => {} + _ => {} //~ ERROR unreachable + } + match option_never2(x) { + None => {} + } + } + Some(x) +} + +fn inner_never(x: Void) { + type T = impl Copy; + let y: T = x; + match y { + _ => {} //~ ERROR unreachable + } +} + +// This one caused ICE https://github.com/rust-lang/rust/issues/117100. +fn inner_tuple() { + type T = impl Copy; + let foo: T = Some((1u32, 2u32)); + match foo { + _ => {} + Some((a, b)) => {} //~ ERROR unreachable + } +} + +type U = impl Copy; +fn unify_never(x: Void, u: U) -> U { + if false { + match u { + _ => {} //~ ERROR unreachable + } + } + x +} + +type V = impl Copy; +fn infer_in_match(x: Option<V>) { + match x { + None => {} + Some((a, b)) => {} + Some((mut x, mut y)) => { + //~^ ERROR unreachable + x = 42; + y = "foo"; + } + } +} + +type W = impl Copy; +#[derive(Copy, Clone)] +struct Rec<'a> { + n: u32, + w: Option<&'a W>, +} +fn recursive_opaque() -> W { + if false { + match recursive_opaque() { + // Check for the ol' ICE when the type is recursively opaque. + _ => {} + Rec { n: 0, w: Some(Rec { n: 0, w: _ }) } => {} //~ ERROR unreachable + } + } + let w: Option<&'static W> = None; + Rec { n: 0, w } +} + +type X = impl Copy; +struct SecretelyVoid(X); +fn nested_empty_opaque(x: Void) -> X { + if false { + let opaque_void = nested_empty_opaque(x); + let secretely_void = SecretelyVoid(opaque_void); + match secretely_void { + _ => {} //~ ERROR unreachable + } + } + x +} + +type Y = (impl Copy, impl Copy); +struct SecretelyDoubleVoid(Y); +fn super_nested_empty_opaque(x: Void) -> Y { + if false { + let opaque_void = super_nested_empty_opaque(x); + let secretely_void = SecretelyDoubleVoid(opaque_void); + match secretely_void { + _ => {} //~ ERROR unreachable + } + } + (x, x) +} diff --git a/tests/ui/pattern/usefulness/impl-trait.stderr b/tests/ui/pattern/usefulness/impl-trait.stderr new file mode 100644 index 00000000000..ba8b12f9f66 --- /dev/null +++ b/tests/ui/pattern/usefulness/impl-trait.stderr @@ -0,0 +1,119 @@ +error: unreachable pattern + --> $DIR/impl-trait.rs:17:13 + | +LL | _ => {} + | ^ + | +note: the lint level is defined here + --> $DIR/impl-trait.rs:5:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/impl-trait.rs:31:13 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/impl-trait.rs:45:13 + | +LL | Some(_) => {} + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/impl-trait.rs:49:13 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/impl-trait.rs:59:13 + | +LL | Some(_) => {} + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/impl-trait.rs:63:13 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/impl-trait.rs:76:9 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/impl-trait.rs:86:9 + | +LL | _ => {} + | - matches any value +LL | Some((a, b)) => {} + | ^^^^^^^^^^^^ unreachable pattern + +error: unreachable pattern + --> $DIR/impl-trait.rs:94:13 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/impl-trait.rs:105:9 + | +LL | Some((mut x, mut y)) => { + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/impl-trait.rs:124:13 + | +LL | _ => {} + | - matches any value +LL | Rec { n: 0, w: Some(Rec { n: 0, w: _ }) } => {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern + +error: unreachable pattern + --> $DIR/impl-trait.rs:138:13 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/impl-trait.rs:151:13 + | +LL | _ => {} + | ^ + +error[E0004]: non-exhaustive patterns: type `impl Copy` is non-empty + --> $DIR/impl-trait.rs:23:11 + | +LL | match return_never_rpit(x) {} + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: the matched value is of type `impl Copy` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match return_never_rpit(x) { +LL + _ => todo!(), +LL + } + | + +error[E0004]: non-exhaustive patterns: type `T` is non-empty + --> $DIR/impl-trait.rs:37:11 + | +LL | match return_never_tait(x) {} + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: the matched value is of type `T` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match return_never_tait(x) { +LL + _ => todo!(), +LL + } + | + +error: aborting due to 15 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-118437-exponential-time-on-diagonal-match.rs b/tests/ui/pattern/usefulness/issue-118437-exponential-time-on-diagonal-match.rs new file mode 100644 index 00000000000..39ad2d4abf3 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-118437-exponential-time-on-diagonal-match.rs @@ -0,0 +1,72 @@ +// check-pass +struct BaseCommand { + field01: bool, + field02: bool, + field03: bool, + field04: bool, + field05: bool, + field06: bool, + field07: bool, + field08: bool, + field09: bool, + field10: bool, + field11: bool, + field12: bool, + field13: bool, + field14: bool, + field15: bool, + field16: bool, + field17: bool, + field18: bool, + field19: bool, + field20: bool, + field21: bool, + field22: bool, + field23: bool, + field24: bool, + field25: bool, + field26: bool, + field27: bool, + field28: bool, + field29: bool, + field30: bool, +} + +fn request_key(command: BaseCommand) { + match command { + BaseCommand { field01: true, .. } => {} + BaseCommand { field02: true, .. } => {} + BaseCommand { field03: true, .. } => {} + BaseCommand { field04: true, .. } => {} + BaseCommand { field05: true, .. } => {} + BaseCommand { field06: true, .. } => {} + BaseCommand { field07: true, .. } => {} + BaseCommand { field08: true, .. } => {} + BaseCommand { field09: true, .. } => {} + BaseCommand { field10: true, .. } => {} + BaseCommand { field11: true, .. } => {} + BaseCommand { field12: true, .. } => {} + BaseCommand { field13: true, .. } => {} + BaseCommand { field14: true, .. } => {} + BaseCommand { field15: true, .. } => {} + BaseCommand { field16: true, .. } => {} + BaseCommand { field17: true, .. } => {} + BaseCommand { field18: true, .. } => {} + BaseCommand { field19: true, .. } => {} + BaseCommand { field20: true, .. } => {} + BaseCommand { field21: true, .. } => {} + BaseCommand { field22: true, .. } => {} + BaseCommand { field23: true, .. } => {} + BaseCommand { field24: true, .. } => {} + BaseCommand { field25: true, .. } => {} + BaseCommand { field26: true, .. } => {} + BaseCommand { field27: true, .. } => {} + BaseCommand { field28: true, .. } => {} + BaseCommand { field29: true, .. } => {} + BaseCommand { field30: true, .. } => {} + + _ => {} + } +} + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-pass.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-pass.stderr index 60cd000f2d8..e72d259e8a5 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-pass.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-pass.stderr @@ -5,6 +5,7 @@ LL | a.plus(b) | ^^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable error[E0015]: cannot call non-const operator in constants --> $DIR/call-const-trait-method-pass.rs:39:22 @@ -18,6 +19,7 @@ note: impl defined here, but it is not `const` LL | impl const std::ops::Add for Int { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable error: aborting due to 2 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call.rs index 5f48c235373..e85976b7e1d 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call.rs @@ -1,6 +1,6 @@ // check-pass -#![feature(const_closures, const_trait_impl)] +#![feature(const_closures, const_trait_impl, effects)] #![allow(incomplete_features)] pub const _: () = { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs index bde8bf20f46..34a0ba1e271 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs @@ -3,7 +3,7 @@ // // check-pass -#![feature(const_trait_impl)] +#![feature(const_trait_impl, effects)] // aux-build: cross-crate.rs extern crate cross_crate; diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.rs index 6598d1da0f8..7d811a2cc1f 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.rs @@ -1,3 +1,5 @@ +// check-pass +// FIXME(effects) this shouldn't pass #![feature(const_closures, const_trait_impl, effects)] #![allow(incomplete_features)] @@ -11,5 +13,5 @@ impl Foo for () { fn main() { (const || { (()).foo() })(); - //~^ ERROR: cannot call non-const fn + // FIXME(effects) ~^ ERROR: cannot call non-const fn } diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.stderr deleted file mode 100644 index 413e217020d..00000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0015]: cannot call non-const fn `<() as Foo>::foo` in constant functions - --> $DIR/const_closure-const_trait_impl-ice-113381.rs:13:22 - | -LL | (const || { (()).foo() })(); - | ^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-112822-expected-type-for-param.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-112822-expected-type-for-param.rs new file mode 100644 index 00000000000..61e31fc9786 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-112822-expected-type-for-param.rs @@ -0,0 +1,16 @@ +#![feature(const_trait_impl, effects)] + +const fn test() -> impl ~const Fn() { //~ ERROR ~const can only be applied to `#[const_trait]` traits + const move || { //~ ERROR const closures are experimental + let sl: &[u8] = b"foo"; + + match sl { + [first, remainder @ ..] => { + assert_eq!(first, &b'f'); + } + [] => panic!(), + } + } +} + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-112822-expected-type-for-param.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-112822-expected-type-for-param.stderr new file mode 100644 index 00000000000..65808212314 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-112822-expected-type-for-param.stderr @@ -0,0 +1,18 @@ +error[E0658]: const closures are experimental + --> $DIR/ice-112822-expected-type-for-param.rs:4:5 + | +LL | const move || { + | ^^^^^ + | + = note: see issue #106003 <https://github.com/rust-lang/rust/issues/106003> for more information + = help: add `#![feature(const_closures)]` to the crate attributes to enable + +error: ~const can only be applied to `#[const_trait]` traits + --> $DIR/ice-112822-expected-type-for-param.rs:3:32 + | +LL | const fn test() -> impl ~const Fn() { + | ^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/generic-bound.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/generic-bound.stderr index 1e8a70ffd29..f42fee59bf0 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/generic-bound.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/generic-bound.stderr @@ -10,6 +10,7 @@ note: impl defined here, but it is not `const` LL | impl<T> const std::ops::Add for S<T> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102985.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102985.stderr index 077f6c7b234..0fa4c8fe04c 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102985.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102985.stderr @@ -4,7 +4,9 @@ error[E0015]: cannot call non-const closure in constants LL | n => n(), | ^^^ | + = note: closures need an RFC before allowed to be called in constants = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.rs index b604c65d751..269fd87ba0d 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.rs @@ -1,5 +1,5 @@ #![feature(const_fmt_arguments_new)] -#![feature(const_trait_impl)] +#![feature(const_trait_impl, effects)] #[const_trait] trait Tr { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-88155.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-88155.stderr index 157b54214fa..e5347a09598 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-88155.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-88155.stderr @@ -5,6 +5,7 @@ LL | T::assoc() | ^^^^^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.gated.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.gated.stderr index 89e59e5db6e..28254ac15a8 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.gated.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.gated.stderr @@ -6,6 +6,7 @@ LL | "a" => (), //FIXME [gated]~ ERROR can't compare `str` with `str` in | = note: `str` cannot be compared in compile-time, and therefore cannot be used in `match`es = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-const-closure-non-const-outer.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-const-closure-non-const-outer.stderr index 97ad83130d4..d82a49be75e 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-const-closure-non-const-outer.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-const-closure-non-const-outer.stderr @@ -5,6 +5,7 @@ LL | (const || { (()).foo() })(); | ^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.rs index ada475909a3..e0c20b819e8 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.rs @@ -1,4 +1,4 @@ -#![feature(const_trait_impl, min_specialization, rustc_attrs)] +#![feature(const_trait_impl, effects, min_specialization, rustc_attrs)] // known-bug: #110395 #[rustc_specialization_trait] #[const_trait] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr index 0b35feddc55..5210a694201 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr @@ -1,11 +1,12 @@ -error[E0015]: cannot call non-const fn `<T as A>::a` in constant functions - --> $DIR/specializing-constness-2.rs:27:5 +error[E0119]: conflicting implementations of trait `A` + --> $DIR/specializing-constness-2.rs:20:1 | -LL | <T as A>::a(); - | ^^^^^^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +LL | impl<T: Default> A for T { + | ------------------------ first implementation here +... +LL | impl<T: Default + ~const Sup> const A for T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr index 12bcdb034bc..fd4d7ff3475 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr @@ -1,23 +1,23 @@ error: `~const` is not allowed here - --> $DIR/super-traits-fail-2.rs:11:12 + --> $DIR/super-traits-fail-2.rs:10:12 | LL | trait Bar: ~const Foo {} | ^^^^^^ | note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds - --> $DIR/super-traits-fail-2.rs:11:1 + --> $DIR/super-traits-fail-2.rs:10:1 | LL | trait Bar: ~const Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ error: ~const can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-2.rs:11:19 + --> $DIR/super-traits-fail-2.rs:10:19 | LL | trait Bar: ~const Foo {} | ^^^ error: ~const can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-2.rs:11:19 + --> $DIR/super-traits-fail-2.rs:10:19 | LL | trait Bar: ~const Foo {} | ^^^ diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr index b60399c57dc..d2e3a5cec1d 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr @@ -1,11 +1,11 @@ error: ~const can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-2.rs:11:19 + --> $DIR/super-traits-fail-2.rs:10:19 | LL | trait Bar: ~const Foo {} | ^^^ error: ~const can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-2.rs:11:19 + --> $DIR/super-traits-fail-2.rs:10:19 | LL | trait Bar: ~const Foo {} | ^^^ diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.rs index 93fd96f8f29..3820d069243 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.rs @@ -1,5 +1,4 @@ -#![feature(const_trait_impl)] -// known-bug: #110395 +#![feature(const_trait_impl, effects)] // revisions: yy yn ny nn #[cfg_attr(any(yy, yn), const_trait)] @@ -9,12 +8,14 @@ trait Foo { #[cfg_attr(any(yy, ny), const_trait)] trait Bar: ~const Foo {} -// FIXME [ny,nn]~^ ERROR: ~const can only be applied to `#[const_trait]` -// FIXME [ny,nn]~| ERROR: ~const can only be applied to `#[const_trait]` +//[ny,nn]~^ ERROR: ~const can only be applied to `#[const_trait]` +//[ny,nn]~| ERROR: ~const can only be applied to `#[const_trait]` +//[yn,nn]~^^^ ERROR: `~const` is not allowed here const fn foo<T: Bar>(x: &T) { x.a(); - // FIXME [yn,yy]~^ ERROR the trait bound + //[yy,yn]~^ ERROR mismatched types + // FIXME(effects) diagnostic } fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr index e465ebaffa8..c05c4d50a33 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr @@ -1,14 +1,24 @@ error: `~const` is not allowed here - --> $DIR/super-traits-fail-2.rs:11:12 + --> $DIR/super-traits-fail-2.rs:10:12 | LL | trait Bar: ~const Foo {} | ^^^^^^ | note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds - --> $DIR/super-traits-fail-2.rs:11:1 + --> $DIR/super-traits-fail-2.rs:10:1 | LL | trait Bar: ~const Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error[E0308]: mismatched types + --> $DIR/super-traits-fail-2.rs:16:5 + | +LL | x.a(); + | ^^^^^ expected `host`, found `true` + | + = note: expected constant `host` + found constant `true` + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr index 1faa5b4dd2c..852c02cad5c 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr @@ -1,11 +1,12 @@ -error[E0015]: cannot call non-const fn `<T as Foo>::a` in constant functions - --> $DIR/super-traits-fail-2.rs:16:7 +error[E0308]: mismatched types + --> $DIR/super-traits-fail-2.rs:16:5 | LL | x.a(); - | ^^^ + | ^^^^^ expected `host`, found `true` | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = note: expected constant `host` + found constant `true` error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr index e10c51ef45a..199d2199c4a 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr @@ -1,23 +1,23 @@ error: `~const` is not allowed here - --> $DIR/super-traits-fail-3.rs:13:12 + --> $DIR/super-traits-fail-3.rs:12:12 | LL | trait Bar: ~const Foo {} | ^^^^^^ | note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds - --> $DIR/super-traits-fail-3.rs:13:1 + --> $DIR/super-traits-fail-3.rs:12:1 | LL | trait Bar: ~const Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ error: ~const can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:13:19 + --> $DIR/super-traits-fail-3.rs:12:19 | LL | trait Bar: ~const Foo {} | ^^^ error: ~const can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:13:19 + --> $DIR/super-traits-fail-3.rs:12:19 | LL | trait Bar: ~const Foo {} | ^^^ @@ -25,7 +25,7 @@ LL | trait Bar: ~const Foo {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: ~const can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:18:24 + --> $DIR/super-traits-fail-3.rs:17:24 | LL | const fn foo<T: ~const Bar>(x: &T) { | ^^^ diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr index cd0ee73277d..46eedc333f1 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr @@ -1,11 +1,11 @@ error: ~const can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:13:19 + --> $DIR/super-traits-fail-3.rs:12:19 | LL | trait Bar: ~const Foo {} | ^^^ error: ~const can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:13:19 + --> $DIR/super-traits-fail-3.rs:12:19 | LL | trait Bar: ~const Foo {} | ^^^ diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs index 5994057b2db..3e98e131930 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs @@ -1,8 +1,7 @@ -#![feature(const_trait_impl)] +#![feature(const_trait_impl, effects)] // revisions: yy yn ny nn -//[yy] known-bug: #110395 -//FIXME [yy] check-pass +//[yy] check-pass #[cfg_attr(any(yy, yn), const_trait)] trait Foo { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr index 34f6515b572..dc08a899738 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr @@ -1,17 +1,17 @@ error: `~const` is not allowed here - --> $DIR/super-traits-fail-3.rs:13:12 + --> $DIR/super-traits-fail-3.rs:12:12 | LL | trait Bar: ~const Foo {} | ^^^^^^ | note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds - --> $DIR/super-traits-fail-3.rs:13:1 + --> $DIR/super-traits-fail-3.rs:12:1 | LL | trait Bar: ~const Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ error: ~const can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:18:24 + --> $DIR/super-traits-fail-3.rs:17:24 | LL | const fn foo<T: ~const Bar>(x: &T) { | ^^^ diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yy.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yy.stderr deleted file mode 100644 index 5cccc025161..00000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yy.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0015]: cannot call non-const fn `<T as Foo>::a` in constant functions - --> $DIR/super-traits-fail-3.rs:20:7 - | -LL | x.a(); - | ^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-default-body-stability.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-default-body-stability.rs index 8d56295e738..aa3b09ec966 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-default-body-stability.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-default-body-stability.rs @@ -1,7 +1,7 @@ // known-bug: #110395 #![feature(staged_api)] -#![feature(const_trait_impl)] +#![feature(const_trait_impl, effects)] #![feature(const_t_try)] #![feature(const_try)] #![feature(try_trait_v2)] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-default-body-stability.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-default-body-stability.stderr index deed05ae179..62c4bc3b7ae 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-default-body-stability.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-default-body-stability.stderr @@ -1,29 +1,39 @@ -error[E0015]: `?` cannot determine the branch of `T` in constant functions - --> $DIR/trait-default-body-stability.rs:44:9 +error: const `impl` for trait `Try` which is not marked with `#[const_trait]` + --> $DIR/trait-default-body-stability.rs:18:12 | -LL | T? - | ^^ +LL | impl const Try for T { + | ^^^ | -note: impl defined here, but it is not `const` - --> $DIR/trait-default-body-stability.rs:18:1 + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: const `impl` for trait `FromResidual` which is not marked with `#[const_trait]` + --> $DIR/trait-default-body-stability.rs:33:12 | -LL | impl const Try for T { - | ^^^^^^^^^^^^^^^^^^^^ - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +LL | impl const FromResidual for T { + | ^^^^^^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change -error[E0015]: `?` cannot convert from residual of `T` in constant functions - --> $DIR/trait-default-body-stability.rs:44:9 +error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates + --> $DIR/trait-default-body-stability.rs:18:6 | -LL | T? - | ^^ +LL | impl const Try for T { + | ^^^^^ unconstrained const parameter | -note: impl defined here, but it is not `const` - --> $DIR/trait-default-body-stability.rs:33:1 + = note: expressions using a const parameter must map each value to a distinct output value + = note: proving the result of expressions other than the parameter are unique is not supported + +error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates + --> $DIR/trait-default-body-stability.rs:33:6 | LL | impl const FromResidual for T { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + | ^^^^^ unconstrained const parameter + | + = note: expressions using a const parameter must map each value to a distinct output value + = note: proving the result of expressions other than the parameter are unique is not supported -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/stats/hir-stats.stderr b/tests/ui/stats/hir-stats.stderr index e6da83296ce..070dbbb10bb 100644 --- a/tests/ui/stats/hir-stats.stderr +++ b/tests/ui/stats/hir-stats.stderr @@ -15,20 +15,20 @@ ast-stats-1 Arm 96 ( 1.5%) 2 48 ast-stats-1 ForeignItem 96 ( 1.5%) 1 96 ast-stats-1 - Fn 96 ( 1.5%) 1 ast-stats-1 FnDecl 120 ( 1.8%) 5 24 -ast-stats-1 FieldDef 160 ( 2.5%) 2 80 -ast-stats-1 Stmt 160 ( 2.5%) 5 32 +ast-stats-1 FieldDef 160 ( 2.4%) 2 80 +ast-stats-1 Stmt 160 ( 2.4%) 5 32 ast-stats-1 - Local 32 ( 0.5%) 1 ast-stats-1 - MacCall 32 ( 0.5%) 1 ast-stats-1 - Expr 96 ( 1.5%) 3 -ast-stats-1 Param 160 ( 2.5%) 4 40 +ast-stats-1 Param 160 ( 2.4%) 4 40 ast-stats-1 Block 192 ( 2.9%) 6 32 ast-stats-1 Variant 208 ( 3.2%) 2 104 -ast-stats-1 GenericBound 256 ( 3.9%) 4 64 -ast-stats-1 - Trait 256 ( 3.9%) 4 +ast-stats-1 GenericBound 288 ( 4.4%) 4 72 +ast-stats-1 - Trait 288 ( 4.4%) 4 ast-stats-1 AssocItem 352 ( 5.4%) 4 88 ast-stats-1 - Type 176 ( 2.7%) 2 ast-stats-1 - Fn 176 ( 2.7%) 2 -ast-stats-1 GenericParam 480 ( 7.4%) 5 96 +ast-stats-1 GenericParam 480 ( 7.3%) 5 96 ast-stats-1 Pat 504 ( 7.7%) 7 72 ast-stats-1 - Struct 72 ( 1.1%) 1 ast-stats-1 - Wild 72 ( 1.1%) 1 @@ -45,15 +45,15 @@ ast-stats-1 - Ptr 64 ( 1.0%) 1 ast-stats-1 - Ref 64 ( 1.0%) 1 ast-stats-1 - ImplicitSelf 128 ( 2.0%) 2 ast-stats-1 - Path 640 ( 9.8%) 10 -ast-stats-1 Item 1_224 (18.8%) 9 136 +ast-stats-1 Item 1_224 (18.7%) 9 136 ast-stats-1 - Trait 136 ( 2.1%) 1 ast-stats-1 - Enum 136 ( 2.1%) 1 ast-stats-1 - ForeignMod 136 ( 2.1%) 1 ast-stats-1 - Impl 136 ( 2.1%) 1 ast-stats-1 - Fn 272 ( 4.2%) 2 -ast-stats-1 - Use 408 ( 6.3%) 3 +ast-stats-1 - Use 408 ( 6.2%) 3 ast-stats-1 ---------------------------------------------------------------- -ast-stats-1 Total 6_520 +ast-stats-1 Total 6_552 ast-stats-1 ast-stats-2 POST EXPANSION AST STATS ast-stats-2 Name Accumulated Size Count Item Size @@ -81,16 +81,16 @@ ast-stats-2 - Expr 96 ( 1.3%) 3 ast-stats-2 Param 160 ( 2.2%) 4 40 ast-stats-2 Block 192 ( 2.7%) 6 32 ast-stats-2 Variant 208 ( 2.9%) 2 104 -ast-stats-2 GenericBound 256 ( 3.6%) 4 64 -ast-stats-2 - Trait 256 ( 3.6%) 4 +ast-stats-2 GenericBound 288 ( 4.0%) 4 72 +ast-stats-2 - Trait 288 ( 4.0%) 4 ast-stats-2 AssocItem 352 ( 4.9%) 4 88 ast-stats-2 - Type 176 ( 2.5%) 2 ast-stats-2 - Fn 176 ( 2.5%) 2 ast-stats-2 GenericParam 480 ( 6.7%) 5 96 -ast-stats-2 Pat 504 ( 7.1%) 7 72 +ast-stats-2 Pat 504 ( 7.0%) 7 72 ast-stats-2 - Struct 72 ( 1.0%) 1 ast-stats-2 - Wild 72 ( 1.0%) 1 -ast-stats-2 - Ident 360 ( 5.1%) 5 +ast-stats-2 - Ident 360 ( 5.0%) 5 ast-stats-2 Expr 648 ( 9.1%) 9 72 ast-stats-2 - Path 72 ( 1.0%) 1 ast-stats-2 - Match 72 ( 1.0%) 1 @@ -99,12 +99,12 @@ ast-stats-2 - InlineAsm 72 ( 1.0%) 1 ast-stats-2 - Lit 144 ( 2.0%) 2 ast-stats-2 - Block 216 ( 3.0%) 3 ast-stats-2 PathSegment 792 (11.1%) 33 24 -ast-stats-2 Ty 896 (12.6%) 14 64 +ast-stats-2 Ty 896 (12.5%) 14 64 ast-stats-2 - Ptr 64 ( 0.9%) 1 ast-stats-2 - Ref 64 ( 0.9%) 1 ast-stats-2 - ImplicitSelf 128 ( 1.8%) 2 -ast-stats-2 - Path 640 ( 9.0%) 10 -ast-stats-2 Item 1_496 (21.0%) 11 136 +ast-stats-2 - Path 640 ( 8.9%) 10 +ast-stats-2 Item 1_496 (20.9%) 11 136 ast-stats-2 - Trait 136 ( 1.9%) 1 ast-stats-2 - Enum 136 ( 1.9%) 1 ast-stats-2 - ExternCrate 136 ( 1.9%) 1 @@ -113,7 +113,7 @@ ast-stats-2 - Impl 136 ( 1.9%) 1 ast-stats-2 - Fn 272 ( 3.8%) 2 ast-stats-2 - Use 544 ( 7.6%) 4 ast-stats-2 ---------------------------------------------------------------- -ast-stats-2 Total 7_120 +ast-stats-2 Total 7_152 ast-stats-2 hir-stats HIR STATS hir-stats Name Accumulated Size Count Item Size diff --git a/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr b/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr index c0f0c414227..cabaa76a886 100644 --- a/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr +++ b/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr @@ -2,7 +2,14 @@ error[E0223]: ambiguous associated type --> $DIR/suggest-trait-in-ufcs-in-hrtb.rs:5:38 | LL | impl<S> Foo for Bar<S> where for<'a> <&'a S>::Item: Foo {} - | ^^^^^^^^^^^^^ help: use fully-qualified syntax: `<&'a S as IntoIterator>::Item` + | ^^^^^^^^^^^^^ + | +help: use fully-qualified syntax + | +LL | impl<S> Foo for Bar<S> where for<'a> <&'a S as IntoAsyncIterator>::Item: Foo {} + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | impl<S> Foo for Bar<S> where for<'a> <&'a S as IntoIterator>::Item: Foo {} + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/track-diagnostics/track.rs b/tests/ui/track-diagnostics/track.rs index 97bd7789a63..08f926610d7 100644 --- a/tests/ui/track-diagnostics/track.rs +++ b/tests/ui/track-diagnostics/track.rs @@ -1,5 +1,7 @@ // compile-flags: -Z track-diagnostics // error-pattern: created at +// rustc-env:RUST_BACKTRACE=0 +// failure-status: 101 // Normalize the emitted location so this doesn't need // updating everytime someone adds or removes a line. diff --git a/tests/ui/track-diagnostics/track.stderr b/tests/ui/track-diagnostics/track.stderr index 60254dc475b..54b1ea2764a 100644 --- a/tests/ui/track-diagnostics/track.stderr +++ b/tests/ui/track-diagnostics/track.stderr @@ -13,15 +13,31 @@ LL | break rust -Ztrack-diagnostics: created at compiler/rustc_passes/src/loops.rs:LL:CC error: internal compiler error: It looks like you're trying to break rust; would you like some ICE? + --> $DIR/track.rs:LL:CC + | +LL | break rust + | ^^^^^^^^^^ +-Ztrack-diagnostics: created at compiler/rustc_hir_typeck/src/lib.rs:LL:CC + | + = note: the compiler expectedly panicked. this is a feature. + = note: we would appreciate a joke overview: https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675 + = note: rustc $VERSION running on $TARGET + = note: compiler flags: ... -Z ui-testing ... -Z track-diagnostics -note: the compiler expectedly panicked. this is a feature. +thread 'rustc' panicked at compiler/rustc_hir_typeck/src/lib.rs:LL:CC: +Box<dyn Any> +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: we would appreciate a joke overview: https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675 +note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md note: rustc $VERSION running on $TARGET note: compiler flags: ... -Z ui-testing ... -Z track-diagnostics +query stack during panic: +#0 [typeck] type-checking `main` +#1 [analysis] running analysis passes on this crate +end of query stack error: aborting due to 3 previous errors Some errors have detailed explanations: E0268, E0425. diff --git a/tests/ui/typeck/issue-110052.stderr b/tests/ui/typeck/issue-110052.stderr index b25b6c0c0b7..5eb10d9a30e 100644 --- a/tests/ui/typeck/issue-110052.stderr +++ b/tests/ui/typeck/issue-110052.stderr @@ -2,7 +2,14 @@ error[E0223]: ambiguous associated type --> $DIR/issue-110052.rs:6:30 | LL | for<'iter> dyn Validator<<&'iter I>::Item>:, - | ^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<&'iter I as IntoIterator>::Item` + | ^^^^^^^^^^^^^^^^ + | +help: use fully-qualified syntax + | +LL | for<'iter> dyn Validator<<&'iter I as IntoAsyncIterator>::Item>:, + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | for<'iter> dyn Validator<<&'iter I as IntoIterator>::Item>:, + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: aborting due to 1 previous error diff --git a/triagebot.toml b/triagebot.toml index e4b104cdb86..27b174454b4 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -639,7 +639,7 @@ cc = ["@nnethercote"] [assign] warn_non_default_branch = true contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" -users_on_vacation = ["jyn514", "oli-obk"] +users_on_vacation = ["jyn514", "oli-obk", "spastorino"] [assign.adhoc_groups] compiler-team = [ |
