Auto merge of #115848 - matthiaskrgr:rollup-lsul9dz, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - #115772 (Improve Span in smir) - #115832 (Fix the error message for `#![feature(no_coverage)]`) - #115834 (Properly consider binder vars in `HasTypeFlagsVisitor`) - #115844 (Paper over an accidental regression) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
ccf817b9bb
compiler
rustc_feature/src
rustc_hir_analysis/src/check
rustc_middle/src/ty
rustc_smir/src
tests/ui
feature-gates
impl-trait
lifetimes
type-alias-impl-trait
@ -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.
|
||||
|
@ -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<T> = impl Trait<&'static T, AssocTy = impl Nested>; `
|
||||
// They can only be referenced as `<Opaque<T> as Trait<&'static T>>::AssocTy`.
|
||||
|
@ -34,6 +34,26 @@ impl FlagComputation {
|
||||
result.flags
|
||||
}
|
||||
|
||||
pub fn bound_var_flags(vars: &ty::List<ty::BoundVariableKind>) -> 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());
|
||||
|
||||
|
@ -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<TyCtxt<'tcx>> for HasTypeFlagsVisitor {
|
||||
type BreakTy = FoundFlags;
|
||||
|
||||
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
|
||||
&mut self,
|
||||
t: &Binder<'tcx, T>,
|
||||
) -> ControlFlow<Self::BreakTy> {
|
||||
// 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<Self::BreakTy> {
|
||||
// Note: no `super_visit_with` call.
|
||||
|
@ -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<R>(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.
|
||||
|
@ -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<DefId>,
|
||||
pub alloc_ids: Vec<AllocId>,
|
||||
pub spans: Vec<rustc_span::Span>,
|
||||
pub types: Vec<MaybeStable<stable_mir::ty::TyKind, Ty<'tcx>>>,
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
13
tests/ui/impl-trait/lifetime-ambiguity-regression.rs
Normal file
13
tests/ui/impl-trait/lifetime-ambiguity-regression.rs
Normal file
@ -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<Item = (&'a u8, impl Into<(&'b u8, &'a u8)>)> {
|
||||
None::<(_, (_, _))>
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -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();
|
||||
}
|
@ -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`
|
||||
|
||||
|
@ -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`.
|
||||
|
Loading…
x
Reference in New Issue
Block a user