diff options
Diffstat (limited to 'compiler/rustc_hir_analysis/src')
19 files changed, 293 insertions, 187 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index a0798656763..18ef00dc8b1 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -397,8 +397,11 @@ fn best_definition_site_of_opaque<'tcx>( return ControlFlow::Continue(()); } - if let Some(hidden_ty) = - self.tcx.mir_borrowck(item_def_id).concrete_opaque_types.get(&self.opaque_def_id) + if let Some(hidden_ty) = self + .tcx + .mir_borrowck(item_def_id) + .ok() + .and_then(|opaque_types| opaque_types.0.get(&self.opaque_def_id)) { ControlFlow::Break((hidden_ty.span, item_def_id)) } else { @@ -413,9 +416,6 @@ fn best_definition_site_of_opaque<'tcx>( self.tcx } fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) -> Self::Result { - if let hir::ExprKind::Closure(closure) = ex.kind { - self.check(closure.def_id)?; - } intravisit::walk_expr(self, ex) } fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) -> Self::Result { @@ -741,10 +741,6 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { for &assoc_item in assoc_items.in_definition_order() { match assoc_item.kind { - ty::AssocKind::Fn => { - let abi = tcx.fn_sig(assoc_item.def_id).skip_binder().abi(); - forbid_intrinsic_abi(tcx, assoc_item.ident(tcx).span, abi); - } ty::AssocKind::Type if assoc_item.defaultness(tcx).has_value() => { let trait_args = GenericArgs::identity_for_item(tcx, def_id); let _: Result<_, rustc_errors::ErrorGuaranteed> = check_type_bounds( @@ -788,65 +784,59 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { }; check_abi(tcx, it.span, abi); - match abi { - ExternAbi::RustIntrinsic => { - for item in items { - intrinsic::check_intrinsic_type( - tcx, - item.id.owner_id.def_id, - item.span, - item.ident.name, - abi, - ); - } + for item in items { + let def_id = item.id.owner_id.def_id; + + if tcx.has_attr(def_id, sym::rustc_intrinsic) { + intrinsic::check_intrinsic_type( + tcx, + item.id.owner_id.def_id, + item.span, + item.ident.name, + abi, + ); } - _ => { - for item in items { - let def_id = item.id.owner_id.def_id; - let generics = tcx.generics_of(def_id); - let own_counts = generics.own_counts(); - if generics.own_params.len() - own_counts.lifetimes != 0 { - let (kinds, kinds_pl, egs) = match (own_counts.types, own_counts.consts) - { - (_, 0) => ("type", "types", Some("u32")), - // We don't specify an example value, because we can't generate - // a valid value for any type. - (0, _) => ("const", "consts", None), - _ => ("type or const", "types or consts", None), - }; - struct_span_code_err!( - tcx.dcx(), - item.span, - E0044, - "foreign items may not have {kinds} parameters", - ) - .with_span_label(item.span, format!("can't have {kinds} parameters")) - .with_help( - // FIXME: once we start storing spans for type arguments, turn this - // into a suggestion. - format!( - "replace the {} parameters with concrete {}{}", - kinds, - kinds_pl, - egs.map(|egs| format!(" like `{egs}`")).unwrap_or_default(), - ), - ) - .emit(); - } + let generics = tcx.generics_of(def_id); + let own_counts = generics.own_counts(); + if generics.own_params.len() - own_counts.lifetimes != 0 { + let (kinds, kinds_pl, egs) = match (own_counts.types, own_counts.consts) { + (_, 0) => ("type", "types", Some("u32")), + // We don't specify an example value, because we can't generate + // a valid value for any type. + (0, _) => ("const", "consts", None), + _ => ("type or const", "types or consts", None), + }; + struct_span_code_err!( + tcx.dcx(), + item.span, + E0044, + "foreign items may not have {kinds} parameters", + ) + .with_span_label(item.span, format!("can't have {kinds} parameters")) + .with_help( + // FIXME: once we start storing spans for type arguments, turn this + // into a suggestion. + format!( + "replace the {} parameters with concrete {}{}", + kinds, + kinds_pl, + egs.map(|egs| format!(" like `{egs}`")).unwrap_or_default(), + ), + ) + .emit(); + } - let item = tcx.hir_foreign_item(item.id); - match &item.kind { - hir::ForeignItemKind::Fn(sig, _, _) => { - require_c_abi_if_c_variadic(tcx, sig.decl, abi, item.span); - } - hir::ForeignItemKind::Static(..) => { - check_static_inhabited(tcx, def_id); - check_static_linkage(tcx, def_id); - } - _ => {} - } + let item = tcx.hir_foreign_item(item.id); + match &item.kind { + hir::ForeignItemKind::Fn(sig, _, _) => { + require_c_abi_if_c_variadic(tcx, sig.decl, abi, item.span); + } + hir::ForeignItemKind::Static(..) => { + check_static_inhabited(tcx, def_id); + check_static_linkage(tcx, def_id); } + _ => {} } } } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 5e68bb31001..32a8f101849 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -442,7 +442,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RemapLateParam<'tcx> { } fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - if let ty::ReLateParam(fr) = *r { + if let ty::ReLateParam(fr) = r.kind() { ty::Region::new_late_param( self.tcx, fr.scope, diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 42d785c8dd0..0bf9e127989 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -1,4 +1,4 @@ -//! Type-checking for the rust-intrinsic intrinsics that the compiler exposes. +//! Type-checking for the `#[rustc_intrinsic]` intrinsics that the compiler exposes. use rustc_abi::ExternAbi; use rustc_errors::codes::*; diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 7c5d7b33a34..30921b6f055 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -137,15 +137,6 @@ fn get_owner_return_paths( }) } -/// Forbid defining intrinsics in Rust code, -/// as they must always be defined by the compiler. -// FIXME: Move this to a more appropriate place. -pub fn forbid_intrinsic_abi(tcx: TyCtxt<'_>, sp: Span, abi: ExternAbi) { - if let ExternAbi::RustIntrinsic = abi { - tcx.dcx().span_err(sp, "intrinsic must be in `extern \"rust-intrinsic\" { ... }` block"); - } -} - pub(super) fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId) { // Only restricted on wasm target for now if !tcx.sess.target.is_like_wasm { diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index cf66ab708bb..7cb31a64e13 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -8,6 +8,7 @@ use std::mem; +use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, Visitor}; @@ -44,6 +45,8 @@ struct ScopeResolutionVisitor<'tcx> { scope_tree: ScopeTree, cx: Context, + + extended_super_lets: FxHashMap<hir::ItemLocalId, Option<Scope>>, } /// Records the lifetime of a local variable as `cx.var_parent` @@ -214,18 +217,29 @@ fn resolve_stmt<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, stmt: &'tcx hi let stmt_id = stmt.hir_id.local_id; debug!("resolve_stmt(stmt.id={:?})", stmt_id); - // Every statement will clean up the temporaries created during - // execution of that statement. Therefore each statement has an - // associated destruction scope that represents the scope of the - // statement plus its destructors, and thus the scope for which - // regions referenced by the destructors need to survive. + if let hir::StmtKind::Let(LetStmt { super_: Some(_), .. }) = stmt.kind { + // `super let` statement does not start a new scope, such that + // + // { super let x = identity(&temp()); &x }.method(); + // + // behaves exactly as + // + // (&identity(&temp()).method(); + intravisit::walk_stmt(visitor, stmt); + } else { + // Every statement will clean up the temporaries created during + // execution of that statement. Therefore each statement has an + // associated destruction scope that represents the scope of the + // statement plus its destructors, and thus the scope for which + // regions referenced by the destructors need to survive. - let prev_parent = visitor.cx.parent; - visitor.enter_node_scope_with_dtor(stmt_id, true); + let prev_parent = visitor.cx.parent; + visitor.enter_node_scope_with_dtor(stmt_id, true); - intravisit::walk_stmt(visitor, stmt); + intravisit::walk_stmt(visitor, stmt); - visitor.cx.parent = prev_parent; + visitor.cx.parent = prev_parent; + } } fn resolve_expr<'tcx>( @@ -446,14 +460,11 @@ fn resolve_expr<'tcx>( // Mark this expr's scope and all parent scopes as containing `yield`. let mut scope = Scope { local_id: expr.hir_id.local_id, data: ScopeData::Node }; loop { - let span = match expr.kind { - hir::ExprKind::Yield(expr, hir::YieldSource::Await { .. }) => { - expr.span.shrink_to_hi().to(expr.span) - } - _ => expr.span, + let data = YieldData { + span: expr.span, + expr_and_pat_count: visitor.expr_and_pat_count, + source: *source, }; - let data = - YieldData { span, expr_and_pat_count: visitor.expr_and_pat_count, source: *source }; match visitor.scope_tree.yield_in_scope.get_mut(&scope) { Some(yields) => yields.push(data), None => { @@ -481,14 +492,19 @@ fn resolve_expr<'tcx>( visitor.cx = prev_cx; } +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +enum LetKind { + Regular, + Super, +} + fn resolve_local<'tcx>( visitor: &mut ScopeResolutionVisitor<'tcx>, pat: Option<&'tcx hir::Pat<'tcx>>, init: Option<&'tcx hir::Expr<'tcx>>, + let_kind: LetKind, ) { - debug!("resolve_local(pat={:?}, init={:?})", pat, init); - - let blk_scope = visitor.cx.var_parent; + debug!("resolve_local(pat={:?}, init={:?}, let_kind={:?})", pat, init, let_kind); // As an exception to the normal rules governing temporary // lifetimes, initializers in a let have a temporary lifetime @@ -546,14 +562,50 @@ fn resolve_local<'tcx>( // A, but the inner rvalues `a()` and `b()` have an extended lifetime // due to rule C. + if let_kind == LetKind::Super { + if let Some(scope) = visitor.extended_super_lets.remove(&pat.unwrap().hir_id.local_id) { + // This expression was lifetime-extended by a parent let binding. E.g. + // + // let a = { + // super let b = temp(); + // &b + // }; + // + // (Which needs to behave exactly as: let a = &temp();) + // + // Processing of `let a` will have already decided to extend the lifetime of this + // `super let` to its own var_scope. We use that scope. + visitor.cx.var_parent = scope; + } else { + // This `super let` is not subject to lifetime extension from a parent let binding. E.g. + // + // identity({ super let x = temp(); &x }).method(); + // + // (Which needs to behave exactly as: identity(&temp()).method();) + // + // Iterate up to the enclosing destruction scope to find the same scope that will also + // be used for the result of the block itself. + while let Some(s) = visitor.cx.var_parent { + let parent = visitor.scope_tree.parent_map.get(&s).cloned(); + if let Some(Scope { data: ScopeData::Destruction, .. }) = parent { + break; + } + visitor.cx.var_parent = parent; + } + } + } + if let Some(expr) = init { - record_rvalue_scope_if_borrow_expr(visitor, expr, blk_scope); + record_rvalue_scope_if_borrow_expr(visitor, expr, visitor.cx.var_parent); if let Some(pat) = pat { if is_binding_pat(pat) { visitor.scope_tree.record_rvalue_candidate( expr.hir_id, - RvalueCandidate { target: expr.hir_id.local_id, lifetime: blk_scope }, + RvalueCandidate { + target: expr.hir_id.local_id, + lifetime: visitor.cx.var_parent, + }, ); } } @@ -565,6 +617,7 @@ fn resolve_local<'tcx>( if let Some(expr) = init { visitor.visit_expr(expr); } + if let Some(pat) = pat { visitor.visit_pat(pat); } @@ -626,6 +679,7 @@ fn resolve_local<'tcx>( PatKind::Ref(_, _) | PatKind::Binding(hir::BindingMode(hir::ByRef::No, _), ..) + | PatKind::Missing | PatKind::Wild | PatKind::Never | PatKind::Expr(_) @@ -642,6 +696,7 @@ fn resolve_local<'tcx>( /// | [ ..., E&, ... ] /// | ( ..., E&, ... ) /// | {...; E&} + /// | { super let ... = E&; ... } /// | if _ { ...; E& } else { ...; E& } /// | match _ { ..., _ => E&, ... } /// | box E& @@ -678,6 +733,13 @@ fn resolve_local<'tcx>( if let Some(subexpr) = block.expr { record_rvalue_scope_if_borrow_expr(visitor, subexpr, blk_id); } + for stmt in block.stmts { + if let hir::StmtKind::Let(local) = stmt.kind + && let Some(_) = local.super_ + { + visitor.extended_super_lets.insert(local.pat.hir_id.local_id, blk_id); + } + } } hir::ExprKind::If(_, then_block, else_block) => { record_rvalue_scope_if_borrow_expr(visitor, then_block, blk_id); @@ -803,7 +865,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { local_id: body.value.hir_id.local_id, data: ScopeData::Destruction, }); - resolve_local(this, None, Some(body.value)); + resolve_local(this, None, Some(body.value), LetKind::Regular); } }) } @@ -821,7 +883,11 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { resolve_expr(self, ex, false); } fn visit_local(&mut self, l: &'tcx LetStmt<'tcx>) { - resolve_local(self, Some(l.pat), l.init) + let let_kind = match l.super_ { + Some(_) => LetKind::Super, + None => LetKind::Regular, + }; + resolve_local(self, Some(l.pat), l.init, let_kind); } fn visit_inline_const(&mut self, c: &'tcx hir::ConstBlock) { let body = self.tcx.hir_body(c.body); @@ -850,6 +916,7 @@ pub(crate) fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree { cx: Context { parent: None, var_parent: None }, pessimistic_yield: false, fixup_scopes: vec![], + extended_super_lets: Default::default(), }; visitor.scope_tree.root_body = Some(body.value.hir_id); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 83d095ab72e..6292d03bf6a 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -631,7 +631,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>( // Ignore `'static` lifetimes for the purpose of this lint: it's // because we know it outlives everything and so doesn't give meaningful // clues. Also ignore `ReError`, to avoid knock-down errors. - if let ty::ReStatic | ty::ReError(_) = **region_a { + if let ty::ReStatic | ty::ReError(_) = region_a.kind() { continue; } // For each region argument (e.g., `'a` in our example), check for a @@ -672,7 +672,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>( // Again, skip `'static` because it outlives everything. Also, we trivially // know that a region outlives itself. Also ignore `ReError`, to avoid // knock-down errors. - if matches!(**region_b, ty::ReStatic | ty::ReError(_)) || region_a == region_b { + if matches!(region_b.kind(), ty::ReStatic | ty::ReError(_)) || region_a == region_b { continue; } if region_known_to_outlive(tcx, item_def_id, param_env, wf_tys, *region_a, *region_b) { diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 1f3f0b754bb..8ad9d80c6b5 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -656,7 +656,7 @@ fn infringing_fields_error<'tcx>( .entry((ty.clone(), predicate.clone())) .or_default() .push(origin.span()); - if let ty::RegionKind::ReEarlyParam(ebr) = *b + if let ty::RegionKind::ReEarlyParam(ebr) = b.kind() && ebr.has_name() { bounds.push((b.to_string(), a.to_string(), None)); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 625f51dd29e..69b921fccbf 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -14,6 +14,7 @@ //! At present, however, we do run collection across all items in the //! crate as a kind of pass. This should eventually be factored away. +use std::assert_matches::assert_matches; use std::cell::Cell; use std::iter; use std::ops::Bound; @@ -42,7 +43,6 @@ use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::ObligationCtxt; use tracing::{debug, instrument}; -use crate::check::intrinsic::intrinsic_operation_unsafety; use crate::errors; use crate::hir_ty_lowering::errors::assoc_kind_str; use crate::hir_ty_lowering::{FeedConstTy, HirTyLowerer, RegionInferReason}; @@ -1345,7 +1345,8 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn compute_sig_of_foreign_fn_decl(tcx, def_id, sig.decl, abi, sig.header.safety()) } - Ctor(data) | Variant(hir::Variant { data, .. }) if data.ctor().is_some() => { + Ctor(data) => { + assert_matches!(data.ctor(), Some(_)); let adt_def_id = tcx.hir_get_parent_item(hir_id).def_id.to_def_id(); let ty = tcx.type_of(adt_def_id).instantiate_identity(); let inputs = data.fields().iter().map(|f| tcx.type_of(f.def_id).instantiate_identity()); @@ -1417,7 +1418,7 @@ fn recover_infer_ret_ty<'tcx>( GenericParamKind::Lifetime { .. } => true, _ => false, }); - let fn_sig = fold_regions(tcx, fn_sig, |r, _| match *r { + let fn_sig = fold_regions(tcx, fn_sig, |r, _| match r.kind() { ty::ReErased => { if has_region_params { ty::Region::new_error_with_message( @@ -1704,18 +1705,13 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( abi: ExternAbi, safety: hir::Safety, ) -> ty::PolyFnSig<'tcx> { - let safety = if abi == ExternAbi::RustIntrinsic { - intrinsic_operation_unsafety(tcx, def_id) - } else { - safety - }; let hir_id = tcx.local_def_id_to_hir_id(def_id); let fty = ItemCtxt::new(tcx, def_id).lowerer().lower_fn_ty(hir_id, safety, abi, decl, None, None); // Feature gate SIMD types in FFI, since I am not sure that the // ABIs are handled at all correctly. -huonw - if abi != ExternAbi::RustIntrinsic && !tcx.features().simd_ffi() { + if !tcx.features().simd_ffi() { let check = |hir_ty: &hir::Ty<'_>, ty: Ty<'_>| { if ty.is_simd() { let snip = tcx diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 776b23bea8e..e90a1cc24c1 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -172,33 +172,9 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen }; if let Node::TraitItem(item) = node { - let parent = tcx.local_parent(item.hir_id().owner.def_id); - let Node::Item(parent_trait) = tcx.hir_node_by_def_id(parent) else { - unreachable!(); - }; - - let (trait_generics, trait_bounds) = match parent_trait.kind { - hir::ItemKind::Trait(_, _, _, generics, supertraits, _) => (generics, supertraits), - hir::ItemKind::TraitAlias(_, generics, supertraits) => (generics, supertraits), - _ => unreachable!(), - }; - - // Implicitly add `Self: DefaultAutoTrait` clauses on trait associated items if - // they are not added as super trait bounds to the trait itself. See comment on - // `requires_default_supertraits` for more details. - if !icx.lowerer().requires_default_supertraits(trait_bounds, trait_generics) { - let mut bounds = Vec::new(); - let self_ty_where_predicates = (parent, item.generics.predicates); - icx.lowerer().add_default_traits_with_filter( - &mut bounds, - tcx.types.self_param, - &[], - Some(self_ty_where_predicates), - item.span, - |tr| tr != hir::LangItem::Sized, - ); - predicates.extend(bounds); - } + let mut bounds = Vec::new(); + icx.lowerer().add_default_trait_item_bounds(item, &mut bounds); + predicates.extend(bounds); } let generics = tcx.generics_of(def_id); @@ -383,7 +359,7 @@ fn compute_bidirectional_outlives_predicates<'tcx>( ) { for param in opaque_own_params { let orig_lifetime = tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local()); - if let ty::ReEarlyParam(..) = *orig_lifetime { + if let ty::ReEarlyParam(..) = orig_lifetime.kind() { let dup_lifetime = ty::Region::new_early_param( tcx, ty::EarlyParamRegion { index: param.index, name: param.name }, diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index 3fe3d71b32d..772197a53ac 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -183,25 +183,23 @@ impl<'tcx> TaitConstraintLocator<'tcx> { self.non_defining_use_in_defining_scope(item_def_id); } } - DefiningScopeKind::MirBorrowck => { - let borrowck_result = tcx.mir_borrowck(item_def_id); - if let Some(guar) = borrowck_result.tainted_by_errors { - self.insert_found(ty::OpaqueHiddenType::new_error(tcx, guar)); - } else if let Some(&hidden_type) = - borrowck_result.concrete_opaque_types.get(&self.def_id) - { - debug!(?hidden_type, "found constraint"); - self.insert_found(hidden_type); - } else if let Err(guar) = tcx - .type_of_opaque_hir_typeck(self.def_id) - .instantiate_identity() - .error_reported() - { - self.insert_found(ty::OpaqueHiddenType::new_error(tcx, guar)); - } else { - self.non_defining_use_in_defining_scope(item_def_id); + DefiningScopeKind::MirBorrowck => match tcx.mir_borrowck(item_def_id) { + Err(guar) => self.insert_found(ty::OpaqueHiddenType::new_error(tcx, guar)), + Ok(concrete_opaque_types) => { + if let Some(&hidden_type) = concrete_opaque_types.0.get(&self.def_id) { + debug!(?hidden_type, "found constraint"); + self.insert_found(hidden_type); + } else if let Err(guar) = tcx + .type_of_opaque_hir_typeck(self.def_id) + .instantiate_identity() + .error_reported() + { + self.insert_found(ty::OpaqueHiddenType::new_error(tcx, guar)); + } else { + self.non_defining_use_in_defining_scope(item_def_id); + } } - } + }, } } } @@ -264,20 +262,20 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>( Ty::new_diverging_default(tcx) } } - DefiningScopeKind::MirBorrowck => { - let borrowck_result = tcx.mir_borrowck(owner_def_id); - if let Some(guar) = borrowck_result.tainted_by_errors { - Ty::new_error(tcx, guar) - } else if let Some(hidden_ty) = borrowck_result.concrete_opaque_types.get(&def_id) { - hidden_ty.ty - } else { - let hir_ty = tcx.type_of_opaque_hir_typeck(def_id).instantiate_identity(); - if let Err(guar) = hir_ty.error_reported() { - Ty::new_error(tcx, guar) + DefiningScopeKind::MirBorrowck => match tcx.mir_borrowck(owner_def_id) { + Ok(concrete_opaque_types) => { + if let Some(hidden_ty) = concrete_opaque_types.0.get(&def_id) { + hidden_ty.ty } else { - hir_ty + let hir_ty = tcx.type_of_opaque_hir_typeck(def_id).instantiate_identity(); + if let Err(guar) = hir_ty.error_reported() { + Ty::new_error(tcx, guar) + } else { + hir_ty + } } } - } + Err(guar) => Ty::new_error(tcx, guar), + }, } } diff --git a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs index 53866aa27b1..951eda72ffe 100644 --- a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs +++ b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs @@ -80,7 +80,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ParameterCollector { } fn visit_region(&mut self, r: ty::Region<'tcx>) { - if let ty::ReEarlyParam(data) = *r { + if let ty::ReEarlyParam(data) = r.kind() { self.parameters.push(Parameter::from(data)); } } diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index f2560f22874..e6090a128b1 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -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, +} diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index c3bb860538e..55087d1f400 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -43,12 +43,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } /// Checks whether `Self: DefaultAutoTrait` bounds should be added on trait super bounds - /// or associative items. + /// or associated items. /// /// To keep backward compatibility with existing code, `experimental_default_bounds` bounds /// should be added everywhere, including super bounds. However this causes a huge performance /// costs. For optimization purposes instead of adding default supertraits, bounds - /// are added to the associative items: + /// are added to the associated items: /// /// ```ignore(illustrative) /// // Default bounds are generated in the following way: @@ -81,7 +81,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// /// Therefore, `experimental_default_bounds` are still being added to supertraits if /// the `SelfTyParam` or `AssocItemConstraint` were found in a trait header. - pub(crate) fn requires_default_supertraits( + fn requires_default_supertraits( &self, hir_bounds: &'tcx [hir::GenericBound<'tcx>], hir_generics: &'tcx hir::Generics<'tcx>, @@ -120,6 +120,43 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { found } + /// Implicitly add `Self: DefaultAutoTrait` clauses on trait associated items if + /// they are not added as super trait bounds to the trait itself. See + /// `requires_default_supertraits` for more information. + pub(crate) fn add_default_trait_item_bounds( + &self, + trait_item: &hir::TraitItem<'tcx>, + bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, + ) { + let tcx = self.tcx(); + if !tcx.sess.opts.unstable_opts.experimental_default_bounds { + return; + } + + let parent = tcx.local_parent(trait_item.hir_id().owner.def_id); + let hir::Node::Item(parent_trait) = tcx.hir_node_by_def_id(parent) else { + unreachable!(); + }; + + let (trait_generics, trait_bounds) = match parent_trait.kind { + hir::ItemKind::Trait(_, _, _, generics, supertraits, _) => (generics, supertraits), + hir::ItemKind::TraitAlias(_, generics, supertraits) => (generics, supertraits), + _ => unreachable!(), + }; + + if !self.requires_default_supertraits(trait_bounds, trait_generics) { + let self_ty_where_predicates = (parent, trait_item.generics.predicates); + self.add_default_traits_with_filter( + bounds, + tcx.types.self_param, + &[], + Some(self_ty_where_predicates), + trait_item.span, + |tr| tr != hir::LangItem::Sized, + ); + } + } + /// Lazily sets `experimental_default_bounds` to true on trait super bounds. /// See `requires_default_supertraits` for more information. pub(crate) fn add_default_super_traits( @@ -130,6 +167,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir_generics: &'tcx hir::Generics<'tcx>, span: Span, ) { + if !self.tcx().sess.opts.unstable_opts.experimental_default_bounds { + return; + } + assert!(matches!(self.tcx().def_kind(trait_def_id), DefKind::Trait | DefKind::TraitAlias)); if self.requires_default_supertraits(hir_bounds, hir_generics) { let self_ty_where_predicates = (trait_def_id, hir_generics.predicates); @@ -263,11 +304,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { seen_unbound = true; } let emit_relax_err = || { - let unbound_traits = - match self.tcx().sess.opts.unstable_opts.experimental_default_bounds { - true => "`?Sized` and `experimental_default_bounds`", - false => "`?Sized`", - }; + let unbound_traits = match tcx.sess.opts.unstable_opts.experimental_default_bounds { + true => "`?Sized` and `experimental_default_bounds`", + false => "`?Sized`", + }; // There was a `?Trait` bound, but it was neither `?Sized` nor `experimental_default_bounds`. tcx.dcx().span_err( unbound.span, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index aeebe45f881..e64cd8ec302 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -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, }; @@ -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( diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index c01b81563dc..64c1a78bd1c 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -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; @@ -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, diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs index a0faa5e8429..780c27d4595 100644 --- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs +++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs @@ -24,8 +24,8 @@ pub(super) fn infer_predicates( // If new predicates were added then we need to re-calculate // all crates since there could be new implied predicates. - loop { - let mut predicates_added = false; + for i in 0.. { + let mut predicates_added = vec![]; // Visit all the crates and infer predicates for id in tcx.hir_free_items() { @@ -83,14 +83,27 @@ pub(super) fn infer_predicates( .get(&item_did.to_def_id()) .map_or(0, |p| p.as_ref().skip_binder().len()); if item_required_predicates.len() > item_predicates_len { - predicates_added = true; + predicates_added.push(item_did); global_inferred_outlives .insert(item_did.to_def_id(), ty::EarlyBinder::bind(item_required_predicates)); } } - if !predicates_added { + if predicates_added.is_empty() { + // We've reached a fixed point. break; + } else if !tcx.recursion_limit().value_within_limit(i) { + let msg = if let &[id] = &predicates_added[..] { + format!("overflow computing implied lifetime bounds for `{}`", tcx.def_path_str(id),) + } else { + "overflow computing implied lifetime bounds".to_string() + }; + tcx.dcx() + .struct_span_fatal( + predicates_added.iter().map(|id| tcx.def_span(*id)).collect::<Vec<_>>(), + msg, + ) + .emit(); } } diff --git a/compiler/rustc_hir_analysis/src/outlives/utils.rs b/compiler/rustc_hir_analysis/src/outlives/utils.rs index d0a2a2230ab..044fb64ca82 100644 --- a/compiler/rustc_hir_analysis/src/outlives/utils.rs +++ b/compiler/rustc_hir_analysis/src/outlives/utils.rs @@ -146,7 +146,7 @@ pub(crate) fn insert_outlives_predicate<'tcx>( fn is_free_region(region: Region<'_>) -> bool { // First, screen for regions that might appear in a type header. - match *region { + match region.kind() { // These correspond to `T: 'a` relationships: // // struct Foo<'a, T> { diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index 8475903c68f..23223de918c 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -428,7 +428,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { region: ty::Region<'tcx>, variance: VarianceTermPtr<'a>, ) { - match *region { + match region.kind() { ty::ReEarlyParam(ref data) => { self.add_constraint(current, data.index, variance); } diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 0800d99e945..dbba45dc7bb 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -44,13 +44,13 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] { return &[]; } - match tcx.def_kind(item_def_id) { + let kind = tcx.def_kind(item_def_id); + match kind { DefKind::Fn | DefKind::AssocFn | DefKind::Enum | DefKind::Struct | DefKind::Union - | DefKind::Variant | DefKind::Ctor(..) => { // These are inferred. let crate_map = tcx.crate_variances(()); @@ -89,7 +89,11 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] { } // Variance not relevant. - span_bug!(tcx.def_span(item_def_id), "asked to compute variance for wrong kind of item"); + span_bug!( + tcx.def_span(item_def_id), + "asked to compute variance for {}", + kind.descr(item_def_id.to_def_id()) + ); } #[derive(Debug, Copy, Clone)] |
