diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index c70e8e3e6b1ec..da18cb2a239e8 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -137,8 +137,8 @@ declare_features! ( /// Allows use of unary negate on unsigned integers, e.g., -e for e: u8 (removed, negate_unsigned, "1.0.0", Some(29645), None, None), /// Allows `#[no_coverage]` on functions. - /// The feature was renamed to `coverage` and the attribute to `#[coverage(on|off)]` - (removed, no_coverage, "CURRENT_RUSTC_VERSION", Some(84605), None, Some("renamed to `coverage`")), + /// The feature was renamed to `coverage_attribute` and the attribute to `#[coverage(on|off)]` + (removed, no_coverage, "CURRENT_RUSTC_VERSION", Some(84605), None, Some("renamed to `coverage_attribute`")), /// Allows `#[no_debug]`. (removed, no_debug, "1.43.0", Some(29721), None, Some("removed due to lack of demand")), /// Allows using `#[on_unimplemented(..)]` on traits. diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index c0cf1ea34cf2d..9a57cc6dbaba4 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -461,7 +461,15 @@ fn check_opaque_meets_bounds<'tcx>( } match origin { // Checked when type checking the function containing them. - hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {} + hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => { + // HACK: this should also fall through to the hidden type check below, but the original + // implementation had a bug where equivalent lifetimes are not identical. This caused us + // to reject existing stable code that is otherwise completely fine. The real fix is to + // compare the hidden types via our type equivalence/relation infra instead of doing an + // identity check. + let _ = infcx.take_opaque_types(); + return Ok(()); + } // Nested opaque types occur only in associated types: // ` type Opaque = impl Trait<&'static T, AssocTy = impl Nested>; ` // They can only be referenced as ` as Trait<&'static T>>::AssocTy`. diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 3cafd9a8da913..231635c086e3b 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -34,6 +34,26 @@ impl FlagComputation { result.flags } + pub fn bound_var_flags(vars: &ty::List) -> FlagComputation { + let mut computation = FlagComputation::new(); + + for bv in vars { + match bv { + ty::BoundVariableKind::Ty(_) => { + computation.flags |= TypeFlags::HAS_TY_LATE_BOUND; + } + ty::BoundVariableKind::Region(_) => { + computation.flags |= TypeFlags::HAS_RE_LATE_BOUND; + } + ty::BoundVariableKind::Const => { + computation.flags |= TypeFlags::HAS_CT_LATE_BOUND; + } + } + } + + computation + } + fn add_flags(&mut self, flags: TypeFlags) { self.flags = self.flags | flags; } @@ -57,21 +77,7 @@ impl FlagComputation { where F: FnOnce(&mut Self, T), { - let mut computation = FlagComputation::new(); - - for bv in value.bound_vars() { - match bv { - ty::BoundVariableKind::Ty(_) => { - computation.flags |= TypeFlags::HAS_TY_LATE_BOUND; - } - ty::BoundVariableKind::Region(_) => { - computation.flags |= TypeFlags::HAS_RE_LATE_BOUND; - } - ty::BoundVariableKind::Const => { - computation.flags |= TypeFlags::HAS_CT_LATE_BOUND; - } - } - } + let mut computation = FlagComputation::bound_var_flags(value.bound_vars()); f(&mut computation, value.skip_binder()); diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index fb760654ea785..5deb5bfb19ee4 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -481,9 +481,33 @@ impl std::fmt::Debug for HasTypeFlagsVisitor { // `Ty`/`Const`/`Predicate`, but not within those types. This is because the // type flags at the outer layer are enough. So it's faster than it first // looks, particular for `Ty`/`Predicate` where it's just a field access. +// +// N.B. The only case where this isn't totally true is binders, which also +// add `HAS_{RE,TY,CT}_LATE_BOUND` flag depending on the *bound variables* that +// are present, regardless of whether those bound variables are used. This +// is important for anonymization of binders in `TyCtxt::erase_regions`. We +// specifically detect this case in `visit_binder`. impl<'tcx> TypeVisitor> for HasTypeFlagsVisitor { type BreakTy = FoundFlags; + fn visit_binder>>( + &mut self, + t: &Binder<'tcx, T>, + ) -> ControlFlow { + // If we're looking for any of the HAS_*_LATE_BOUND flags, we need to + // additionally consider the bound vars on the binder itself, even if + // the contents of a the binder (e.g. a `TraitRef`) doesn't reference + // the bound vars. + if self.flags.intersects(TypeFlags::HAS_LATE_BOUND) { + let bound_var_flags = FlagComputation::bound_var_flags(t.bound_vars()); + if bound_var_flags.flags.intersects(self.flags) { + return ControlFlow::Break(FoundFlags); + } + } + + t.super_visit_with(self) + } + #[inline] fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { // Note: no `super_visit_with` call. diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 4203990ab0560..10ee5af86c627 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -17,6 +17,7 @@ use rustc_interface::{interface, Queries}; use rustc_middle::mir::interpret::AllocId; use rustc_middle::ty::TyCtxt; pub use rustc_span::def_id::{CrateNum, DefId}; +use rustc_span::Span; fn with_tables(mut f: impl FnMut(&mut Tables<'_>) -> R) -> R { let mut ret = None; @@ -159,6 +160,17 @@ impl<'tcx> Tables<'tcx> { self.alloc_ids.push(aid); stable_mir::AllocId(id) } + + pub(crate) fn create_span(&mut self, span: Span) -> stable_mir::ty::Span { + for (i, &sp) in self.spans.iter().enumerate() { + if sp == span { + return stable_mir::ty::Span(i); + } + } + let id = self.spans.len(); + self.spans.push(span); + stable_mir::ty::Span(id) + } } pub fn crate_num(item: &stable_mir::Crate) -> CrateNum { @@ -166,7 +178,10 @@ pub fn crate_num(item: &stable_mir::Crate) -> CrateNum { } pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) { - crate::stable_mir::run(Tables { tcx, def_ids: vec![], alloc_ids: vec![], types: vec![] }, f); + crate::stable_mir::run( + Tables { tcx, def_ids: vec![], alloc_ids: vec![], spans: vec![], types: vec![] }, + f, + ); } /// A type that provides internal information but that can still be used for debug purpose. diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 141a3efe964e3..93b5b9654d35d 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -9,7 +9,9 @@ use crate::rustc_internal::{self, opaque}; use crate::stable_mir::mir::{CopyNonOverlapping, UserTypeProjection, VariantIdx}; -use crate::stable_mir::ty::{FloatTy, GenericParamDef, IntTy, Movability, RigidTy, TyKind, UintTy}; +use crate::stable_mir::ty::{ + FloatTy, GenericParamDef, IntTy, Movability, RigidTy, Span, TyKind, UintTy, +}; use crate::stable_mir::{self, CompilerError, Context}; use rustc_hir as hir; use rustc_middle::mir::interpret::{alloc_range, AllocId}; @@ -42,7 +44,7 @@ impl<'tcx> Context for Tables<'tcx> { self.tcx.def_path_str(self[def_id]) } - fn span_of_an_item(&mut self, def_id: stable_mir::DefId) -> stable_mir::ty::Span { + fn span_of_an_item(&mut self, def_id: stable_mir::DefId) -> Span { self.tcx.def_span(self[def_id]).stable(self) } @@ -185,6 +187,7 @@ pub struct Tables<'tcx> { pub tcx: TyCtxt<'tcx>, pub def_ids: Vec, pub alloc_ids: Vec, + pub spans: Vec, pub types: Vec>>, } @@ -1514,9 +1517,8 @@ impl<'tcx> Stable<'tcx> for ty::Region<'tcx> { impl<'tcx> Stable<'tcx> for rustc_span::Span { type T = stable_mir::ty::Span; - fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { - // FIXME: add a real implementation of stable spans - opaque(self) + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + tables.create_span(*self) } } diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/rustc_smir/src/stable_mir/mod.rs index ef5901482d884..3c86cb4038a0a 100644 --- a/compiler/rustc_smir/src/stable_mir/mod.rs +++ b/compiler/rustc_smir/src/stable_mir/mod.rs @@ -90,7 +90,7 @@ impl CrateItem { with(|cx| cx.mir_body(self.0)) } - pub fn span(&self) -> ty::Span { + pub fn span(&self) -> Span { with(|cx| cx.span_of_an_item(self.0)) } } diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index 76e7beac57175..3a8fc1a502e6d 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -35,7 +35,16 @@ pub struct Const { type Ident = Opaque; pub(crate) type Region = Opaque; -pub(crate) type Span = Opaque; +#[derive(Clone, Copy, PartialEq, Eq)] +pub struct Span(pub(crate) usize); + +impl Debug for Span { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + let mut span = None; + with(|context| context.rustc_tables(&mut |tables| span = Some(tables.spans[self.0]))); + f.write_fmt(format_args!("{:?}", &span.unwrap())) + } +} #[derive(Clone, Debug)] pub enum TyKind { diff --git a/tests/ui/feature-gates/feature-gate-coverage-attribute.stderr b/tests/ui/feature-gates/feature-gate-coverage-attribute.stderr index 3912b9834fe24..0131a19a39dde 100644 --- a/tests/ui/feature-gates/feature-gate-coverage-attribute.stderr +++ b/tests/ui/feature-gates/feature-gate-coverage-attribute.stderr @@ -4,7 +4,7 @@ error[E0557]: feature has been removed LL | #![feature(no_coverage)] | ^^^^^^^^^^^ feature has been removed | - = note: renamed to `coverage` + = note: renamed to `coverage_attribute` error[E0658]: the `#[coverage]` attribute is an experimental feature --> $DIR/feature-gate-coverage-attribute.rs:10:1 diff --git a/tests/ui/impl-trait/lifetime-ambiguity-regression.rs b/tests/ui/impl-trait/lifetime-ambiguity-regression.rs new file mode 100644 index 0000000000000..ce6ae3786e164 --- /dev/null +++ b/tests/ui/impl-trait/lifetime-ambiguity-regression.rs @@ -0,0 +1,13 @@ +//! This test shows a situation where through subtle compiler changes we can +//! suddenly infer a different lifetime in the hidden type, and thus not meet +//! the opaque type bounds anymore. In this case `'a` and `'b` are equal, so +//! picking either is fine, but then we'll fail an identity check of the hidden +//! type and the expected hidden type. + +// check-pass + +fn test<'a: 'b, 'b: 'a>() -> impl IntoIterator)> { + None::<(_, (_, _))> +} + +fn main() {} diff --git a/tests/ui/lifetimes/anonymize-unnamed-bound-vars-in-binders.rs b/tests/ui/lifetimes/anonymize-unnamed-bound-vars-in-binders.rs new file mode 100644 index 0000000000000..05e3763e9d103 --- /dev/null +++ b/tests/ui/lifetimes/anonymize-unnamed-bound-vars-in-binders.rs @@ -0,0 +1,27 @@ +// build-pass +// issue: #115807 + +trait Chip: for<'a> TraitWithLifetime<'a> + SomeMarker { + fn compute(&self); +} + +trait SomeMarker {} + +trait TraitWithLifetime<'a>: SomeMarker {} + +trait Machine { + fn run(); +} + +struct BasicMachine; + +impl Machine for BasicMachine { + fn run() { + let chips: [&dyn Chip; 0] = []; + let _ = chips.map(|chip| chip.compute()); + } +} + +fn main() { + BasicMachine::run(); +} diff --git a/tests/ui/type-alias-impl-trait/nested-tait-hrtb.rs b/tests/ui/type-alias-impl-trait/nested-tait-hrtb.rs index 4a9631a720887..ba705d6f85ac7 100644 --- a/tests/ui/type-alias-impl-trait/nested-tait-hrtb.rs +++ b/tests/ui/type-alias-impl-trait/nested-tait-hrtb.rs @@ -8,7 +8,7 @@ fn without_lt() -> impl for<'a> Trait<'a, Assoc = WithoutLt> {} //~^ ERROR captures lifetime that does not appear in bounds type WithLt<'a> = impl Sized + 'a; -//~^ ERROR concrete type differs from previous defining opaque type use + fn with_lt() -> impl for<'a> Trait<'a, Assoc = WithLt<'a>> {} //~^ ERROR expected generic lifetime parameter, found `'a` diff --git a/tests/ui/type-alias-impl-trait/nested-tait-hrtb.stderr b/tests/ui/type-alias-impl-trait/nested-tait-hrtb.stderr index 9a783a6d92a2c..f208730552d90 100644 --- a/tests/ui/type-alias-impl-trait/nested-tait-hrtb.stderr +++ b/tests/ui/type-alias-impl-trait/nested-tait-hrtb.stderr @@ -17,19 +17,7 @@ LL | LL | fn with_lt() -> impl for<'a> Trait<'a, Assoc = WithLt<'a>> {} | ^^ -error: concrete type differs from previous defining opaque type use - --> $DIR/nested-tait-hrtb.rs:10:19 - | -LL | type WithLt<'a> = impl Sized + 'a; - | ^^^^^^^^^^^^^^^ expected `&'a str`, got `{type error}` - | -note: previous use here - --> $DIR/nested-tait-hrtb.rs:12:17 - | -LL | fn with_lt() -> impl for<'a> Trait<'a, Assoc = WithLt<'a>> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0700, E0792. For more information about an error, try `rustc --explain E0700`.