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
13 changed files with 133 additions and 41 deletions
|
@ -137,8 +137,8 @@ declare_features! (
|
||||||
/// Allows use of unary negate on unsigned integers, e.g., -e for e: u8
|
/// Allows use of unary negate on unsigned integers, e.g., -e for e: u8
|
||||||
(removed, negate_unsigned, "1.0.0", Some(29645), None, None),
|
(removed, negate_unsigned, "1.0.0", Some(29645), None, None),
|
||||||
/// Allows `#[no_coverage]` on functions.
|
/// Allows `#[no_coverage]` on functions.
|
||||||
/// The feature was renamed to `coverage` and the attribute to `#[coverage(on|off)]`
|
/// 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`")),
|
(removed, no_coverage, "CURRENT_RUSTC_VERSION", Some(84605), None, Some("renamed to `coverage_attribute`")),
|
||||||
/// Allows `#[no_debug]`.
|
/// Allows `#[no_debug]`.
|
||||||
(removed, no_debug, "1.43.0", Some(29721), None, Some("removed due to lack of demand")),
|
(removed, no_debug, "1.43.0", Some(29721), None, Some("removed due to lack of demand")),
|
||||||
/// Allows using `#[on_unimplemented(..)]` on traits.
|
/// Allows using `#[on_unimplemented(..)]` on traits.
|
||||||
|
|
|
@ -461,7 +461,15 @@ fn check_opaque_meets_bounds<'tcx>(
|
||||||
}
|
}
|
||||||
match origin {
|
match origin {
|
||||||
// Checked when type checking the function containing them.
|
// 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:
|
// Nested opaque types occur only in associated types:
|
||||||
// ` type Opaque<T> = impl Trait<&'static T, AssocTy = impl Nested>; `
|
// ` type Opaque<T> = impl Trait<&'static T, AssocTy = impl Nested>; `
|
||||||
// They can only be referenced as `<Opaque<T> as Trait<&'static T>>::AssocTy`.
|
// They can only be referenced as `<Opaque<T> as Trait<&'static T>>::AssocTy`.
|
||||||
|
|
|
@ -34,6 +34,26 @@ impl FlagComputation {
|
||||||
result.flags
|
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) {
|
fn add_flags(&mut self, flags: TypeFlags) {
|
||||||
self.flags = self.flags | flags;
|
self.flags = self.flags | flags;
|
||||||
}
|
}
|
||||||
|
@ -57,21 +77,7 @@ impl FlagComputation {
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut Self, T),
|
F: FnOnce(&mut Self, T),
|
||||||
{
|
{
|
||||||
let mut computation = FlagComputation::new();
|
let mut computation = FlagComputation::bound_var_flags(value.bound_vars());
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
f(&mut computation, value.skip_binder());
|
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
|
// `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
|
// 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.
|
// 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 {
|
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasTypeFlagsVisitor {
|
||||||
type BreakTy = FoundFlags;
|
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]
|
#[inline]
|
||||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||||
// Note: no `super_visit_with` call.
|
// Note: no `super_visit_with` call.
|
||||||
|
|
|
@ -17,6 +17,7 @@ use rustc_interface::{interface, Queries};
|
||||||
use rustc_middle::mir::interpret::AllocId;
|
use rustc_middle::mir::interpret::AllocId;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
pub use rustc_span::def_id::{CrateNum, DefId};
|
pub use rustc_span::def_id::{CrateNum, DefId};
|
||||||
|
use rustc_span::Span;
|
||||||
|
|
||||||
fn with_tables<R>(mut f: impl FnMut(&mut Tables<'_>) -> R) -> R {
|
fn with_tables<R>(mut f: impl FnMut(&mut Tables<'_>) -> R) -> R {
|
||||||
let mut ret = None;
|
let mut ret = None;
|
||||||
|
@ -159,6 +160,17 @@ impl<'tcx> Tables<'tcx> {
|
||||||
self.alloc_ids.push(aid);
|
self.alloc_ids.push(aid);
|
||||||
stable_mir::AllocId(id)
|
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 {
|
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()) {
|
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.
|
/// 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::rustc_internal::{self, opaque};
|
||||||
use crate::stable_mir::mir::{CopyNonOverlapping, UserTypeProjection, VariantIdx};
|
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 crate::stable_mir::{self, CompilerError, Context};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_middle::mir::interpret::{alloc_range, AllocId};
|
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])
|
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)
|
self.tcx.def_span(self[def_id]).stable(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,6 +187,7 @@ pub struct Tables<'tcx> {
|
||||||
pub tcx: TyCtxt<'tcx>,
|
pub tcx: TyCtxt<'tcx>,
|
||||||
pub def_ids: Vec<DefId>,
|
pub def_ids: Vec<DefId>,
|
||||||
pub alloc_ids: Vec<AllocId>,
|
pub alloc_ids: Vec<AllocId>,
|
||||||
|
pub spans: Vec<rustc_span::Span>,
|
||||||
pub types: Vec<MaybeStable<stable_mir::ty::TyKind, Ty<'tcx>>>,
|
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 {
|
impl<'tcx> Stable<'tcx> for rustc_span::Span {
|
||||||
type T = stable_mir::ty::Span;
|
type T = stable_mir::ty::Span;
|
||||||
|
|
||||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
// FIXME: add a real implementation of stable spans
|
tables.create_span(*self)
|
||||||
opaque(self)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,7 @@ impl CrateItem {
|
||||||
with(|cx| cx.mir_body(self.0))
|
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))
|
with(|cx| cx.span_of_an_item(self.0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,16 @@ pub struct Const {
|
||||||
|
|
||||||
type Ident = Opaque;
|
type Ident = Opaque;
|
||||||
pub(crate) type Region = 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)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum TyKind {
|
pub enum TyKind {
|
||||||
|
|
|
@ -4,7 +4,7 @@ error[E0557]: feature has been removed
|
||||||
LL | #![feature(no_coverage)]
|
LL | #![feature(no_coverage)]
|
||||||
| ^^^^^^^^^^^ feature has been removed
|
| ^^^^^^^^^^^ feature has been removed
|
||||||
|
|
|
|
||||||
= note: renamed to `coverage`
|
= note: renamed to `coverage_attribute`
|
||||||
|
|
||||||
error[E0658]: the `#[coverage]` attribute is an experimental feature
|
error[E0658]: the `#[coverage]` attribute is an experimental feature
|
||||||
--> $DIR/feature-gate-coverage-attribute.rs:10:1
|
--> $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
|
//~^ ERROR captures lifetime that does not appear in bounds
|
||||||
|
|
||||||
type WithLt<'a> = impl Sized + 'a;
|
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>> {}
|
fn with_lt() -> impl for<'a> Trait<'a, Assoc = WithLt<'a>> {}
|
||||||
//~^ ERROR expected generic lifetime parameter, found `'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>> {}
|
LL | fn with_lt() -> impl for<'a> Trait<'a, Assoc = WithLt<'a>> {}
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error: concrete type differs from previous defining opaque type use
|
error: aborting due to 2 previous errors
|
||||||
--> $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
|
|
||||||
|
|
||||||
Some errors have detailed explanations: E0700, E0792.
|
Some errors have detailed explanations: E0700, E0792.
|
||||||
For more information about an error, try `rustc --explain E0700`.
|
For more information about an error, try `rustc --explain E0700`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue