Skip to content

Rollup of 6 pull requests #135402

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

Merged
merged 13 commits into from
Jan 12, 2025
Merged
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
2 changes: 1 addition & 1 deletion compiler/rustc_arena/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ impl<T> ArenaChunk<T> {
// been initialized.
unsafe {
let slice = self.storage.as_mut();
ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(&mut slice[..len]));
slice[..len].assume_init_drop();
}
}
}
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_borrowck/src/region_infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
let (Ok(e) | Err(e)) = prev
.build_mismatch_error(
&OpaqueHiddenType { ty, span: concrete_type.span },
opaque_type_key.def_id,
infcx.tcx,
)
.map(|d| d.emit());
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_errors/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -566,9 +566,7 @@ pub enum StashKey {
/// FRU syntax
MaybeFruTypo,
CallAssocMethod,
TraitMissingMethod,
AssociatedTypeSuggestion,
OpaqueHiddenTypeMismatch,
MaybeForgetReturn,
/// Query cycle detected, stashing in favor of a better error.
Cycle,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ fn sanity_check_found_hidden_type<'tcx>(
} else {
let span = tcx.def_span(key.def_id);
let other = ty::OpaqueHiddenType { ty: hidden_ty, span };
Err(ty.build_mismatch_error(&other, key.def_id, tcx)?.emit())
Err(ty.build_mismatch_error(&other, tcx)?.emit())
}
}

Expand Down
21 changes: 7 additions & 14 deletions compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use rustc_errors::StashKey;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, Visitor};
Expand Down Expand Up @@ -45,7 +44,7 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type(
if !hidden.ty.references_error() {
for concrete_type in locator.typeck_types {
if concrete_type.ty != tcx.erase_regions(hidden.ty) {
if let Ok(d) = hidden.build_mismatch_error(&concrete_type, def_id, tcx) {
if let Ok(d) = hidden.build_mismatch_error(&concrete_type, tcx) {
d.emit();
}
}
Expand Down Expand Up @@ -121,7 +120,7 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local
if !hidden.ty.references_error() {
for concrete_type in locator.typeck_types {
if concrete_type.ty != tcx.erase_regions(hidden.ty) {
if let Ok(d) = hidden.build_mismatch_error(&concrete_type, def_id, tcx) {
if let Ok(d) = hidden.build_mismatch_error(&concrete_type, tcx) {
d.emit();
}
}
Expand Down Expand Up @@ -285,9 +284,8 @@ impl TaitConstraintLocator<'_> {
debug!(?concrete_type, "found constraint");
if let Some(prev) = &mut self.found {
if concrete_type.ty != prev.ty {
let (Ok(guar) | Err(guar)) = prev
.build_mismatch_error(&concrete_type, self.def_id, self.tcx)
.map(|d| d.emit());
let (Ok(guar) | Err(guar)) =
prev.build_mismatch_error(&concrete_type, self.tcx).map(|d| d.emit());
prev.ty = Ty::new_error(self.tcx, guar);
}
} else {
Expand Down Expand Up @@ -361,11 +359,8 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
);
if let Some(prev) = &mut hir_opaque_ty {
if concrete_type.ty != prev.ty {
if let Ok(d) = prev.build_mismatch_error(&concrete_type, def_id, tcx) {
d.stash(
tcx.def_span(opaque_type_key.def_id),
StashKey::OpaqueHiddenTypeMismatch,
);
if let Ok(d) = prev.build_mismatch_error(&concrete_type, tcx) {
d.emit();
}
}
} else {
Expand Down Expand Up @@ -435,9 +430,7 @@ impl RpitConstraintChecker<'_> {
debug!(?concrete_type, "found constraint");

if concrete_type.ty != self.found.ty {
if let Ok(d) =
self.found.build_mismatch_error(&concrete_type, self.def_id, self.tcx)
{
if let Ok(d) = self.found.build_mismatch_error(&concrete_type, self.tcx) {
d.emit();
}
}
Expand Down
53 changes: 50 additions & 3 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ use rustc_ast::TraitObjectSyntax;
use rustc_errors::codes::*;
use rustc_errors::{Diag, EmissionGuarantee, ErrorGuaranteed, StashKey, Suggestions};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def::{DefKind, Namespace, Res};
use rustc_hir::def_id::DefId;
use rustc_lint_defs::Applicability;
use rustc_lint_defs::builtin::BARE_TRAIT_OBJECTS;
use rustc_span::Span;
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName;

use super::HirTyLowerer;
Expand Down Expand Up @@ -86,7 +88,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// Check if the impl trait that we are considering is an impl of a local trait.
self.maybe_suggest_blanket_trait_impl(self_ty, &mut diag);
self.maybe_suggest_assoc_ty_bound(self_ty, &mut diag);
// In case there is an associate type with the same name
self.maybe_suggest_typoed_method(
self_ty,
poly_trait_ref.trait_ref.trait_def_id(),
&mut diag,
);
// In case there is an associated type with the same name
// Add the suggestion to this error
if let Some(mut sugg) =
tcx.dcx().steal_non_err(self_ty.span, StashKey::AssociatedTypeSuggestion)
Expand All @@ -96,7 +103,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
s1.append(s2);
sugg.cancel();
}
diag.stash(self_ty.span, StashKey::TraitMissingMethod)
Some(diag.emit())
} else {
tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, |lint| {
lint.primary_message("trait objects without an explicit `dyn` are deprecated");
Expand Down Expand Up @@ -343,4 +350,44 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
);
}
}

fn maybe_suggest_typoed_method(
&self,
self_ty: &hir::Ty<'_>,
trait_def_id: Option<DefId>,
diag: &mut Diag<'_>,
) {
let tcx = self.tcx();
let Some(trait_def_id) = trait_def_id else {
return;
};
let hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Path(hir::QPath::TypeRelative(path_ty, segment)),
..
}) = tcx.parent_hir_node(self_ty.hir_id)
else {
return;
};
if path_ty.hir_id != self_ty.hir_id {
return;
}
let names: Vec<_> = tcx
.associated_items(trait_def_id)
.in_definition_order()
.filter(|assoc| assoc.kind.namespace() == Namespace::ValueNS)
.map(|cand| cand.name)
.collect();
if let Some(typo) = find_best_match_for_name(&names, segment.ident.name, None) {
diag.span_suggestion_verbose(
segment.ident.span,
format!(
"you may have misspelled this associated item, causing `{}` \
to be interpreted as a type rather than a trait",
tcx.item_name(trait_def_id),
),
typo,
Applicability::MaybeIncorrect,
);
}
}
}
24 changes: 1 addition & 23 deletions compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::slice;

use rustc_abi::FieldIdx;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey};
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan};
use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
Expand Down Expand Up @@ -806,17 +806,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let item_name = item_segment.ident;
let result = self
.resolve_fully_qualified_call(span, item_name, ty.normalized, qself.span, hir_id)
.map(|r| {
// lint bare trait if the method is found in the trait
if span.edition().at_least_rust_2021() {
self.dcx().try_steal_modify_and_emit_err(
qself.span,
StashKey::TraitMissingMethod,
|_err| {},
);
}
r
})
.or_else(|error| {
let guar = self
.dcx()
Expand All @@ -840,17 +829,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}

// Emit the diagnostic for bare traits. (We used to cancel for slightly better
// error messages, but cancelling stashed diagnostics is no longer allowed because
// it causes problems when tracking whether errors have actually occurred.)
if span.edition().at_least_rust_2021() {
self.dcx().try_steal_modify_and_emit_err(
qself.span,
StashKey::TraitMissingMethod,
|_err| {},
);
}

if item_name.name != kw::Empty {
self.report_method_error(
hir_id,
Expand Down
13 changes: 3 additions & 10 deletions compiler/rustc_hir_typeck/src/writeback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use std::mem;

use rustc_data_structures::unord::ExtendUnord;
use rustc_errors::{ErrorGuaranteed, StashKey};
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::HirId;
use rustc_hir::intravisit::{self, Visitor};
Expand Down Expand Up @@ -582,15 +582,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
&& last_opaque_ty.ty != hidden_type.ty
{
assert!(!self.fcx.next_trait_solver());
if let Ok(d) = hidden_type.build_mismatch_error(
&last_opaque_ty,
opaque_type_key.def_id,
self.tcx(),
) {
d.stash(
self.tcx().def_span(opaque_type_key.def_id),
StashKey::OpaqueHiddenTypeMismatch,
);
if let Ok(d) = hidden_type.build_mismatch_error(&last_opaque_ty, self.tcx()) {
d.emit();
}
}
}
Expand Down
12 changes: 1 addition & 11 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::intern::Interned;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::steal::Steal;
use rustc_errors::{Diag, ErrorGuaranteed, StashKey};
use rustc_errors::{Diag, ErrorGuaranteed};
use rustc_hir::LangItem;
use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
Expand Down Expand Up @@ -782,18 +782,8 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
pub fn build_mismatch_error(
&self,
other: &Self,
opaque_def_id: LocalDefId,
tcx: TyCtxt<'tcx>,
) -> Result<Diag<'tcx>, ErrorGuaranteed> {
// We used to cancel here for slightly better error messages, but
// cancelling stashed diagnostics is no longer allowed because it
// causes problems when tracking whether errors have actually
// occurred.
tcx.sess.dcx().try_steal_modify_and_emit_err(
tcx.def_span(opaque_def_id),
StashKey::OpaqueHiddenTypeMismatch,
|_err| {},
);
(self.ty, other.ty).error_reported()?;
// Found different concrete types for the opaque type.
let sub_diag = if self.span == other.span {
Expand Down
56 changes: 56 additions & 0 deletions compiler/rustc_mir_transform/src/impossible_predicates.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//! Check if it's even possible to satisfy the 'where' clauses
//! for this item.
//!
//! It's possible to `#!feature(trivial_bounds)]` to write
//! a function with impossible to satisfy clauses, e.g.:
//! `fn foo() where String: Copy {}`.
//!
//! We don't usually need to worry about this kind of case,
//! since we would get a compilation error if the user tried
//! to call it. However, since we optimize even without any
//! calls to the function, we need to make sure that it even
//! makes sense to try to evaluate the body.
//!
//! If there are unsatisfiable where clauses, then all bets are
//! off, and we just give up.
//!
//! We manually filter the predicates, skipping anything that's not
//! "global". We are in a potentially generic context
//! (e.g. we are evaluating a function without instantiating generic
//! parameters, so this filtering serves two purposes:
//!
//! 1. We skip evaluating any predicates that we would
//! never be able prove are unsatisfiable (e.g. `<T as Foo>`
//! 2. We avoid trying to normalize predicates involving generic
//! parameters (e.g. `<T as Foo>::MyItem`). This can confuse
//! the normalization code (leading to cycle errors), since
//! it's usually never invoked in this way.

use rustc_middle::mir::{Body, START_BLOCK, TerminatorKind};
use rustc_middle::ty::{TyCtxt, TypeVisitableExt};
use rustc_trait_selection::traits;
use tracing::trace;

use crate::pass_manager::MirPass;

pub(crate) struct ImpossiblePredicates;

impl<'tcx> MirPass<'tcx> for ImpossiblePredicates {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let predicates = tcx
.predicates_of(body.source.def_id())
.predicates
.iter()
.filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
if traits::impossible_predicates(tcx, traits::elaborate(tcx, predicates).collect()) {
trace!("found unsatisfiable predicates for {:?}", body.source);
// Clear the body to only contain a single `unreachable` statement.
let bbs = body.basic_blocks.as_mut();
bbs.raw.truncate(1);
bbs[START_BLOCK].statements.clear();
bbs[START_BLOCK].terminator_mut().kind = TerminatorKind::Unreachable;
body.var_debug_info.clear();
body.local_decls.raw.truncate(body.arg_count + 1);
}
}
}
Loading
Loading