Skip to content

Rollup of 6 pull requests #139499

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 13 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -406,8 +406,8 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
// started MIR borrowchecking with, so the region
// constraints have already been taken. Use the data from
// our `mbcx` instead.
|vid| mbcx.regioncx.var_infos[vid].origin,
|vid| mbcx.regioncx.var_infos[vid].universe,
|vid| RegionVariableOrigin::Nll(mbcx.regioncx.definitions[vid].origin),
|vid| mbcx.regioncx.definitions[vid].universe,
)
}
}
Expand Down
9 changes: 3 additions & 6 deletions compiler/rustc_borrowck/src/diagnostics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ use rustc_errors::{Applicability, Diag, EmissionGuarantee, MultiSpan, listify};
use rustc_hir::def::{CtorKind, Namespace};
use rustc_hir::{self as hir, CoroutineKind, LangItem};
use rustc_index::IndexSlice;
use rustc_infer::infer::{
BoundRegionConversionTime, NllRegionVariableOrigin, RegionVariableOrigin,
};
use rustc_infer::infer::{BoundRegionConversionTime, NllRegionVariableOrigin};
use rustc_infer::traits::SelectionError;
use rustc_middle::bug;
use rustc_middle::mir::{
Expand Down Expand Up @@ -633,9 +631,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
) {
let predicate_span = path.iter().find_map(|constraint| {
let outlived = constraint.sub;
if let Some(origin) = self.regioncx.var_infos.get(outlived)
&& let RegionVariableOrigin::Nll(NllRegionVariableOrigin::Placeholder(_)) =
origin.origin
if let Some(origin) = self.regioncx.definitions.get(outlived)
&& let NllRegionVariableOrigin::Placeholder(_) = origin.origin
&& let ConstraintCategory::Predicate(span) = constraint.category
{
Some(span)
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/polonius/dump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ fn emit_mermaid_nll_regions<'tcx>(
writeln!(out, "flowchart TD")?;

// Emit the region nodes.
for region in regioncx.var_infos.indices() {
for region in regioncx.definitions.indices() {
write!(out, "{}[\"", region.as_usize())?;
render_region(region, regioncx, out)?;
writeln!(out, "\"]")?;
Expand Down Expand Up @@ -387,7 +387,7 @@ fn emit_mermaid_nll_sccs<'tcx>(
// Gather and emit the SCC nodes.
let mut nodes_per_scc: IndexVec<_, _> =
regioncx.constraint_sccs().all_sccs().map(|_| Vec::new()).collect();
for region in regioncx.var_infos.indices() {
for region in regioncx.definitions.indices() {
let scc = regioncx.constraint_sccs().scc(region);
nodes_per_scc[scc].push(region);
}
Expand Down
5 changes: 1 addition & 4 deletions compiler/rustc_borrowck/src/region_infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,13 +139,11 @@ impl RegionTracker {
}

pub struct RegionInferenceContext<'tcx> {
pub var_infos: VarInfos,

/// Contains the definition for every region variable. Region
/// variables are identified by their index (`RegionVid`). The
/// definition contains information about where the region came
/// from as well as its final inferred value.
definitions: IndexVec<RegionVid, RegionDefinition<'tcx>>,
pub(crate) definitions: IndexVec<RegionVid, RegionDefinition<'tcx>>,

/// The liveness constraints added to each region. For most
/// regions, these start out empty and steadily grow, though for
Expand Down Expand Up @@ -453,7 +451,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
Rc::new(member_constraints.into_mapped(|r| constraint_sccs.scc(r)));

let mut result = Self {
var_infos,
definitions,
liveness_constraints,
constraints,
Expand Down
70 changes: 44 additions & 26 deletions compiler/rustc_errors/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,8 @@ struct DiagCtxtInner {
/// add more information). All stashed diagnostics must be emitted with
/// `emit_stashed_diagnostics` by the time the `DiagCtxtInner` is dropped,
/// otherwise an assertion failure will occur.
stashed_diagnostics: FxIndexMap<(Span, StashKey), (DiagInner, Option<ErrorGuaranteed>)>,
stashed_diagnostics:
FxIndexMap<StashKey, FxIndexMap<Span, (DiagInner, Option<ErrorGuaranteed>)>>,

future_breakage_diagnostics: Vec<DiagInner>,

Expand Down Expand Up @@ -912,8 +913,12 @@ impl<'a> DiagCtxtHandle<'a> {
// FIXME(Centril, #69537): Consider reintroducing panic on overwriting a stashed diagnostic
// if/when we have a more robust macro-friendly replacement for `(span, key)` as a key.
// See the PR for a discussion.
let key = (span.with_parent(None), key);
self.inner.borrow_mut().stashed_diagnostics.insert(key, (diag, guar));
self.inner
.borrow_mut()
.stashed_diagnostics
.entry(key)
.or_default()
.insert(span.with_parent(None), (diag, guar));

guar
}
Expand All @@ -922,9 +927,10 @@ impl<'a> DiagCtxtHandle<'a> {
/// and [`StashKey`] as the key. Panics if the found diagnostic is an
/// error.
pub fn steal_non_err(self, span: Span, key: StashKey) -> Option<Diag<'a, ()>> {
let key = (span.with_parent(None), key);
// FIXME(#120456) - is `swap_remove` correct?
let (diag, guar) = self.inner.borrow_mut().stashed_diagnostics.swap_remove(&key)?;
let (diag, guar) = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then(
|stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)),
)?;
assert!(!diag.is_error());
assert!(guar.is_none());
Some(Diag::new_diagnostic(self, diag))
Expand All @@ -943,9 +949,10 @@ impl<'a> DiagCtxtHandle<'a> {
where
F: FnMut(&mut Diag<'_>),
{
let key = (span.with_parent(None), key);
// FIXME(#120456) - is `swap_remove` correct?
let err = self.inner.borrow_mut().stashed_diagnostics.swap_remove(&key);
let err = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then(
|stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)),
);
err.map(|(err, guar)| {
// The use of `::<ErrorGuaranteed>` is safe because level is `Level::Error`.
assert_eq!(err.level, Error);
Expand All @@ -966,9 +973,10 @@ impl<'a> DiagCtxtHandle<'a> {
key: StashKey,
new_err: Diag<'_>,
) -> ErrorGuaranteed {
let key = (span.with_parent(None), key);
// FIXME(#120456) - is `swap_remove` correct?
let old_err = self.inner.borrow_mut().stashed_diagnostics.swap_remove(&key);
let old_err = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then(
|stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)),
);
match old_err {
Some((old_err, guar)) => {
assert_eq!(old_err.level, Error);
Expand All @@ -983,7 +991,14 @@ impl<'a> DiagCtxtHandle<'a> {
}

pub fn has_stashed_diagnostic(&self, span: Span, key: StashKey) -> bool {
self.inner.borrow().stashed_diagnostics.get(&(span.with_parent(None), key)).is_some()
let inner = self.inner.borrow();
if let Some(stashed_diagnostics) = inner.stashed_diagnostics.get(&key)
&& !stashed_diagnostics.is_empty()
{
stashed_diagnostics.contains_key(&span.with_parent(None))
} else {
false
}
}

/// Emit all stashed diagnostics.
Expand All @@ -997,7 +1012,11 @@ impl<'a> DiagCtxtHandle<'a> {
let inner = self.inner.borrow();
inner.err_guars.len()
+ inner.lint_err_guars.len()
+ inner.stashed_diagnostics.values().filter(|(_diag, guar)| guar.is_some()).count()
+ inner
.stashed_diagnostics
.values()
.map(|a| a.values().filter(|(_, guar)| guar.is_some()).count())
.sum::<usize>()
}

/// This excludes lint errors and delayed bugs. Unless absolutely
Expand Down Expand Up @@ -1486,16 +1505,18 @@ impl DiagCtxtInner {
fn emit_stashed_diagnostics(&mut self) -> Option<ErrorGuaranteed> {
let mut guar = None;
let has_errors = !self.err_guars.is_empty();
for (_, (diag, _guar)) in std::mem::take(&mut self.stashed_diagnostics).into_iter() {
if !diag.is_error() {
// Unless they're forced, don't flush stashed warnings when
// there are errors, to avoid causing warning overload. The
// stash would've been stolen already if it were important.
if !diag.is_force_warn() && has_errors {
continue;
for (_, stashed_diagnostics) in std::mem::take(&mut self.stashed_diagnostics).into_iter() {
for (_, (diag, _guar)) in stashed_diagnostics {
if !diag.is_error() {
// Unless they're forced, don't flush stashed warnings when
// there are errors, to avoid causing warning overload. The
// stash would've been stolen already if it were important.
if !diag.is_force_warn() && has_errors {
continue;
}
}
guar = guar.or(self.emit_diagnostic(diag, None));
}
guar = guar.or(self.emit_diagnostic(diag, None));
}
guar
}
Expand Down Expand Up @@ -1688,6 +1709,7 @@ impl DiagCtxtInner {
if let Some((_diag, guar)) = self
.stashed_diagnostics
.values()
.flat_map(|stashed_diagnostics| stashed_diagnostics.values())
.find(|(diag, guar)| guar.is_some() && diag.is_lint.is_none())
{
*guar
Expand All @@ -1700,13 +1722,9 @@ impl DiagCtxtInner {
fn has_errors(&self) -> Option<ErrorGuaranteed> {
self.err_guars.get(0).copied().or_else(|| self.lint_err_guars.get(0).copied()).or_else(
|| {
if let Some((_diag, guar)) =
self.stashed_diagnostics.values().find(|(_diag, guar)| guar.is_some())
{
*guar
} else {
None
}
self.stashed_diagnostics.values().find_map(|stashed_diagnostics| {
stashed_diagnostics.values().find_map(|(_, guar)| *guar)
})
},
)
}
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_hir_analysis/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,9 @@ hir_analysis_self_in_impl_self =
`Self` is not valid in the self type of an impl block
.note = replace `Self` with a different type

hir_analysis_self_in_type_alias = `Self` is not allowed in type aliases
.label = `Self` is only available in impls, traits, and concrete type definitions

hir_analysis_self_ty_not_captured = `impl Trait` must mention the `Self` type of the trait in `use<...>`
.label = `Self` type parameter is implicitly captured by this `impl Trait`
.note = currently, all type parameters are required to be mentioned in the precise captures list
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_hir_analysis/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1707,3 +1707,11 @@ pub(crate) enum SupertraitItemShadowee {
traits: DiagSymbolList,
},
}

#[derive(Diagnostic)]
#[diag(hir_analysis_self_in_type_alias, code = E0411)]
pub(crate) struct SelfInTypeAlias {
#[primary_span]
#[label]
pub span: Span,
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use smallvec::{SmallVec, smallvec};
use tracing::{debug, instrument};

use super::HirTyLowerer;
use crate::errors::SelfInTypeAlias;
use crate::hir_ty_lowering::{
GenericArgCountMismatch, GenericArgCountResult, PredicateFilter, RegionInferReason,
};
Expand Down Expand Up @@ -125,6 +126,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// ```
let mut projection_bounds = FxIndexMap::default();
for (proj, proj_span) in elaborated_projection_bounds {
let proj = proj.map_bound(|mut b| {
if let Some(term_ty) = &b.term.as_type() {
let references_self = term_ty.walk().any(|arg| arg == dummy_self.into());
if references_self {
// With trait alias and type alias combined, type resolver
// may not be able to catch all illegal `Self` usages (issue 139082)
let guar = tcx.dcx().emit_err(SelfInTypeAlias { span });
b.term = replace_dummy_self_with_error(tcx, b.term, guar);
}
}
b
});

let key = (
proj.skip_binder().projection_term.def_id,
tcx.anonymize_bound_vars(
Expand Down
11 changes: 10 additions & 1 deletion compiler/rustc_hir_analysis/src/hir_wf_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::{ObligationCause, WellFormedLoc};
use rustc_middle::bug;
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, TyCtxt, TypingMode, fold_regions};
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt, TypingMode, fold_regions};
use rustc_span::def_id::LocalDefId;
use rustc_trait_selection::traits::{self, ObligationCtxt};
use tracing::debug;
Expand Down Expand Up @@ -77,6 +77,15 @@ fn diagnostic_hir_wf_check<'tcx>(
let tcx_ty = fold_regions(self.tcx, tcx_ty, |r, _| {
if r.is_bound() { self.tcx.lifetimes.re_erased } else { r }
});

// We may be checking the WFness of a type in an opaque with a non-lifetime bound.
// Perhaps we could rebind all the escaping bound vars, but they're coming from
// arbitrary debruijn indices and aren't particularly important anyways, since they
// are only coming from `feature(non_lifetime_binders)` anyways.
if tcx_ty.has_escaping_bound_vars() {
return;
}

let cause = traits::ObligationCause::new(
ty.span,
self.def_id,
Expand Down
38 changes: 24 additions & 14 deletions compiler/rustc_trait_selection/src/traits/select/confirmation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1090,26 +1090,36 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
{
// See `assemble_candidates_for_unsizing` for more info.
// We already checked the compatibility of auto traits within `assemble_candidates_for_unsizing`.
let iter = data_a
.principal()
.filter(|_| {
// optionally drop the principal, if we're unsizing to no principal
data_b.principal().is_some()
})
.map(|b| b.map_bound(ty::ExistentialPredicate::Trait))
.into_iter()
.chain(
let existential_predicates = if data_b.principal().is_some() {
tcx.mk_poly_existential_predicates_from_iter(
data_a
.projection_bounds()
.map(|b| b.map_bound(ty::ExistentialPredicate::Projection)),
.principal()
.map(|b| b.map_bound(ty::ExistentialPredicate::Trait))
.into_iter()
.chain(
data_a
.projection_bounds()
.map(|b| b.map_bound(ty::ExistentialPredicate::Projection)),
)
.chain(
data_b
.auto_traits()
.map(ty::ExistentialPredicate::AutoTrait)
.map(ty::Binder::dummy),
),
)
.chain(
} else {
// If we're unsizing to a dyn type that has no principal, then drop
// the principal and projections from the type. We use the auto traits
// from the RHS type since as we noted that we've checked for auto
// trait compatibility during unsizing.
tcx.mk_poly_existential_predicates_from_iter(
data_b
.auto_traits()
.map(ty::ExistentialPredicate::AutoTrait)
.map(ty::Binder::dummy),
);
let existential_predicates = tcx.mk_poly_existential_predicates_from_iter(iter);
)
};
let source_trait = Ty::new_dynamic(tcx, existential_predicates, r_b, dyn_a);

// Require that the traits involved in this upcast are **equal**;
Expand Down
12 changes: 4 additions & 8 deletions library/core/src/intrinsics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,11 @@
//!
//! # Const intrinsics
//!
//! Note: any changes to the constness of intrinsics should be discussed with the language team.
//! This includes changes in the stability of the constness.
//!
//! //FIXME(#132735) "old" style intrinsics support has been removed
//! In order to make an intrinsic usable at compile-time, it needs to be declared in the "new"
//! style, i.e. as a `#[rustc_intrinsic]` function, not inside an `extern` block. Then copy the
//! implementation from <https://github.com/rust-lang/miri/blob/master/src/intrinsics> to
//! In order to make an intrinsic unstable usable at compile-time, copy the implementation from
//! <https://github.com/rust-lang/miri/blob/master/src/intrinsics> to
//! <https://github.com/rust-lang/rust/blob/master/compiler/rustc_const_eval/src/interpret/intrinsics.rs>
//! and make the intrinsic declaration a `const fn`.
//! and make the intrinsic declaration below a `const fn`. This should be done in coordination with
//! wg-const-eval.
//!
//! If an intrinsic is supposed to be used from a `const fn` with a `rustc_const_stable` attribute,
//! `#[rustc_intrinsic_const_stable_indirect]` needs to be added to the intrinsic. Such a change requires
Expand Down
3 changes: 2 additions & 1 deletion src/doc/unstable-book/src/language-features/intrinsics.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ Various intrinsics have native MIR operations that they correspond to. Instead o
backends to implement both the intrinsic and the MIR operation, the `lower_intrinsics` pass
will convert the calls to the MIR operation. Backends do not need to know about these intrinsics
at all. These intrinsics only make sense without a body, and can be declared as a `#[rustc_intrinsic]`.
The body is never used, as calls to the intrinsic do not exist anymore after MIR analyses.
The body is never used as the lowering pass implements support for all backends, so we never have to
use the fallback logic.

## Intrinsics without fallback logic

Expand Down
12 changes: 12 additions & 0 deletions tests/ui/dyn-compatibility/trait-alias-self-projection.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#![feature(trait_alias)]
trait B = Fn() -> Self;
type D = &'static dyn B;
//~^ ERROR E0411

fn a() -> D {
unreachable!();
}

fn main() {
_ = a();
}
9 changes: 9 additions & 0 deletions tests/ui/dyn-compatibility/trait-alias-self-projection.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0411]: `Self` is not allowed in type aliases
--> $DIR/trait-alias-self-projection.rs:3:19
|
LL | type D = &'static dyn B;
| ^^^^^ `Self` is only available in impls, traits, and concrete type definitions

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0411`.
Loading
Loading