diff options
Diffstat (limited to 'compiler')
28 files changed, 244 insertions, 204 deletions
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index b4556f8fcb8..5d7eb052561 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -29,8 +29,8 @@ use rustc_middle::middle::debugger_visualizer::{DebuggerVisualizerFile, Debugger use rustc_middle::middle::exported_symbols; use rustc_middle::middle::exported_symbols::SymbolExportKind; use rustc_middle::middle::lang_items; -use rustc_middle::mir::BinOp; use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem}; +use rustc_middle::mir::BinOp; use rustc_middle::query::Providers; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 5fbf5b41109..5fbf5b41109 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs diff --git a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs b/compiler/rustc_const_eval/src/check_consts/mod.rs index 308b90cd470..308b90cd470 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs +++ b/compiler/rustc_const_eval/src/check_consts/mod.rs diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index 8406e0f4876..8406e0f4876 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs diff --git a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs index f0763f1e490..f0763f1e490 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs +++ b/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs index 5949444e599..5949444e599 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs diff --git a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs b/compiler/rustc_const_eval/src/check_consts/resolver.rs index 011341472b4..011341472b4 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs +++ b/compiler/rustc_const_eval/src/check_consts/resolver.rs diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index 7a1c2a7b6fa..650669ac690 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -139,10 +139,9 @@ where ErrorHandled::TooGeneric(span) } err_inval!(AlreadyReported(guar)) => ErrorHandled::Reported(guar, span), - err_inval!(Layout(LayoutError::ReferencesError(guar))) => ErrorHandled::Reported( - ReportedErrorInfo::tainted_by_errors(guar), - span, - ), + err_inval!(Layout(LayoutError::ReferencesError(guar))) => { + ErrorHandled::Reported(ReportedErrorInfo::tainted_by_errors(guar), span) + } // Report remaining errors. _ => { let (our_span, frames) = get_span_and_frames(); diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index b14780c0d98..3a7c87c1cad 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -14,10 +14,10 @@ #![feature(yeet_expr)] #![feature(if_let_guard)] +pub mod check_consts; pub mod const_eval; mod errors; pub mod interpret; -pub mod transform; pub mod util; use std::sync::atomic::AtomicBool; diff --git a/compiler/rustc_const_eval/src/transform/mod.rs b/compiler/rustc_const_eval/src/transform/mod.rs deleted file mode 100644 index e3582c7d317..00000000000 --- a/compiler/rustc_const_eval/src/transform/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod check_consts; -pub mod validate; diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 50fe20346cf..8506b8d75f9 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -164,9 +164,8 @@ pub fn check_intrinsic_type( ) { let generics = tcx.generics_of(intrinsic_id); let param = |n| { - if let Some(&ty::GenericParamDef { - name, kind: ty::GenericParamDefKind::Type { .. }, .. - }) = generics.opt_param_at(n as usize, tcx) + if let &ty::GenericParamDef { name, kind: ty::GenericParamDefKind::Type { .. }, .. } = + generics.param_at(n as usize, tcx) { Ty::new_param(tcx, n, name) } else { diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index db36aba7edf..606f1653767 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -461,83 +461,55 @@ pub(super) fn explicit_predicates_of<'tcx>( } } } else { - if matches!(def_kind, DefKind::AnonConst) && tcx.features().generic_const_exprs { - let hir_id = tcx.local_def_id_to_hir_id(def_id); - let parent_def_id = tcx.hir().get_parent_item(hir_id); - - if let Some(defaulted_param_def_id) = - tcx.hir().opt_const_param_default_param_def_id(hir_id) - { - // In `generics_of` we set the generics' parent to be our parent's parent which means that - // we lose out on the predicates of our actual parent if we dont return those predicates here. - // (See comment in `generics_of` for more information on why the parent shenanigans is necessary) - // - // struct Foo<T, const N: usize = { <T as Trait>::ASSOC }>(T) where T: Trait; - // ^^^ ^^^^^^^^^^^^^^^^^^^^^^^ the def id we are calling - // ^^^ explicit_predicates_of on - // parent item we dont have set as the - // parent of generics returned by `generics_of` - // - // In the above code we want the anon const to have predicates in its param env for `T: Trait` - // and we would be calling `explicit_predicates_of(Foo)` here - let parent_preds = tcx.explicit_predicates_of(parent_def_id); - - // If we dont filter out `ConstArgHasType` predicates then every single defaulted const parameter - // will ICE because of #106994. FIXME(generic_const_exprs): remove this when a more general solution - // to #106994 is implemented. - let filtered_predicates = parent_preds - .predicates - .into_iter() - .filter(|(pred, _)| { - if let ty::ClauseKind::ConstArgHasType(ct, _) = pred.kind().skip_binder() { - match ct.kind() { - ty::ConstKind::Param(param_const) => { - let defaulted_param_idx = tcx - .generics_of(parent_def_id) - .param_def_id_to_index[&defaulted_param_def_id.to_def_id()]; - param_const.index < defaulted_param_idx - } - _ => bug!( - "`ConstArgHasType` in `predicates_of`\ - that isn't a `Param` const" - ), + if matches!(def_kind, DefKind::AnonConst) + && tcx.features().generic_const_exprs + && let Some(defaulted_param_def_id) = + tcx.hir().opt_const_param_default_param_def_id(tcx.local_def_id_to_hir_id(def_id)) + { + // In `generics_of` we set the generics' parent to be our parent's parent which means that + // we lose out on the predicates of our actual parent if we dont return those predicates here. + // (See comment in `generics_of` for more information on why the parent shenanigans is necessary) + // + // struct Foo<T, const N: usize = { <T as Trait>::ASSOC }>(T) where T: Trait; + // ^^^ ^^^^^^^^^^^^^^^^^^^^^^^ the def id we are calling + // ^^^ explicit_predicates_of on + // parent item we dont have set as the + // parent of generics returned by `generics_of` + // + // In the above code we want the anon const to have predicates in its param env for `T: Trait` + // and we would be calling `explicit_predicates_of(Foo)` here + let parent_def_id = tcx.local_parent(def_id); + let parent_preds = tcx.explicit_predicates_of(parent_def_id); + + // If we dont filter out `ConstArgHasType` predicates then every single defaulted const parameter + // will ICE because of #106994. FIXME(generic_const_exprs): remove this when a more general solution + // to #106994 is implemented. + let filtered_predicates = parent_preds + .predicates + .into_iter() + .filter(|(pred, _)| { + if let ty::ClauseKind::ConstArgHasType(ct, _) = pred.kind().skip_binder() { + match ct.kind() { + ty::ConstKind::Param(param_const) => { + let defaulted_param_idx = tcx + .generics_of(parent_def_id) + .param_def_id_to_index[&defaulted_param_def_id.to_def_id()]; + param_const.index < defaulted_param_idx } - } else { - true + _ => bug!( + "`ConstArgHasType` in `predicates_of`\ + that isn't a `Param` const" + ), } - }) - .cloned(); - return GenericPredicates { - parent: parent_preds.parent, - predicates: { tcx.arena.alloc_from_iter(filtered_predicates) }, - }; - } - - let parent_def_kind = tcx.def_kind(parent_def_id); - if matches!(parent_def_kind, DefKind::OpaqueTy) { - // In `instantiate_identity` we inherit the predicates of our parent. - // However, opaque types do not have a parent (see `gather_explicit_predicates_of`), which means - // that we lose out on the predicates of our actual parent if we dont return those predicates here. - // - // - // fn foo<T: Trait>() -> impl Iterator<Output = Another<{ <T as Trait>::ASSOC }> > { todo!() } - // ^^^^^^^^^^^^^^^^^^^ the def id we are calling - // explicit_predicates_of on - // - // In the above code we want the anon const to have predicates in its param env for `T: Trait`. - // However, the anon const cannot inherit predicates from its parent since it's opaque. - // - // To fix this, we call `explicit_predicates_of` directly on `foo`, the parent's parent. - - // In the above example this is `foo::{opaque#0}` or `impl Iterator` - let parent_hir_id = tcx.local_def_id_to_hir_id(parent_def_id.def_id); - - // In the above example this is the function `foo` - let item_def_id = tcx.hir().get_parent_item(parent_hir_id); - - // In the above code example we would be calling `explicit_predicates_of(foo)` here - return tcx.explicit_predicates_of(item_def_id); - } + } else { + true + } + }) + .cloned(); + return GenericPredicates { + parent: parent_preds.parent, + predicates: { tcx.arena.alloc_from_iter(filtered_predicates) }, + }; } gather_explicit_predicates_of(tcx, def_id) } diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index 72b95a9603d..6f499947d5c 100644 --- a/compiler/rustc_hir_typeck/messages.ftl +++ b/compiler/rustc_hir_typeck/messages.ftl @@ -137,6 +137,10 @@ hir_typeck_rpit_change_return_type = you could change the return type to be a bo hir_typeck_rustcall_incorrect_args = functions with the "rust-call" ABI must take a single non-self tuple argument +hir_typeck_self_ctor_from_outer_item = can't reference `Self` constructor from outer item + .label = the inner item doesn't inherit generics from this impl, so `Self` is invalid to reference + .suggestion = replace `Self` with the actual type + hir_typeck_struct_expr_non_exhaustive = cannot create non-exhaustive {$what} using struct expression diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index f250b909596..3f12f252654 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -651,3 +651,31 @@ pub enum SuggestBoxingForReturnImplTrait { ends: Vec<Span>, }, } + +#[derive(Diagnostic)] +#[diag(hir_typeck_self_ctor_from_outer_item, code = E0401)] +pub struct SelfCtorFromOuterItem { + #[primary_span] + pub span: Span, + #[label] + pub impl_span: Span, + #[subdiagnostic] + pub sugg: Option<ReplaceWithName>, +} + +#[derive(LintDiagnostic)] +#[diag(hir_typeck_self_ctor_from_outer_item)] +pub struct SelfCtorFromOuterItemLint { + #[label] + pub impl_span: Span, + #[subdiagnostic] + pub sugg: Option<ReplaceWithName>, +} + +#[derive(Subdiagnostic)] +#[suggestion(hir_typeck_suggestion, code = "{name}", applicability = "machine-applicable")] +pub struct ReplaceWithName { + #[primary_span] + pub span: Span, + pub name: String, +} diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 77f90c0c131..074aca78933 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1,5 +1,5 @@ use crate::callee::{self, DeferredCallResolution}; -use crate::errors::CtorIsPrivate; +use crate::errors::{self, CtorIsPrivate}; use crate::method::{self, MethodCallee, SelfSource}; use crate::rvalue_scopes; use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, LoweredTy}; @@ -21,6 +21,7 @@ use rustc_hir_analysis::hir_ty_lowering::{ use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse}; use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; use rustc_infer::infer::{DefineOpaqueTypes, InferResult}; +use rustc_lint::builtin::SELF_CONSTRUCTOR_FROM_OUTER_ITEM; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::fold::TypeFoldable; @@ -1156,6 +1157,43 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span, tcx.at(span).type_of(impl_def_id).instantiate_identity(), ); + + // Firstly, check that this SelfCtor even comes from the item we're currently + // typechecking. This can happen because we never validated the resolution of + // SelfCtors, and when we started doing so, we noticed regressions. After + // sufficiently long time, we can remove this check and turn it into a hard + // error in `validate_res_from_ribs` -- it's just difficult to tell whether the + // self type has any generic types during rustc_resolve, which is what we use + // to determine if this is a hard error or warning. + if std::iter::successors(Some(self.body_id.to_def_id()), |def_id| { + self.tcx.generics_of(def_id).parent + }) + .all(|def_id| def_id != impl_def_id) + { + let sugg = ty.normalized.ty_adt_def().map(|def| errors::ReplaceWithName { + span: path_span, + name: self.tcx.item_name(def.did()).to_ident_string(), + }); + if ty.raw.has_param() { + let guar = self.tcx.dcx().emit_err(errors::SelfCtorFromOuterItem { + span: path_span, + impl_span: tcx.def_span(impl_def_id), + sugg, + }); + return (Ty::new_error(self.tcx, guar), res); + } else { + self.tcx.emit_node_span_lint( + SELF_CONSTRUCTOR_FROM_OUTER_ITEM, + hir_id, + path_span, + errors::SelfCtorFromOuterItemLint { + impl_span: tcx.def_span(impl_def_id), + sugg, + }, + ); + } + } + match ty.normalized.ty_adt_def() { Some(adt_def) if adt_def.has_ctor() => { let (ctor_kind, ctor_def_id) = adt_def.non_enum_variant().ctor.unwrap(); diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index b9a99fbec3c..86fe2756b59 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -235,11 +235,17 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti if let Some(item) = tcx.opt_associated_item(def_id.into()) && let ty::AssocKind::Const = item.kind && let ty::ImplContainer = item.container - && let Some(trait_item) = item.trait_item_def_id + && let Some(trait_item_def_id) = item.trait_item_def_id { - let args = - tcx.impl_trait_ref(item.container_id(tcx)).unwrap().instantiate_identity().args; - Some(tcx.type_of(trait_item).instantiate(tcx, args)) + let impl_def_id = item.container_id(tcx); + let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity(); + let args = ty::GenericArgs::identity_for_item(tcx, def_id).rebase_onto( + tcx, + impl_def_id, + impl_trait_ref.args, + ); + tcx.check_args_compatible(trait_item_def_id, args) + .then(|| tcx.type_of(trait_item_def_id).instantiate(tcx, args)) } else { Some(fcx.next_ty_var(span)) } diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 87b76b978b9..25b74dca12f 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -381,10 +381,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let maybe_missing_semi = self.check_for_missing_semi(expr, &mut err); // We defer to the later error produced by `check_lhs_assignable`. - // We only downgrade this if it's the LHS, though. + // We only downgrade this if it's the LHS, though, and if this is a + // valid assignment statement. if maybe_missing_semi && let hir::Node::Expr(parent) = self.tcx.parent_hir_node(expr.hir_id) && let hir::ExprKind::Assign(lhs, _, _) = parent.kind + && let hir::Node::Stmt(stmt) = self.tcx.parent_hir_node(parent.hir_id) + && let hir::StmtKind::Expr(_) | hir::StmtKind::Semi(_) = stmt.kind && lhs.hir_id == expr.hir_id { err.downgrade_to_delayed_bug(); diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index 6c3f73cf465..af667a57ce1 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -116,8 +116,7 @@ fn load_dep_graph(sess: &Session) -> LoadResult<(Arc<SerializedDepGraph>, WorkPr if let LoadResult::Ok { data: (work_products_data, start_pos) } = load_result { // Decode the list of work_products - let Ok(mut work_product_decoder) = - MemDecoder::new(&work_products_data[..], start_pos) + let Ok(mut work_product_decoder) = MemDecoder::new(&work_products_data[..], start_pos) else { sess.dcx().emit_warn(errors::CorruptFile { path: &work_products_path }); return LoadResult::DataOutOfDate; diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs index f2fe43380b8..f4514c23508 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs @@ -54,17 +54,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } (ty::Param(expected), ty::Param(found)) => { let generics = tcx.generics_of(body_owner_def_id); - if let Some(param) = generics.opt_type_param(expected, tcx) { - let e_span = tcx.def_span(param.def_id); - if !sp.contains(e_span) { - diag.span_label(e_span, "expected type parameter"); - } + let e_span = tcx.def_span(generics.type_param(expected, tcx).def_id); + if !sp.contains(e_span) { + diag.span_label(e_span, "expected type parameter"); } - if let Some(param) = generics.opt_type_param(found, tcx) { - let f_span = tcx.def_span(param.def_id); - if !sp.contains(f_span) { - diag.span_label(f_span, "found type parameter"); - } + let f_span = tcx.def_span(generics.type_param(found, tcx).def_id); + if !sp.contains(f_span) { + diag.span_label(f_span, "found type parameter"); } diag.note( "a type parameter was expected, but a different one was found; \ @@ -87,29 +83,22 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { | (ty::Alias(ty::Projection, proj), ty::Param(p)) if !tcx.is_impl_trait_in_trait(proj.def_id) => { - let parent = tcx - .generics_of(body_owner_def_id) - .opt_type_param(p, tcx) - .and_then(|param| { - let p_def_id = param.def_id; - let p_span = tcx.def_span(p_def_id); - let expected = match (values.expected.kind(), values.found.kind()) { - (ty::Param(_), _) => "expected ", - (_, ty::Param(_)) => "found ", - _ => "", - }; - if !sp.contains(p_span) { - diag.span_label( - p_span, - format!("{expected}this type parameter"), - ); - } - p_def_id.as_local().and_then(|id| { - let local_id = tcx.local_def_id_to_hir_id(id); - let generics = tcx.parent_hir_node(local_id).generics()?; - Some((id, generics)) - }) - }); + let param = tcx.generics_of(body_owner_def_id).type_param(p, tcx); + let p_def_id = param.def_id; + let p_span = tcx.def_span(p_def_id); + let expected = match (values.expected.kind(), values.found.kind()) { + (ty::Param(_), _) => "expected ", + (_, ty::Param(_)) => "found ", + _ => "", + }; + if !sp.contains(p_span) { + diag.span_label(p_span, format!("{expected}this type parameter")); + } + let parent = p_def_id.as_local().and_then(|id| { + let local_id = tcx.local_def_id_to_hir_id(id); + let generics = tcx.parent_hir_node(local_id).generics()?; + Some((id, generics)) + }); let mut note = true; if let Some((local_id, generics)) = parent { // Synthesize the associated type restriction `Add<Output = Expected>`. @@ -183,16 +172,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { (ty::Param(p), ty::Dynamic(..) | ty::Alias(ty::Opaque, ..)) | (ty::Dynamic(..) | ty::Alias(ty::Opaque, ..), ty::Param(p)) => { let generics = tcx.generics_of(body_owner_def_id); - if let Some(param) = generics.opt_type_param(p, tcx) { - let p_span = tcx.def_span(param.def_id); - let expected = match (values.expected.kind(), values.found.kind()) { - (ty::Param(_), _) => "expected ", - (_, ty::Param(_)) => "found ", - _ => "", - }; - if !sp.contains(p_span) { - diag.span_label(p_span, format!("{expected}this type parameter")); - } + let p_span = tcx.def_span(generics.type_param(p, tcx).def_id); + let expected = match (values.expected.kind(), values.found.kind()) { + (ty::Param(_), _) => "expected ", + (_, ty::Param(_)) => "found ", + _ => "", + }; + if !sp.contains(p_span) { + diag.span_label(p_span, format!("{expected}this type parameter")); } diag.help("type parameters must be constrained to match other types"); if tcx.sess.teach(diag.code.unwrap()) { @@ -233,11 +220,9 @@ impl<T> Trait<T> for X { ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(..), ) => { let generics = tcx.generics_of(body_owner_def_id); - if let Some(param) = generics.opt_type_param(p, tcx) { - let p_span = tcx.def_span(param.def_id); - if !sp.contains(p_span) { - diag.span_label(p_span, "expected this type parameter"); - } + let p_span = tcx.def_span(generics.type_param(p, tcx).def_id); + if !sp.contains(p_span) { + diag.span_label(p_span, "expected this type parameter"); } diag.help(format!( "every closure has a distinct type and so could not always match the \ @@ -246,16 +231,14 @@ impl<T> Trait<T> for X { } (ty::Param(p), _) | (_, ty::Param(p)) => { let generics = tcx.generics_of(body_owner_def_id); - if let Some(param) = generics.opt_type_param(p, tcx) { - let p_span = tcx.def_span(param.def_id); - let expected = match (values.expected.kind(), values.found.kind()) { - (ty::Param(_), _) => "expected ", - (_, ty::Param(_)) => "found ", - _ => "", - }; - if !sp.contains(p_span) { - diag.span_label(p_span, format!("{expected}this type parameter")); - } + let p_span = tcx.def_span(generics.type_param(p, tcx).def_id); + let expected = match (values.expected.kind(), values.found.kind()) { + (ty::Param(_), _) => "expected ", + (_, ty::Param(_)) => "found ", + _ => "", + }; + if !sp.contains(p_span) { + diag.span_label(p_span, format!("{expected}this type parameter")); } } (ty::Alias(ty::Projection | ty::Inherent, proj_ty), _) @@ -545,10 +528,8 @@ impl<T> Trait<T> for X { return false; }; let generics = tcx.generics_of(body_owner_def_id); - let Some(param) = generics.opt_type_param(param_ty, tcx) else { - return false; - }; - let Some(def_id) = param.def_id.as_local() else { + let def_id = generics.type_param(param_ty, tcx).def_id; + let Some(def_id) = def_id.as_local() else { return false; }; diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 8d4011421bd..6f603d9b612 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -957,27 +957,14 @@ impl<'tcx> InferCtxt<'tcx> { (&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => { return Err((a_vid, b_vid)); } - // We don't silently want to constrain hidden types here, so we assert that either one side is - // an infer var, so it'll get constrained to whatever the other side is, or there are no opaque - // types involved. - // We don't expect this to actually get hit, but if it does, we now at least know how to write - // a test for it. - (_, ty::Infer(ty::TyVar(_))) => {} - (ty::Infer(ty::TyVar(_)), _) => {} - _ if r_a != r_b && (r_a, r_b).has_opaque_types() => { - span_bug!( - cause.span(), - "opaque types got hidden types registered from within subtype predicate: {r_a:?} vs {r_b:?}" - ) - } _ => {} } self.enter_forall(predicate, |ty::SubtypePredicate { a_is_expected, a, b }| { if a_is_expected { - Ok(self.at(cause, param_env).sub(DefineOpaqueTypes::Yes, a, b)) + Ok(self.at(cause, param_env).sub(DefineOpaqueTypes::No, a, b)) } else { - Ok(self.at(cause, param_env).sup(DefineOpaqueTypes::Yes, b, a)) + Ok(self.at(cause, param_env).sup(DefineOpaqueTypes::No, b, a)) } }) } diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs index b05f5e7638b..aa00fb4573d 100644 --- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs +++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs @@ -62,7 +62,9 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles { }; let (article, ty, var) = match adt.did() { - did if cx.tcx.is_diagnostic_item(sym::Option, did) && ref_mutability.is_some() => ("a", "Option", "Some"), + did if cx.tcx.is_diagnostic_item(sym::Option, did) && ref_mutability.is_some() => { + ("a", "Option", "Some") + } did if cx.tcx.is_diagnostic_item(sym::Option, did) => ("an", "Option", "Some"), did if cx.tcx.is_diagnostic_item(sym::Result, did) => ("a", "Result", "Ok"), _ => return, diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 82f16b31a66..617fe99ef6a 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -90,6 +90,7 @@ declare_lint_pass! { RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, RUST_2021_PRELUDE_COLLISIONS, RUST_2024_INCOMPATIBLE_PAT, + SELF_CONSTRUCTOR_FROM_OUTER_ITEM, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS, SINGLE_USE_LIFETIMES, SOFT_UNSTABLE, @@ -3150,6 +3151,47 @@ declare_lint! { } declare_lint! { + /// The `self_constructor_from_outer_item` lint detects cases where the `Self` constructor + /// was silently allowed due to a bug in the resolver, and which may produce surprising + /// and unintended behavior. + /// + /// Using a `Self` type alias from an outer item was never intended, but was silently allowed. + /// This is deprecated -- and is a hard error when the `Self` type alias references generics + /// that are not in scope. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(self_constructor_from_outer_item)] + /// + /// struct S0(usize); + /// + /// impl S0 { + /// fn foo() { + /// const C: S0 = Self(0); + /// fn bar() -> S0 { + /// Self(0) + /// } + /// } + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// The `Self` type alias should not be reachable because nested items are not associated with + /// the scope of the parameters from the parent item. + pub SELF_CONSTRUCTOR_FROM_OUTER_ITEM, + Warn, + "detect unsupported use of `Self` from outer item", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, + reference: "issue #124186 <https://github.com/rust-lang/rust/issues/124186>", + }; +} + +declare_lint! { /// The `semicolon_in_expressions_from_macros` lint detects trailing semicolons /// in macro bodies when the macro is invoked in expression position. /// This was previous accepted, but is being phased out. diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 870e4865aea..1c4462fc1dc 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -245,20 +245,6 @@ impl<'tcx> Generics { } } - /// Returns the `GenericParamDef` with the given index if available. - pub fn opt_param_at( - &'tcx self, - param_index: usize, - tcx: TyCtxt<'tcx>, - ) -> Option<&'tcx GenericParamDef> { - if let Some(index) = param_index.checked_sub(self.parent_count) { - self.own_params.get(index) - } else { - tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?")) - .opt_param_at(param_index, tcx) - } - } - pub fn params_to(&'tcx self, param_index: usize, tcx: TyCtxt<'tcx>) -> &'tcx [GenericParamDef] { if let Some(index) = param_index.checked_sub(self.parent_count) { &self.own_params[..index] @@ -290,20 +276,6 @@ impl<'tcx> Generics { } } - /// Returns the `GenericParamDef` associated with this `ParamTy` if it belongs to this - /// `Generics`. - pub fn opt_type_param( - &'tcx self, - param: ParamTy, - tcx: TyCtxt<'tcx>, - ) -> Option<&'tcx GenericParamDef> { - let param = self.opt_param_at(param.index as usize, tcx)?; - match param.kind { - GenericParamDefKind::Type { .. } => Some(param), - _ => None, - } - } - /// Returns the `GenericParamDef` associated with this `ParamConst`. pub fn const_param(&'tcx self, param: ParamConst, tcx: TyCtxt<'tcx>) -> &GenericParamDef { let param = self.param_at(param.index as usize, tcx); diff --git a/compiler/rustc_mir_transform/Cargo.toml b/compiler/rustc_mir_transform/Cargo.toml index bd0a54ef363..f864a13a31b 100644 --- a/compiler/rustc_mir_transform/Cargo.toml +++ b/compiler/rustc_mir_transform/Cargo.toml @@ -16,6 +16,7 @@ rustc_errors = { path = "../rustc_errors" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } +rustc_infer = { path = "../rustc_infer" } rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } rustc_mir_build = { path = "../rustc_mir_build" } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 401056cd496..fe2237dd2e9 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -1,7 +1,6 @@ //! Inlining pass for MIR functions use crate::deref_separator::deref_finder; use rustc_attr::InlineAttr; -use rustc_const_eval::transform::validate::validate_types; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_index::bit_set::BitSet; @@ -21,6 +20,7 @@ use rustc_target::spec::abi::Abi; use crate::cost_checker::CostChecker; use crate::simplify::simplify_cfg; use crate::util; +use crate::validate::validate_types; use std::iter; use std::ops::{Range, RangeFrom}; diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 9af48f0bad2..e4670633914 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -109,9 +109,9 @@ mod simplify_comparison_integral; mod sroa; mod unreachable_enum_branching; mod unreachable_prop; +mod validate; -use rustc_const_eval::transform::check_consts::{self, ConstCx}; -use rustc_const_eval::transform::validate; +use rustc_const_eval::check_consts::{self, ConstCx}; use rustc_mir_dataflow::rustc_peek; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index 34aa31baab7..e37f90ae7f4 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -30,7 +30,7 @@ use std::assert_matches::assert_matches; use std::cell::Cell; use std::{cmp, iter, mem}; -use rustc_const_eval::transform::check_consts::{qualifs, ConstCx}; +use rustc_const_eval::check_consts::{qualifs, ConstCx}; /// A `MirPass` for promotion. /// diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 3a2b2c5f300..66cc65de647 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -685,6 +685,15 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { check_equal(self, location, *f_ty); } ty::Adt(adt_def, args) => { + // see <https://github.com/rust-lang/rust/blob/7601adcc764d42c9f2984082b49948af652df986/compiler/rustc_middle/src/ty/layout.rs#L861-L864> + if Some(adt_def.did()) == self.tcx.lang_items().dyn_metadata() { + self.fail( + location, + format!("You can't project to field {f:?} of `DynMetadata` because \ + layout is weird and thinks it doesn't have fields."), + ); + } + let var = parent_ty.variant_index.unwrap_or(FIRST_VARIANT); let Some(field) = adt_def.variant(var).fields.get(f) else { fail_out_of_bounds(self, location); |
