diff --git a/compiler/rustc_index/src/idx.rs b/compiler/rustc_index/src/idx.rs index b85160540d872..f8397d16a8ca9 100644 --- a/compiler/rustc_index/src/idx.rs +++ b/compiler/rustc_index/src/idx.rs @@ -43,3 +43,15 @@ impl Idx for u32 { self as usize } } + +impl Idx for u8 { + #[inline] + fn new(idx: usize) -> Self { + assert!(idx <= u8::MAX as usize); + idx as u8 + } + #[inline] + fn index(self) -> usize { + self as usize + } +} diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index c6d7b839e1970..3c7af142177e9 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -302,12 +302,12 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas // `check_foo` method in `$methods` within this pass simply calls `check_foo` // once per `$pass`. Compare with `declare_combined_late_lint_pass`, which is // similar, but combines lint passes at compile time. -struct RuntimeCombinedLateLintPass<'a, 'tcx> { - passes: &'a mut [LateLintPassObject<'tcx>], +struct RuntimeCombinedLateLintPass<'tcx> { + passes: Vec>, } #[allow(rustc::lint_pass_impl_without_macro)] -impl LintPass for RuntimeCombinedLateLintPass<'_, '_> { +impl LintPass for RuntimeCombinedLateLintPass<'_> { fn name(&self) -> &'static str { panic!() } @@ -318,7 +318,7 @@ impl LintPass for RuntimeCombinedLateLintPass<'_, '_> { macro_rules! impl_late_lint_pass { ([], [$($(#[$attr:meta])* fn $f:ident($($param:ident: $arg:ty),*);)*]) => { - impl<'tcx> LateLintPass<'tcx> for RuntimeCombinedLateLintPass<'_, 'tcx> { + impl<'tcx> LateLintPass<'tcx> for RuntimeCombinedLateLintPass<'tcx> { $(fn $f(&mut self, context: &LateContext<'tcx>, $($param: $arg),*) { for pass in self.passes.iter_mut() { pass.$f(context, $($param),*); @@ -355,14 +355,14 @@ pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>( late_lint_mod_inner(tcx, module_def_id, context, builtin_lints); } else { let builtin_lints = Box::new(builtin_lints) as Box>; - let mut binding = store + let passes = store .late_module_passes .iter() .map(|mk_pass| (mk_pass)(tcx)) .chain(std::iter::once(builtin_lints)) .collect::>(); - let pass = RuntimeCombinedLateLintPass { passes: binding.as_mut_slice() }; + let pass = RuntimeCombinedLateLintPass { passes }; late_lint_mod_inner(tcx, module_def_id, context, pass); } } @@ -393,10 +393,10 @@ fn late_lint_mod_inner<'tcx, T: LateLintPass<'tcx>>( fn late_lint_crate<'tcx>(tcx: TyCtxt<'tcx>) { // Note: `passes` is often empty. - let passes: Vec<_> = + let unfiltered_passes: Vec<_> = unerased_lint_store(tcx.sess).late_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect(); - if passes.is_empty() { + if unfiltered_passes.is_empty() { return; } @@ -413,7 +413,7 @@ fn late_lint_crate<'tcx>(tcx: TyCtxt<'tcx>) { let lints_that_dont_need_to_run = tcx.lints_that_dont_need_to_run(()); - let mut filtered_passes: Vec>> = passes + let mut passes: Vec>> = unfiltered_passes .into_iter() .filter(|pass| { let lints = (**pass).get_lints(); @@ -424,8 +424,8 @@ fn late_lint_crate<'tcx>(tcx: TyCtxt<'tcx>) { }) .collect(); - filtered_passes.push(Box::new(HardwiredLints)); - let pass = RuntimeCombinedLateLintPass { passes: &mut filtered_passes[..] }; + passes.push(Box::new(HardwiredLints)); + let pass = RuntimeCombinedLateLintPass { passes }; late_lint_crate_inner(tcx, context, pass); } diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 83a168c3f4462..f8576076057be 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -30,6 +30,7 @@ #![feature(if_let_guard)] #![feature(iter_order_by)] #![feature(let_chains)] +#![feature(macro_metavar_expr)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] #![feature(trait_upcasting)] @@ -146,7 +147,7 @@ pub fn provide(providers: &mut Providers) { } fn lint_mod(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { - late_lint_mod(tcx, module_def_id, BuiltinCombinedModuleLateLintPass::new()); + late_lint_mod(tcx, module_def_id, BuiltinCombinedModuleLateLintPass::new(tcx)); } early_lint_methods!( diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs index 8cc8f911d3a6d..556d20d6d820b 100644 --- a/compiler/rustc_lint/src/passes.rs +++ b/compiler/rustc_lint/src/passes.rs @@ -75,7 +75,11 @@ impl LateLintPass<'_> for HardwiredLints {} #[macro_export] macro_rules! expand_combined_late_lint_pass_method { ([$($pass:ident),*], $self: ident, $name: ident, $params:tt) => ({ - $($self.$pass.$name $params;)* + $( + if $self.enabled_passes.contains(EnabledPasses::$pass as u8) { + $self.$pass.$name $params; + } + )* }) } @@ -96,15 +100,37 @@ macro_rules! expand_combined_late_lint_pass_methods { #[macro_export] macro_rules! declare_combined_late_lint_pass { ([$v:vis $name:ident, [$($pass:ident: $constructor:expr,)*]], $methods:tt) => ( + #[repr(u8)] + enum EnabledPasses { + $($pass,)* + } + #[allow(non_snake_case)] $v struct $name { + enabled_passes: rustc_index::bit_set::DenseBitSet, $($pass: $pass,)* } impl $name { - $v fn new() -> Self { + #[allow(non_snake_case)] + $v fn new<'tcx>(tcx: TyCtxt<'tcx>) -> Self { + let mut enabled_passes = rustc_index::bit_set::DenseBitSet::new_filled(${count($pass)}); + let lints_that_dont_need_to_run = tcx.lints_that_dont_need_to_run(()); + $( + let $pass = $constructor; + { + let lints = $pass.get_lints(); + // If the pass doesn't have a single needed lint, omit it. + if !lints.is_empty() + && lints.iter().all(|lint| lints_that_dont_need_to_run.contains(&LintId::of(lint))) + { + enabled_passes.remove(EnabledPasses::$pass as u8); + } + } + )* Self { - $($pass: $constructor,)* + enabled_passes, + $($pass,)* } } diff --git a/tests/ui/print_type_sizes/multiple_types.rs b/tests/ui/print_type_sizes/multiple_types.rs index bbb16687f6a89..e9e9cf44c54e6 100644 --- a/tests/ui/print_type_sizes/multiple_types.rs +++ b/tests/ui/print_type_sizes/multiple_types.rs @@ -11,3 +11,8 @@ pub enum Enum { Small(SevenBytes), Large(FiftyBytes), } + +fn main() { + let x = Enum::Small(SevenBytes([0; 7])); + let x = Enum::Large(FiftyBytes([0; 50])); +} diff --git a/tests/ui/print_type_sizes/padding.rs b/tests/ui/print_type_sizes/padding.rs index 81a5c78631026..86f3d6247c9fe 100644 --- a/tests/ui/print_type_sizes/padding.rs +++ b/tests/ui/print_type_sizes/padding.rs @@ -26,3 +26,9 @@ enum E2 { A(i8, i32), B(S), } + +fn main() { + let s = S { a: true, b: true, g: 0 }; + let e1 = E1::A(0, 0); + let e2 = E2::A(0, 0); +} diff --git a/tests/ui/print_type_sizes/repr-align.rs b/tests/ui/print_type_sizes/repr-align.rs index 1b9a22dcef7af..85def7491581e 100644 --- a/tests/ui/print_type_sizes/repr-align.rs +++ b/tests/ui/print_type_sizes/repr-align.rs @@ -30,3 +30,14 @@ pub struct S { c: A, d: i8, } + +fn main() { + let s = S { + a: 0, + b: 0, + c: A(0), + d: 0, + }; + + let e = E::A(0); +} diff --git a/tests/ui/print_type_sizes/repr_int_c.rs b/tests/ui/print_type_sizes/repr_int_c.rs index f82dfcb7cfc54..44baac8986f70 100644 --- a/tests/ui/print_type_sizes/repr_int_c.rs +++ b/tests/ui/print_type_sizes/repr_int_c.rs @@ -17,3 +17,8 @@ enum Repru8 { A(u16), B, } + +fn main() { + let c = ReprCu8::A(0); + let r = Repru8::A(0); +} diff --git a/tests/ui/print_type_sizes/variants.rs b/tests/ui/print_type_sizes/variants.rs index 0d0e8a0773bb2..888e7e81b9186 100644 --- a/tests/ui/print_type_sizes/variants.rs +++ b/tests/ui/print_type_sizes/variants.rs @@ -16,3 +16,8 @@ pub enum Enum { Small(SevenBytes), Large(FiftyBytes), } + +fn main() { + let x = Enum::Small(SevenBytes([0; 7])); + let x = Enum::Large(FiftyBytes([0; 50])); +} diff --git a/tests/ui/traits/solver-cycles/129541-recursive-enum-and-array-impl.rs b/tests/ui/traits/solver-cycles/129541-recursive-enum-and-array-impl.rs deleted file mode 100644 index 197207dfb4be8..0000000000000 --- a/tests/ui/traits/solver-cycles/129541-recursive-enum-and-array-impl.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Regression test for #129541 -//~^ ERROR cycle detected when computing layout of `<[Hello] as Normalize>::Assoc` [E0391] - -trait Bound {} -trait Normalize { - type Assoc; -} - -impl Normalize for T { - type Assoc = T; -} - -impl Normalize for [T] { - type Assoc = T; -} - -impl Bound for Hello {} -enum Hello { - Variant(<[Hello] as Normalize>::Assoc), -} - -fn main() {} diff --git a/tests/ui/traits/solver-cycles/129541-recursive-enum-and-array-impl.stderr b/tests/ui/traits/solver-cycles/129541-recursive-enum-and-array-impl.stderr deleted file mode 100644 index 50dcea0bfac69..0000000000000 --- a/tests/ui/traits/solver-cycles/129541-recursive-enum-and-array-impl.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error[E0391]: cycle detected when computing layout of `<[Hello] as Normalize>::Assoc` - | - = note: ...which requires computing layout of `Hello`... - = note: ...which again requires computing layout of `<[Hello] as Normalize>::Assoc`, completing the cycle - = note: cycle used when computing layout of `Hello` - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0391`.