diff options
| author | bors <bors@rust-lang.org> | 2025-05-20 15:48:56 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2025-05-20 15:48:56 +0000 |
| commit | 444a62712a29e14d3b6147b51fd24e623496bf58 (patch) | |
| tree | a947a2d73273ff78fff8c9e97344f9dd6746551c /compiler | |
| parent | 6cab15c1aef39456d86ce51be6096088cb2ef1da (diff) | |
| parent | cc0ee34b43ffb49fe37109a1fb3ad5e85878c4b8 (diff) | |
| download | rust-444a62712a29e14d3b6147b51fd24e623496bf58.tar.gz rust-444a62712a29e14d3b6147b51fd24e623496bf58.zip | |
Auto merge of #141292 - matthiaskrgr:rollup-9nhhk7k, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #139419 (Error on recursive opaque ty in HIR typeck) - #141236 (Resolved issue with mismatched types triggering ICE in certain scenarios) - #141253 (Warning added when dependency crate has async drop types, and the feature is disabled) - #141269 (rustc-dev-guide subtree update) - #141275 (`gather_locals`: only visit guard pattern guards when checking the guard) - #141279 (`lower_to_hir` cleanups) - #141285 (Add tick to `RePlaceholder` debug output) r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_ast_lowering/src/item.rs | 50 | ||||
| -rw-r--r-- | compiler/rustc_ast_lowering/src/lib.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_hir_typeck/src/demand.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_hir_typeck/src/gather_locals.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_hir_typeck/src/writeback.rs | 70 | ||||
| -rw-r--r-- | compiler/rustc_metadata/messages.ftl | 2 | ||||
| -rw-r--r-- | compiler/rustc_pattern_analysis/src/rustc.rs | 40 | ||||
| -rw-r--r-- | compiler/rustc_type_ir/src/region_kind.rs | 2 |
8 files changed, 114 insertions, 85 deletions
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index f48a571b86a..e98d6c50ee7 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -70,44 +70,32 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { } } - pub(super) fn lower_node(&mut self, def_id: LocalDefId) -> hir::MaybeOwner<'hir> { + pub(super) fn lower_node(&mut self, def_id: LocalDefId) { let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom); if let hir::MaybeOwner::Phantom = owner { let node = self.ast_index[def_id]; match node { AstOwner::NonOwner => {} - AstOwner::Crate(c) => self.lower_crate(c), - AstOwner::Item(item) => self.lower_item(item), - AstOwner::AssocItem(item, ctxt) => self.lower_assoc_item(item, ctxt), - AstOwner::ForeignItem(item) => self.lower_foreign_item(item), + AstOwner::Crate(c) => { + debug_assert_eq!(self.resolver.node_id_to_def_id[&CRATE_NODE_ID], CRATE_DEF_ID); + self.with_lctx(CRATE_NODE_ID, |lctx| { + let module = lctx.lower_mod(&c.items, &c.spans); + // FIXME(jdonszelman): is dummy span ever a problem here? + lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs, DUMMY_SP); + hir::OwnerNode::Crate(module) + }) + } + AstOwner::Item(item) => { + self.with_lctx(item.id, |lctx| hir::OwnerNode::Item(lctx.lower_item(item))) + } + AstOwner::AssocItem(item, ctxt) => { + self.with_lctx(item.id, |lctx| lctx.lower_assoc_item(item, ctxt)) + } + AstOwner::ForeignItem(item) => self.with_lctx(item.id, |lctx| { + hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item)) + }), } } - - self.owners[def_id] - } - - #[instrument(level = "debug", skip(self, c))] - fn lower_crate(&mut self, c: &Crate) { - debug_assert_eq!(self.resolver.node_id_to_def_id[&CRATE_NODE_ID], CRATE_DEF_ID); - self.with_lctx(CRATE_NODE_ID, |lctx| { - let module = lctx.lower_mod(&c.items, &c.spans); - // FIXME(jdonszelman): is dummy span ever a problem here? - lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs, DUMMY_SP); - hir::OwnerNode::Crate(module) - }) - } - - #[instrument(level = "debug", skip(self))] - fn lower_item(&mut self, item: &Item) { - self.with_lctx(item.id, |lctx| hir::OwnerNode::Item(lctx.lower_item(item))) - } - - fn lower_assoc_item(&mut self, item: &AssocItem, ctxt: AssocCtxt) { - self.with_lctx(item.id, |lctx| lctx.lower_assoc_item(item, ctxt)) - } - - fn lower_foreign_item(&mut self, item: &ForeignItem) { - self.with_lctx(item.id, |lctx| hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item))) } } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 19095f2e01e..422e79ca82f 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -444,14 +444,14 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> { tcx.definitions_untracked().def_index_count(), ); + let mut lowerer = item::ItemLowerer { + tcx, + resolver: &mut resolver, + ast_index: &ast_index, + owners: &mut owners, + }; for def_id in ast_index.indices() { - item::ItemLowerer { - tcx, - resolver: &mut resolver, - ast_index: &ast_index, - owners: &mut owners, - } - .lower_node(def_id); + lowerer.lower_node(def_id); } drop(ast_index); diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index d1bc54ed73e..8182851a015 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -84,7 +84,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.annotate_expected_due_to_let_ty(err, expr, error); self.annotate_loop_expected_due_to_inference(err, expr, error); - if self.annotate_mut_binding_to_immutable_binding(err, expr, error) { + if self.annotate_mut_binding_to_immutable_binding(err, expr, expr_ty, expected, error) { return; } @@ -799,17 +799,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Detect the following case /// /// ```text - /// fn change_object(mut a: &Ty) { + /// fn change_object(mut b: &Ty) { /// let a = Ty::new(); /// b = a; /// } /// ``` /// - /// where the user likely meant to modify the value behind there reference, use `a` as an out + /// where the user likely meant to modify the value behind there reference, use `b` as an out /// parameter, instead of mutating the local binding. When encountering this we suggest: /// /// ```text - /// fn change_object(a: &'_ mut Ty) { + /// fn change_object(b: &'_ mut Ty) { /// let a = Ty::new(); /// *b = a; /// } @@ -818,13 +818,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, err: &mut Diag<'_>, expr: &hir::Expr<'_>, + expr_ty: Ty<'tcx>, + expected: Ty<'tcx>, error: Option<TypeError<'tcx>>, ) -> bool { - if let Some(TypeError::Sorts(ExpectedFound { expected, found })) = error + if let Some(TypeError::Sorts(ExpectedFound { .. })) = error && let ty::Ref(_, inner, hir::Mutability::Not) = expected.kind() // The difference between the expected and found values is one level of borrowing. - && self.can_eq(self.param_env, *inner, found) + && self.can_eq(self.param_env, *inner, expr_ty) // We have an `ident = expr;` assignment. && let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(lhs, rhs, _), .. }) = diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs index 956671fc66e..7d99b0e7869 100644 --- a/compiler/rustc_hir_typeck/src/gather_locals.rs +++ b/compiler/rustc_hir_typeck/src/gather_locals.rs @@ -218,7 +218,12 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { ); } let old_outermost_fn_param_pat = self.outermost_fn_param_pat.take(); - intravisit::walk_pat(self, p); + if let PatKind::Guard(subpat, _) = p.kind { + // We'll visit the guard when checking it. Don't gather its locals twice. + self.visit_pat(subpat); + } else { + intravisit::walk_pat(self, p); + } self.outermost_fn_param_pat = old_outermost_fn_param_pat; } diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 9be041f75d7..b2497cb0de1 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -9,17 +9,21 @@ //! which creates a new `TypeckResults` which doesn't contain any inference variables. use std::mem; +use std::ops::ControlFlow; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::unord::ExtendUnord; -use rustc_errors::ErrorGuaranteed; +use rustc_errors::{E0720, ErrorGuaranteed}; +use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, InferKind, Visitor}; use rustc_hir::{self as hir, AmbigArg, HirId}; use rustc_infer::traits::solve::Goal; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion}; use rustc_middle::ty::{ - self, DefiningScopeKind, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, - TypeVisitableExt, fold_regions, + self, DefiningScopeKind, OpaqueHiddenType, Ty, TyCtxt, TypeFoldable, TypeFolder, + TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, + fold_regions, }; use rustc_span::{Span, sym}; use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded; @@ -595,6 +599,35 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { entry.span = prev.span.substitute_dummy(hidden_type.span); } } + + let recursive_opaques: Vec<_> = self + .typeck_results + .concrete_opaque_types + .iter() + .filter(|&(&def_id, hidden_ty)| { + hidden_ty + .ty + .visit_with(&mut HasRecursiveOpaque { + def_id, + seen: Default::default(), + opaques: &self.typeck_results.concrete_opaque_types, + tcx, + }) + .is_break() + }) + .map(|(def_id, hidden_ty)| (*def_id, hidden_ty.span)) + .collect(); + for (def_id, span) in recursive_opaques { + let guar = self + .fcx + .dcx() + .struct_span_err(span, "cannot resolve opaque type") + .with_code(E0720) + .emit(); + self.typeck_results + .concrete_opaque_types + .insert(def_id, OpaqueHiddenType { span, ty: Ty::new_error(tcx, guar) }); + } } fn visit_field_id(&mut self, hir_id: HirId) { @@ -959,3 +992,34 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EagerlyNormalizeConsts<'tcx> { self.tcx.try_normalize_erasing_regions(self.typing_env, ct).unwrap_or(ct) } } + +struct HasRecursiveOpaque<'a, 'tcx> { + def_id: LocalDefId, + seen: FxHashSet<LocalDefId>, + opaques: &'a FxIndexMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>, + tcx: TyCtxt<'tcx>, +} + +impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasRecursiveOpaque<'_, 'tcx> { + type Result = ControlFlow<()>; + + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { + if let ty::Alias(ty::Opaque, alias_ty) = *t.kind() + && let Some(def_id) = alias_ty.def_id.as_local() + { + if self.def_id == def_id { + return ControlFlow::Break(()); + } + + if self.seen.insert(def_id) + && let Some(hidden_ty) = self.opaques.get(&def_id) + { + ty::EarlyBinder::bind(hidden_ty.ty) + .instantiate(self.tcx, alias_ty.args) + .visit_with(self)?; + } + } + + t.super_visit_with(self) + } +} diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl index cac8f34b0fa..bccffe39243 100644 --- a/compiler/rustc_metadata/messages.ftl +++ b/compiler/rustc_metadata/messages.ftl @@ -2,7 +2,7 @@ metadata_as_needed_compatibility = linking modifier `as-needed` is only compatible with `dylib` and `framework` linking kinds metadata_async_drop_types_in_dependency = - found async drop types in dependecy `{$extern_crate}`, but async_drop feature is disabled for `{$local_crate}` + found async drop types in dependency `{$extern_crate}`, but async_drop feature is disabled for `{$local_crate}` .help = if async drop type will be dropped in a crate without `feature(async_drop)`, sync Drop will be used metadata_bad_panic_strategy = diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index a89d01dcbbe..d9f1888bfd9 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -1,6 +1,5 @@ use std::fmt; use std::iter::once; -use std::ops::ControlFlow; use rustc_abi::{FIRST_VARIANT, FieldIdx, Integer, VariantIdx}; use rustc_arena::DroplessArena; @@ -12,8 +11,7 @@ use rustc_middle::mir::{self, Const}; use rustc_middle::thir::{self, Pat, PatKind, PatRange, PatRangeBoundary}; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{ - self, FieldDef, OpaqueTypeKey, ScalarInt, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, - TypeVisitableExt, TypeVisitor, VariantDef, + self, FieldDef, OpaqueTypeKey, ScalarInt, Ty, TyCtxt, TypeVisitableExt, VariantDef, }; use rustc_middle::{bug, span_bug}; use rustc_session::lint; @@ -137,22 +135,11 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { /// Returns the hidden type corresponding to this key if the body under analysis is allowed to /// know it. fn reveal_opaque_key(&self, key: OpaqueTypeKey<'tcx>) -> Option<Ty<'tcx>> { - if let Some(hidden_ty) = self.typeck_results.concrete_opaque_types.get(&key.def_id) { - let ty = ty::EarlyBinder::bind(hidden_ty.ty).instantiate(self.tcx, key.args); - if ty.visit_with(&mut RecursiveOpaque { def_id: key.def_id.into() }).is_continue() { - Some(ty) - } else { - // HACK: We skip revealing opaque types which recursively expand - // to themselves. This is because we may infer hidden types like - // `Opaque<T> = Opaque<Opaque<T>>` or `Opaque<T> = Opaque<(T,)>` - // in hir typeck. - None - } - } else { - None - } + self.typeck_results + .concrete_opaque_types + .get(&key.def_id) + .map(|x| ty::EarlyBinder::bind(x.ty).instantiate(self.tcx, key.args)) } - // This can take a non-revealed `Ty` because it reveals opaques itself. pub fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool { !ty.inhabited_predicate(self.tcx).apply_revealing_opaque( @@ -1177,20 +1164,3 @@ fn detect_mixed_deref_pat_ctors<'p, 'tcx>( } Ok(()) } - -struct RecursiveOpaque { - def_id: DefId, -} -impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for RecursiveOpaque { - type Result = ControlFlow<()>; - - fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { - if let ty::Alias(ty::Opaque, alias_ty) = t.kind() { - if alias_ty.def_id == self.def_id { - return ControlFlow::Break(()); - } - } - - if t.has_opaque_types() { t.super_visit_with(self) } else { ControlFlow::Continue(()) } - } -} diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs index eae3213ead0..1b5d04e6025 100644 --- a/compiler/rustc_type_ir/src/region_kind.rs +++ b/compiler/rustc_type_ir/src/region_kind.rs @@ -193,7 +193,7 @@ impl<I: Interner> fmt::Debug for RegionKind<I> { ReVar(vid) => write!(f, "{vid:?}"), - RePlaceholder(placeholder) => write!(f, "{placeholder:?}"), + RePlaceholder(placeholder) => write!(f, "'{placeholder:?}"), // Use `'{erased}` as the output instead of `'erased` so that its more obviously distinct from // a `ReEarlyParam` named `'erased`. Technically that would print as `'erased/#IDX` so this is |
