diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index 2bc521d5bbe0b..4bb5b4a54afe7 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -13,7 +13,7 @@ where T: TypeVisitable<'tcx>, { debug!("ensure_monomorphic_enough: ty={:?}", ty); - if !ty.needs_subst() { + if !(ty.needs_subst() || ty.has_opaque_types()) { return Ok(()); } @@ -31,7 +31,7 @@ where } match *ty.kind() { - ty::Param(_) => ControlFlow::Break(FoundParam), + ty::Param(_) | ty::Opaque(..) => ControlFlow::Break(FoundParam), ty::Closure(def_id, substs) | ty::Generator(def_id, substs, ..) | ty::FnDef(def_id, substs) => { diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 4aa98cb13d82b..561d352dbf568 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -2,6 +2,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_index::bit_set::BitSet; +use rustc_infer::infer::DefiningAnchor; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::visit::NonUseContext::VarDebugInfo; @@ -12,13 +13,14 @@ use rustc_middle::mir::{ ProjectionElem, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind, Terminator, TerminatorKind, UnOp, START_BLOCK, }; -use rustc_middle::ty::fold::BottomUpFolder; +use rustc_middle::traits::ObligationCause; use rustc_middle::ty::subst::Subst; -use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeFoldable, TypeVisitable}; +use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitable}; use rustc_mir_dataflow::impls::MaybeStorageLive; use rustc_mir_dataflow::storage::always_storage_live_locals; use rustc_mir_dataflow::{Analysis, ResultsCursor}; use rustc_target::abi::{Size, VariantIdx}; +use rustc_trait_selection::traits::ObligationCtxt; #[derive(Copy, Clone, Debug)] enum EdgeKind { @@ -88,25 +90,36 @@ pub fn equal_up_to_regions<'tcx>( return true; } - // Normalize lifetimes away on both sides, then compare. - let normalize = |ty: Ty<'tcx>| { - tcx.try_normalize_erasing_regions(param_env, ty).unwrap_or(ty).fold_with( - &mut BottomUpFolder { - tcx, - // FIXME: We erase all late-bound lifetimes, but this is not fully correct. - // If you have a type like ` fn(&'a u32) as SomeTrait>::Assoc`, - // this is not necessarily equivalent to `::Assoc`, - // since one may have an `impl SomeTrait for fn(&32)` and - // `impl SomeTrait for fn(&'static u32)` at the same time which - // specify distinct values for Assoc. (See also #56105) - lt_op: |_| tcx.lifetimes.re_erased, - // Leave consts and types unchanged. - ct_op: |ct| ct, - ty_op: |ty| ty, - }, - ) - }; - tcx.infer_ctxt().enter(|infcx| infcx.can_eq(param_env, normalize(src), normalize(dest)).is_ok()) + may_subtype_ignoring_regions(tcx, param_env, src, dest) + || may_subtype_ignoring_regions(tcx, param_env, dest, src) +} + +fn may_subtype_ignoring_regions<'tcx>( + tcx: TyCtxt<'tcx>, + param_env: ParamEnv<'tcx>, + src: Ty<'tcx>, + dest: Ty<'tcx>, +) -> bool { + let mut builder = + tcx.infer_ctxt().ignoring_regions().with_opaque_type_inference(DefiningAnchor::Bubble); + builder.enter(|infcx| { + let ocx = ObligationCtxt::new(&infcx); + let cause = ObligationCause::dummy(); + let src = ocx.normalize(cause.clone(), param_env, src); + let dest = ocx.normalize(cause.clone(), param_env, dest); + let Ok(infer_ok) = infcx.at(&cause, param_env).eq(src, dest) else { + return false; + }; + let () = ocx.register_infer_ok_obligations(infer_ok); + let errors = ocx.select_all_or_error(); + // With `Reveal::All`, opaque types get normalized away, with `Reveal::UserFacing` + // we would get unification errors because we're unable to look into opaque types, + // even if they're constrained in our current function. + // + // It seems very unlikely that this hides any bugs. + let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); + errors.is_empty() + }) } struct TypeChecker<'a, 'tcx> { @@ -189,16 +202,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // all normal lifetimes are erased, higher-ranked types with their // late-bound lifetimes are still around and can lead to type // differences. So we compare ignoring lifetimes. - - // First, try with reveal_all. This might not work in some cases, as the predicates - // can be cleared in reveal_all mode. We try the reveal first anyways as it is used - // by some other passes like inlining as well. - let param_env = self.param_env.with_reveal_all_normalized(self.tcx); - if equal_up_to_regions(self.tcx, param_env, src, dest) { - return true; - } - - // If this fails, we can try it without the reveal. equal_up_to_regions(self.tcx, self.param_env, src, dest) } } @@ -285,7 +288,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { this.fail( location, format!( - "Field projection `{:?}.{:?}` specified type `{:?}`, but actual type is {:?}", + "Field projection `{:?}.{:?}` specified type `{:?}`, but actual type is `{:?}`", parent, f, ty, f_ty ) ) diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 67526c2228937..5cf2ba39de7df 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -3199,4 +3199,13 @@ impl<'tcx> InferCtxt<'_, 'tcx> { _ => false, } } + + pub fn concrete_ctfe_failure_error(&self, span: Span) -> ErrorGuaranteed { + self.tcx + .sess + .struct_span_err(span, "unable to use constant with a hidden value in the type system") + .note("this most often happens when trying to look into an opaque type") + .note("the type system cannot access the hidden type of opaque types") + .emit() + } } diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index e5dfda24dc701..cd2ed3cbb841b 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3365,6 +3365,7 @@ declare_lint_pass! { DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, DUPLICATE_MACRO_ATTRIBUTES, SUSPICIOUS_AUTO_TRAIT_IMPLS, + HIDDEN_TYPE_OF_OPAQUE_TYPES_IN_TYPE_SYSTEM, DEPRECATED_WHERE_CLAUSE_LOCATION, TEST_UNSTABLE_LINT, FFI_UNWIND_CALLS, @@ -3981,6 +3982,47 @@ declare_lint! { }; } +declare_lint! { + /// The `hidden_type_of_opaque_types_in_type_system` backward compatibility + /// lint detects when the hidden type of an opaque type is required by the type + /// system. + /// + /// + /// ### Example + /// + /// ```rust + /// use std::mem::transmute; + /// fn foo() -> impl Sized { + /// 0u8 + /// } + /// + /// fn main() { + /// unsafe { + /// transmute::<_, u8>(foo()); + /// } + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// When using an opaque type, i.e. `impl Trait`, the + /// concrete underlying type should not be revealed to + /// the type system. The compiler previously revealed this + /// underlying type in some instances causing bugs. + /// It is still unclear whether this lint will be converted to + /// a hard error in the future or whether a different implementation + /// can support these use-cases. + pub HIDDEN_TYPE_OF_OPAQUE_TYPES_IN_TYPE_SYSTEM, + Warn, + "the rules governing auto traits will change in the future", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseError, + reference: "issue # ", + }; +} + declare_lint! { /// The `deprecated_where_clause_location` lint detects when a where clause in front of the equals /// in an associated type. diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 786927e2dad70..fe3daa64759a5 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -1,10 +1,11 @@ use super::{ErrorHandled, EvalToConstValueResult, EvalToValTreeResult, GlobalId}; use crate::mir; +use crate::traits::Reveal; use crate::ty::subst::InternalSubsts; use crate::ty::visit::TypeVisitable; use crate::ty::{self, query::TyCtxtAt, query::TyCtxtEnsure, TyCtxt}; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, CRATE_DEF_ID}; use rustc_span::{Span, DUMMY_SP}; impl<'tcx> TyCtxt<'tcx> { @@ -20,7 +21,9 @@ impl<'tcx> TyCtxt<'tcx> { let substs = InternalSubsts::identity_for_item(self, def_id); let instance = ty::Instance::new(def_id, substs); let cid = GlobalId { instance, promoted: None }; - let param_env = self.param_env(def_id).with_reveal_all_normalized(self); + // This function isn't used in the type system, so we're free to use + // `param_env_reveal_all_normalized` here. + let param_env = self.param_env_reveal_all_normalized(def_id); self.const_eval_global_id(param_env, cid, None) } /// Resolves and evaluates a constant. @@ -59,6 +62,42 @@ impl<'tcx> TyCtxt<'tcx> { } } + /// HACK: We retry evaluation with `Reveal::All` for backwards + /// compatability reasons, see #101478 for more details. + #[cold] + fn const_eval_resolve_for_typeck_backcompat_hack( + self, + param_env: ty::ParamEnv<'tcx>, + ct: ty::Unevaluated<'tcx>, + span: Option, + ) -> EvalToValTreeResult<'tcx> { + let param_env_reveal_all = ty::ParamEnv::new( + self.normalize_opaque_types(param_env.caller_bounds()), + Reveal::All, + param_env.constness(), + ); + + match self.const_eval_resolve_for_typeck(param_env_reveal_all, ct, span) { + Ok(Some(v)) => { + let local_def_id = ct.def.did.as_local().unwrap_or(CRATE_DEF_ID); + self.struct_span_lint_hir( + rustc_session::lint::builtin::HIDDEN_TYPE_OF_OPAQUE_TYPES_IN_TYPE_SYSTEM, + self.hir().local_def_id_to_hir_id(local_def_id), + self.def_span(ct.def.did), + |err| { + err.build( + "relying on the underlying type of an opaque type in the type system", + ) + .note("evaluating this constant relies on the underlying type of an opaque type") + .emit() + }, + ); + Ok(Some(v)) + } + res => res, + } + } + #[instrument(level = "debug", skip(self))] pub fn const_eval_resolve_for_typeck( self, @@ -76,13 +115,22 @@ impl<'tcx> TyCtxt<'tcx> { bug!("did not expect inference variables here"); } - match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) { + let result = match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) { Ok(Some(instance)) => { let cid = GlobalId { instance, promoted: ct.promoted }; self.const_eval_global_id_for_typeck(param_env, cid, span) } Ok(None) => Err(ErrorHandled::TooGeneric), Err(error_reported) => Err(ErrorHandled::Reported(error_reported)), + }; + + match result { + Err(ErrorHandled::TooGeneric) + if param_env.reveal() != Reveal::All && !ct.needs_subst() => + { + self.const_eval_resolve_for_typeck_backcompat_hack(param_env, ct, span) + } + result => result, } } @@ -184,8 +232,9 @@ impl<'tcx> TyCtxtEnsure<'tcx> { let substs = InternalSubsts::identity_for_item(self.tcx, def_id); let instance = ty::Instance::new(def_id, substs); let cid = GlobalId { instance, promoted: None }; - let param_env = - self.tcx.param_env(def_id).with_reveal_all_normalized(self.tcx).with_const(); + // This function isn't used in the type system, so we're free to use + // `param_env_reveal_all_normalized` here. + let param_env = self.tcx.param_env_reveal_all_normalized(def_id).with_const(); // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should // improve caching of queries. let inputs = self.tcx.erase_regions(param_env.and(cid)); diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index ac5fddb7ad1eb..a9e0a28013eed 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -84,7 +84,7 @@ impl<'tcx> ConstValue<'tcx> { param_env: ParamEnv<'tcx>, ty: Ty<'tcx>, ) -> Option { - let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size; + let size = tcx.layout_of(param_env.and(ty)).ok()?.size; self.try_to_bits(size) } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index af00118fcbeba..13f12a8dc7c87 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2164,8 +2164,7 @@ impl<'tcx> ConstantKind<'tcx> { Self::Ty(ct) => ct.try_eval_bits(tcx, param_env, ty), Self::Val(val, t) => { assert_eq!(*t, ty); - let size = - tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size; + let size = tcx.layout_of(param_env.and(ty)).ok()?.size; val.try_to_bits(size) } } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 53c254119f436..5a499cccc02db 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1238,8 +1238,6 @@ rustc_queries! { } /// Like `param_env`, but returns the `ParamEnv` in `Reveal::All` mode. - /// Prefer this over `tcx.param_env(def_id).with_reveal_all_normalized(tcx)`, - /// as this method is more efficient. query param_env_reveal_all_normalized(def_id: DefId) -> ty::ParamEnv<'tcx> { desc { |tcx| "computing revealed normalized predicates of `{}`", tcx.def_path_str(def_id) } } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 68a7af0b8c8d7..73e00c355b077 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -71,13 +71,17 @@ pub enum Reveal { /// Also, `impl Trait` is normalized to the concrete type, /// which has to be already collected by type-checking. /// - /// NOTE: as `impl Trait`'s concrete type should *never* - /// be observable directly by the user, `Reveal::All` - /// should not be used by checks which may expose - /// type equality or type contents to the user. - /// There are some exceptions, e.g., around auto traits and - /// transmute-checking, which expose some details, but - /// not the whole concrete type of the `impl Trait`. + /// **This should not be used at any point before borrowck** + /// + /// The concrete type of an opaque type should *never* + /// be observable directly by the user and doing so can cause + /// cycles if done before borrowck. Therefore, `Reveal::All` + /// should not be used by checks which may expose type equality + /// or type contents to the user. + /// + /// There are some places where we do observe some details about + /// the concrete type of opaque types, e.g., around auto traits and + /// transmute-checking, but these shouldn't rely on `Reveal::All`. All, } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 2eb5cffa6bc44..77f44af32ac56 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -250,7 +250,7 @@ impl<'tcx> Const<'tcx> { ty: Ty<'tcx>, ) -> Option { assert_eq!(self.ty(), ty); - let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size; + let size = tcx.layout_of(param_env.and(ty)).ok()?.size; // if `ty` does not depend on generic parameters, use an empty param_env self.kind().eval(tcx, param_env).try_to_bits(size) } diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index 2f7352e0aff24..42ade519491d8 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -184,16 +184,7 @@ impl<'tcx> ConstKind<'tcx> { if let ConstKind::Unevaluated(unevaluated) = self { use crate::mir::interpret::ErrorHandled; - // HACK(eddyb) this erases lifetimes even though `const_eval_resolve` - // also does later, but we want to do it before checking for - // inference variables. - // Note that we erase regions *before* calling `with_reveal_all_normalized`, - // so that we don't try to invoke this query with - // any region variables. - let param_env_and = tcx - .erase_regions(param_env) - .with_reveal_all_normalized(tcx) - .and(tcx.erase_regions(unevaluated)); + let param_env_and = tcx.erase_regions(param_env).and(tcx.erase_regions(unevaluated)); // HACK(eddyb) when the query key would contain inference variables, // attempt using identity substs and `ParamEnv` instead, that will succeed diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 042eeec3f4622..a2cf942596bf7 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -232,7 +232,6 @@ fn layout_of<'tcx>( let (param_env, ty) = query.into_parts(); debug!(?ty); - let param_env = param_env.with_reveal_all_normalized(tcx); let unnormalized_ty = ty; // FIXME: We might want to have two different versions of `layout_of`: diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index e8fe37e7dab73..82551a2f9b18e 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1618,27 +1618,6 @@ impl<'tcx> ParamEnv<'tcx> { *self = self.with_constness(constness.and(self.constness())) } - /// Returns a new parameter environment with the same clauses, but - /// which "reveals" the true results of projections in all cases - /// (even for associated types that are specializable). This is - /// the desired behavior during codegen and certain other special - /// contexts; normally though we want to use `Reveal::UserFacing`, - /// which is the default. - /// All opaque types in the caller_bounds of the `ParamEnv` - /// will be normalized to their underlying types. - /// See PR #65989 and issue #65918 for more details - pub fn with_reveal_all_normalized(self, tcx: TyCtxt<'tcx>) -> Self { - if self.packed.tag().reveal == traits::Reveal::All { - return self; - } - - ParamEnv::new( - tcx.normalize_opaque_types(self.caller_bounds()), - Reveal::All, - self.constness(), - ) - } - /// Returns this same environment but with no caller bounds. #[inline] pub fn without_caller_bounds(self) -> Self { diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 2c131a26d3a41..f34b4b480d604 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -478,11 +478,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { _ => return pat_from_kind(self.lower_variant_or_leaf(res, id, span, ty, vec![])), }; - // Use `Reveal::All` here because patterns are always monomorphic even if their function - // isn't. - let param_env_reveal_all = self.param_env.with_reveal_all_normalized(self.tcx); let substs = self.typeck_results.node_substs(id); - let instance = match ty::Instance::resolve(self.tcx, param_env_reveal_all, def_id, substs) { + let instance = match ty::Instance::resolve(self.tcx, self.param_env, def_id, substs) { Ok(Some(i)) => i, Ok(None) => { // It should be assoc consts if there's no error but we cannot resolve it. @@ -505,7 +502,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let mir_structural_match_violation = self.tcx.mir_const_qualif(instance.def_id()).custom_eq; debug!("mir_structural_match_violation({:?}) -> {}", qpath, mir_structural_match_violation); - match self.tcx.const_eval_instance(param_env_reveal_all, instance, Some(span)) { + match self.tcx.const_eval_instance(self.param_env, instance, Some(span)) { Ok(literal) => { let const_ = mir::ConstantKind::Val(literal, ty); let pattern = self.const_to_pat(const_, id, span, mir_structural_match_violation); diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index c0b0cc3c591b0..bb971165131e2 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -3,7 +3,6 @@ use rustc_hir::lang_items::LangItem; use rustc_index::vec::Idx; use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::*; -use rustc_middle::traits::Reveal; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -273,7 +272,6 @@ where let subpath = self.elaborator.field_subpath(variant_path, field); let tcx = self.tcx(); - assert_eq!(self.elaborator.param_env().reveal(), Reveal::All); let field_ty = tcx.normalize_erasing_regions(self.elaborator.param_env(), f.ty(tcx, substs)); (tcx.mk_place_field(base_place, field, field_ty), subpath) diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index 65f4956d23acd..4ddce50ef6d82 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -25,7 +25,7 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops { debug!("elaborate_drops({:?} @ {:?})", body.source, body.span); let def_id = body.source.def_id(); - let param_env = tcx.param_env_reveal_all_normalized(def_id); + let param_env = tcx.param_env(def_id); let (side_table, move_data) = match MoveData::gather_moves(body, tcx, param_env) { Ok(move_data) => move_data, Err((move_data, _)) => { diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs index fd03f657111d9..8221aa6995c5e 100644 --- a/compiler/rustc_passes/src/layout_test.rs +++ b/compiler/rustc_passes/src/layout_test.rs @@ -25,7 +25,7 @@ pub fn test_layout(tcx: TyCtxt<'_>) { fn dump_layout_of<'tcx>(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId, attr: &Attribute) { let tcx = tcx; - let param_env = tcx.param_env(item_def_id); + let param_env = tcx.param_env_reveal_all_normalized(item_def_id); let ty = tcx.type_of(item_def_id); match tcx.layout_of(param_env.and(ty)) { Ok(ty_layout) => { @@ -66,10 +66,7 @@ fn dump_layout_of<'tcx>(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId, attr: &Attri } sym::debug => { - let normalized_ty = tcx.normalize_erasing_regions( - param_env.with_reveal_all_normalized(tcx), - ty, - ); + let normalized_ty = tcx.normalize_erasing_regions(param_env, ty); tcx.sess.span_err( tcx.def_span(item_def_id.to_def_id()), &format!("layout_of({:?}) = {:#?}", normalized_ty, *ty_layout), diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 05738b6c48ae2..6cffa797beb14 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -136,7 +136,6 @@ fn resolve_associated_item<'tcx>( }); let substs = tcx.infer_ctxt().enter(|infcx| { - let param_env = param_env.with_reveal_all_normalized(tcx); let substs = rcvr_substs.rebase_onto(tcx, trait_def_id, impl_data.substs); let substs = translate_substs( &infcx, @@ -173,7 +172,11 @@ fn resolve_associated_item<'tcx>( // If the item does not have a value, then we cannot return an instance. if !leaf_def.item.defaultness(tcx).has_value() { - return Ok(None); + let guard = tcx.sess.delay_span_bug( + tcx.def_span(leaf_def.item.def_id), + "missing value for assoc item in impl", + ); + return Err(guard); } let substs = tcx.erase_regions(substs); diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 9266e4e3f6efb..6ff2c7d065166 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -335,7 +335,12 @@ fn well_formed_types_in_env<'tcx>( } fn param_env_reveal_all_normalized(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { - tcx.param_env(def_id).with_reveal_all_normalized(tcx) + let param_env = tcx.param_env(def_id); + ty::ParamEnv::new( + tcx.normalize_opaque_types(param_env.caller_bounds()), + traits::Reveal::All, + param_env.constness(), + ) } fn instance_def_size_estimate<'tcx>( diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 93b00850069c2..110f960f2dc10 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -541,7 +541,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // been resolved or we errored. This is important as we can only check transmute // on concrete types, but the output type may not be known yet (it would only // be known if explicitly specified via turbofish). - self.deferred_transmute_checks.borrow_mut().push((from, to, expr.span)); + self.deferred_transmute_checks.borrow_mut().push((from, to, expr.hir_id)); } if !tcx.features().unsized_fn_params { // We want to remove some Sized bounds from std functions, diff --git a/compiler/rustc_typeck/src/check/inherited.rs b/compiler/rustc_typeck/src/check/inherited.rs index 37c830d4e3850..2546227e13858 100644 --- a/compiler/rustc_typeck/src/check/inherited.rs +++ b/compiler/rustc_typeck/src/check/inherited.rs @@ -55,7 +55,7 @@ pub struct Inherited<'a, 'tcx> { pub(super) deferred_cast_checks: RefCell>>, - pub(super) deferred_transmute_checks: RefCell, Ty<'tcx>, Span)>>, + pub(super) deferred_transmute_checks: RefCell, Ty<'tcx>, hir::HirId)>>, pub(super) deferred_asm_checks: RefCell, hir::HirId)>>, diff --git a/compiler/rustc_typeck/src/check/intrinsicck.rs b/compiler/rustc_typeck/src/check/intrinsicck.rs index d8fe63dbf084a..8913be0c85734 100644 --- a/compiler/rustc_typeck/src/check/intrinsicck.rs +++ b/compiler/rustc_typeck/src/check/intrinsicck.rs @@ -1,12 +1,14 @@ use rustc_ast::InlineAsmTemplatePiece; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::struct_span_err; +use rustc_errors::{struct_span_err, ErrorGuaranteed}; use rustc_hir as hir; +use rustc_hir::HirId; use rustc_index::vec::Idx; +use rustc_middle::traits::Reveal; use rustc_middle::ty::layout::{LayoutError, SizeSkeleton}; use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitable, UintTy}; use rustc_session::lint; -use rustc_span::{Span, Symbol, DUMMY_SP}; +use rustc_span::{Symbol, DUMMY_SP}; use rustc_target::abi::{Pointer, VariantIdx}; use rustc_target::asm::{InlineAsmReg, InlineAsmRegClass, InlineAsmRegOrRegClass, InlineAsmType}; @@ -39,63 +41,108 @@ fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { ty } -impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - pub fn check_transmute(&self, span: Span, from: Ty<'tcx>, to: Ty<'tcx>) { - let convert = |ty: Ty<'tcx>| { - let ty = self.resolve_vars_if_possible(ty); - let ty = self.tcx.normalize_erasing_regions(self.param_env, ty); - (SizeSkeleton::compute(ty, self.tcx, self.param_env), ty) - }; - let (sk_from, from) = convert(from); - let (sk_to, to) = convert(to); +fn inner_check_transmute<'tcx>( + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + hir_id: HirId, + from: Ty<'tcx>, + to: Ty<'tcx>, +) -> Result<(), ErrorGuaranteed> { + let convert = |ty: Ty<'tcx>| { + let ty = tcx.normalize_erasing_regions(param_env, ty); + (SizeSkeleton::compute(ty, tcx, param_env), ty) + }; + let (sk_from, from) = convert(from); + let (sk_to, to) = convert(to); - // Check for same size using the skeletons. - if let (Ok(sk_from), Ok(sk_to)) = (sk_from, sk_to) { - if sk_from.same_size(sk_to) { - return; - } + // Check for same size using the skeletons. + if let (Ok(sk_from), Ok(sk_to)) = (sk_from, sk_to) { + if sk_from.same_size(sk_to) { + return Ok(()); + } - // Special-case transmuting from `typeof(function)` and - // `Option` to present a clearer error. - let from = unpack_option_like(self.tcx, from); - if let (&ty::FnDef(..), SizeSkeleton::Known(size_to)) = (from.kind(), sk_to) && size_to == Pointer.size(&self.tcx) { - struct_span_err!(self.tcx.sess, span, E0591, "can't transmute zero-sized type") - .note(&format!("source type: {from}")) - .note(&format!("target type: {to}")) - .help("cast with `as` to a pointer instead") - .emit(); - return; - } + // Special-case transmuting from `typeof(function)` and + // `Option` to present a clearer error. + let from = unpack_option_like(tcx, from); + if let (&ty::FnDef(..), SizeSkeleton::Known(size_to)) = (from.kind(), sk_to) && size_to == Pointer.size(&tcx) { + let err = struct_span_err!( + tcx.sess, + tcx.hir().span(hir_id), + E0591, + "can't transmute zero-sized type", + ) + .note(&format!("source type: {from}")) + .note(&format!("target type: {to}")) + .help("cast with `as` to a pointer instead") + .emit(); + return Err(err); } + } - // Try to display a sensible error with as much information as possible. - let skeleton_string = |ty: Ty<'tcx>, sk| match sk { - Ok(SizeSkeleton::Known(size)) => format!("{} bits", size.bits()), - Ok(SizeSkeleton::Pointer { tail, .. }) => format!("pointer to `{tail}`"), - Err(LayoutError::Unknown(bad)) => { - if bad == ty { - "this type does not have a fixed size".to_owned() - } else { - format!("size can vary because of {bad}") - } + // HACK: We retry with `Reveal::All` for backwards + // compatability reasons, see #101478 for more details. + if param_env.reveal() != Reveal::All { + let param_env_reveal_all = ty::ParamEnv::new( + tcx.normalize_opaque_types(param_env.caller_bounds()), + Reveal::All, + param_env.constness(), + ); + + match inner_check_transmute(tcx, param_env_reveal_all, hir_id, from, to) { + Ok(()) => { + tcx.struct_span_lint_hir( + rustc_session::lint::builtin::HIDDEN_TYPE_OF_OPAQUE_TYPES_IN_TYPE_SYSTEM, + hir_id, + tcx.hir().span(hir_id), + |err| { + err.build( + "relying on the underlying type of an opaque type in the type system", + ) + .note("checking whether this transmute is valid relies on the underlying type of an opaque type") + .emit() + }, + ); + return Ok(()); } - Err(err) => err.to_string(), - }; + Err(e) => return Err(e), + } + } - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0512, - "cannot transmute between types of different sizes, \ - or dependently-sized types" - ); - if from == to { - err.note(&format!("`{from}` does not have a fixed size")); - } else { - err.note(&format!("source type: `{}` ({})", from, skeleton_string(from, sk_from))) - .note(&format!("target type: `{}` ({})", to, skeleton_string(to, sk_to))); + // Try to display a sensible error with as much information as possible. + let skeleton_string = |ty: Ty<'tcx>, sk| match sk { + Ok(SizeSkeleton::Known(size)) => format!("{} bits", size.bits()), + Ok(SizeSkeleton::Pointer { tail, .. }) => format!("pointer to `{tail}`"), + Err(LayoutError::Unknown(bad)) => { + if bad == ty { + "this type does not have a fixed size".to_owned() + } else { + format!("size can vary because of {bad}") + } } - err.emit(); + Err(err) => err.to_string(), + }; + + let mut err = struct_span_err!( + tcx.sess, + tcx.hir().span(hir_id), + E0512, + "cannot transmute between types of different sizes, \ + or dependently-sized types" + ); + if from == to { + err.note(&format!("`{from}` does not have a fixed size")); + } else { + err.note(&format!("source type: `{}` ({})", from, skeleton_string(from, sk_from))) + .note(&format!("target type: `{}` ({})", to, skeleton_string(to, sk_to))); + } + Err(err.emit()) +} + +impl<'a, 'tcx> FnCtxt<'a, 'tcx> { + pub fn check_transmute(&self, hir_id: HirId, from: Ty<'tcx>, to: Ty<'tcx>) { + let from = self.resolve_vars_if_possible(from); + let to = self.resolve_vars_if_possible(to); + let _ = inner_check_transmute(self.tcx, self.param_env, hir_id, from, to); } } diff --git a/src/test/mir-opt/inline/inline_generator.main.Inline.diff b/src/test/mir-opt/inline/inline_generator.main.Inline.diff index 0b992e3c32ad1..7ad57a3944f61 100644 --- a/src/test/mir-opt/inline/inline_generator.main.Inline.diff +++ b/src/test/mir-opt/inline/inline_generator.main.Inline.diff @@ -50,7 +50,7 @@ + Deinit(_4); // scope 2 at $DIR/inline-generator.rs:15:5: 15:41 + discriminant(_4) = 0; // scope 2 at $DIR/inline-generator.rs:15:5: 15:41 _3 = &mut _4; // scope 0 at $DIR/inline-generator.rs:+1:23: +1:31 -- _2 = Pin::<&mut [generator@$DIR/inline-generator.rs:15:5: 15:8]>::new(move _3) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/inline-generator.rs:+1:14: +1:32 +- _2 = Pin::<&mut [generator@$DIR/inline-generator.rs:15:5: 15:8]>::new(move _3) -> [return: bb2, unwind: bb7]; // scope 0 at $DIR/inline-generator.rs:+1:14: +1:32 - // mir::Constant - // + span: $DIR/inline-generator.rs:9:14: 9:22 - // + user_ty: UserType(0) @@ -67,7 +67,7 @@ + StorageDead(_6); // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL + StorageDead(_5); // scope 4 at $SRC_DIR/core/src/pin.rs:LL:COL StorageDead(_3); // scope 0 at $DIR/inline-generator.rs:+1:31: +1:32 -- _1 = <[generator@$DIR/inline-generator.rs:15:5: 15:8] as Generator>::resume(move _2, const false) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/inline-generator.rs:+1:14: +1:46 +- _1 = <[generator@$DIR/inline-generator.rs:15:5: 15:8] as Generator>::resume(move _2, const false) -> [return: bb3, unwind: bb7]; // scope 0 at $DIR/inline-generator.rs:+1:14: +1:46 - // mir::Constant - // + span: $DIR/inline-generator.rs:9:33: 9:39 - // + literal: Const { ty: for<'r> fn(Pin<&'r mut [generator@$DIR/inline-generator.rs:15:5: 15:8]>, bool) -> GeneratorState<<[generator@$DIR/inline-generator.rs:15:5: 15:8] as Generator>::Yield, <[generator@$DIR/inline-generator.rs:15:5: 15:8] as Generator>::Return> {<[generator@$DIR/inline-generator.rs:15:5: 15:8] as Generator>::resume}, val: Value() } @@ -77,7 +77,7 @@ + StorageLive(_11); // scope 0 at $DIR/inline-generator.rs:+1:14: +1:46 + _13 = deref_copy (_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 + _12 = discriminant((*_13)); // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 -+ switchInt(move _12) -> [0_u32: bb3, 1_u32: bb8, 3_u32: bb7, otherwise: bb9]; // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 ++ switchInt(move _12) -> [0_u32: bb7, 1_u32: bb12, 3_u32: bb11, otherwise: bb13]; // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 } - bb3: { @@ -86,36 +86,60 @@ + StorageDead(_10); // scope 0 at $DIR/inline-generator.rs:+1:14: +1:46 + StorageDead(_7); // scope 0 at $DIR/inline-generator.rs:+1:14: +1:46 StorageDead(_2); // scope 0 at $DIR/inline-generator.rs:+1:45: +1:46 +- drop(_4) -> [return: bb4, unwind: bb6]; // scope 0 at $DIR/inline-generator.rs:+1:46: +1:47 ++ drop(_4) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/inline-generator.rs:+1:46: +1:47 + } + +- bb4: { ++ bb2: { StorageDead(_4); // scope 0 at $DIR/inline-generator.rs:+1:46: +1:47 _0 = const (); // scope 0 at $DIR/inline-generator.rs:+0:11: +2:2 +- drop(_1) -> [return: bb5, unwind: bb8]; // scope 0 at $DIR/inline-generator.rs:+2:1: +2:2 ++ drop(_1) -> [return: bb3, unwind: bb6]; // scope 0 at $DIR/inline-generator.rs:+2:1: +2:2 + } + +- bb5: { ++ bb3: { StorageDead(_1); // scope 0 at $DIR/inline-generator.rs:+2:1: +2:2 return; // scope 0 at $DIR/inline-generator.rs:+2:2: +2:2 } -- bb4 (cleanup): { -+ bb2 (cleanup): { +- bb6 (cleanup): { +- drop(_1) -> bb8; // scope 0 at $DIR/inline-generator.rs:+2:1: +2:2 ++ bb4 (cleanup): { ++ drop(_1) -> bb6; // scope 0 at $DIR/inline-generator.rs:+2:1: +2:2 + } + +- bb7 (cleanup): { +- drop(_4) -> bb8; // scope 0 at $DIR/inline-generator.rs:+1:46: +1:47 ++ bb5 (cleanup): { ++ drop(_4) -> bb6; // scope 0 at $DIR/inline-generator.rs:+1:46: +1:47 + } + +- bb8 (cleanup): { ++ bb6 (cleanup): { resume; // scope 0 at $DIR/inline-generator.rs:+0:1: +2:2 + } + -+ bb3: { ++ bb7: { + _11 = move _7; // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 + StorageLive(_8); // scope 6 at $DIR/inline-generator.rs:15:17: 15:39 + StorageLive(_9); // scope 6 at $DIR/inline-generator.rs:15:20: 15:21 + _9 = _11; // scope 6 at $DIR/inline-generator.rs:15:20: 15:21 -+ switchInt(move _9) -> [false: bb5, otherwise: bb4]; // scope 6 at $DIR/inline-generator.rs:15:20: 15:21 ++ switchInt(move _9) -> [false: bb9, otherwise: bb8]; // scope 6 at $DIR/inline-generator.rs:15:20: 15:21 + } + -+ bb4: { ++ bb8: { + _8 = const 7_i32; // scope 6 at $DIR/inline-generator.rs:15:24: 15:25 -+ goto -> bb6; // scope 6 at $DIR/inline-generator.rs:15:17: 15:39 ++ goto -> bb10; // scope 6 at $DIR/inline-generator.rs:15:17: 15:39 + } + -+ bb5: { ++ bb9: { + _8 = const 13_i32; // scope 6 at $DIR/inline-generator.rs:15:35: 15:37 -+ goto -> bb6; // scope 6 at $DIR/inline-generator.rs:15:17: 15:39 ++ goto -> bb10; // scope 6 at $DIR/inline-generator.rs:15:17: 15:39 + } + -+ bb6: { ++ bb10: { + StorageDead(_9); // scope 6 at $DIR/inline-generator.rs:15:38: 15:39 + Deinit(_1); // scope 6 at $DIR/inline-generator.rs:15:11: 15:39 + ((_1 as Yielded).0: i32) = move _8; // scope 6 at $DIR/inline-generator.rs:15:11: 15:39 @@ -125,7 +149,7 @@ + goto -> bb1; // scope 0 at $DIR/inline-generator.rs:15:11: 15:39 + } + -+ bb7: { ++ bb11: { + StorageLive(_8); // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 + _10 = move _7; // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 + StorageDead(_8); // scope 6 at $DIR/inline-generator.rs:15:38: 15:39 @@ -137,11 +161,11 @@ + goto -> bb1; // scope 0 at $DIR/inline-generator.rs:15:41: 15:41 + } + -+ bb8: { -+ assert(const false, "generator resumed after completion") -> [success: bb8, unwind: bb2]; // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 ++ bb12: { ++ assert(const false, "generator resumed after completion") -> [success: bb12, unwind: bb5]; // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 + } + -+ bb9: { ++ bb13: { + unreachable; // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 } } diff --git a/src/test/mir-opt/inline/issue_78442.bar.Inline.diff b/src/test/mir-opt/inline/issue_78442.bar.Inline.diff index c16dfdf395ecc..c2cfc5735934e 100644 --- a/src/test/mir-opt/inline/issue_78442.bar.Inline.diff +++ b/src/test/mir-opt/inline/issue_78442.bar.Inline.diff @@ -15,8 +15,8 @@ StorageLive(_2); // scope 0 at $DIR/issue-78442.rs:+4:5: +4:17 StorageLive(_3); // scope 0 at $DIR/issue-78442.rs:+4:5: +4:15 StorageLive(_4); // scope 0 at $DIR/issue-78442.rs:+4:5: +4:15 -- _4 = hide_foo() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:+4:5: +4:15 -+ _4 = hide_foo() -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/issue-78442.rs:+4:5: +4:15 +- _4 = hide_foo() -> [return: bb1, unwind: bb6]; // scope 0 at $DIR/issue-78442.rs:+4:5: +4:15 ++ _4 = hide_foo() -> [return: bb1, unwind: bb5]; // scope 0 at $DIR/issue-78442.rs:+4:5: +4:15 // mir::Constant // + span: $DIR/issue-78442.rs:11:5: 11:13 // + literal: Const { ty: fn() -> impl Fn() {hide_foo}, val: Value() } @@ -26,43 +26,52 @@ _3 = &_4; // scope 0 at $DIR/issue-78442.rs:+4:5: +4:15 StorageLive(_5); // scope 0 at $DIR/issue-78442.rs:+4:5: +4:17 Deinit(_5); // scope 0 at $DIR/issue-78442.rs:+4:5: +4:17 -- _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:+4:5: +4:17 +- _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/issue-78442.rs:+4:5: +4:17 - // mir::Constant - // + span: $DIR/issue-78442.rs:11:5: 11:15 - // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r fn() {foo}, ()) -> >::Output {>::call}, val: Value() } -+ _2 = move (*_3)() -> [return: bb5, unwind: bb3]; // scope 1 at $SRC_DIR/core/src/ops/function.rs:LL:COL ++ _2 = move (*_3)() -> [return: bb7, unwind: bb4]; // scope 1 at $SRC_DIR/core/src/ops/function.rs:LL:COL } bb2: { - StorageDead(_5); // scope 0 at $DIR/issue-78442.rs:+4:16: +4:17 - StorageDead(_3); // scope 0 at $DIR/issue-78442.rs:+4:16: +4:17 -- StorageDead(_4); // scope 0 at $DIR/issue-78442.rs:+4:17: +4:18 -- StorageDead(_2); // scope 0 at $DIR/issue-78442.rs:+4:17: +4:18 -- _0 = const (); // scope 0 at $DIR/issue-78442.rs:+3:3: +5:2 -- drop(_1) -> [return: bb3, unwind: bb5]; // scope 0 at $DIR/issue-78442.rs:+5:1: +5:2 -+ return; // scope 0 at $DIR/issue-78442.rs:+5:2: +5:2 +- drop(_4) -> [return: bb3, unwind: bb6]; // scope 0 at $DIR/issue-78442.rs:+4:17: +4:18 +- } +- +- bb3: { + StorageDead(_4); // scope 0 at $DIR/issue-78442.rs:+4:17: +4:18 + StorageDead(_2); // scope 0 at $DIR/issue-78442.rs:+4:17: +4:18 + _0 = const (); // scope 0 at $DIR/issue-78442.rs:+3:3: +5:2 +- drop(_1) -> [return: bb4, unwind: bb7]; // scope 0 at $DIR/issue-78442.rs:+5:1: +5:2 ++ drop(_1) -> [return: bb3, unwind: bb6]; // scope 0 at $DIR/issue-78442.rs:+5:1: +5:2 } -- bb3: { -- return; // scope 0 at $DIR/issue-78442.rs:+5:2: +5:2 -+ bb3 (cleanup): { -+ drop(_1) -> bb4; // scope 0 at $DIR/issue-78442.rs:+5:1: +5:2 +- bb4: { ++ bb3: { + return; // scope 0 at $DIR/issue-78442.rs:+5:2: +5:2 + } + ++ bb4 (cleanup): { ++ drop(_4) -> bb5; // scope 0 at $DIR/issue-78442.rs:+4:17: +4:18 ++ } ++ + bb5 (cleanup): { +- drop(_4) -> bb6; // scope 0 at $DIR/issue-78442.rs:+4:17: +4:18 ++ drop(_1) -> bb6; // scope 0 at $DIR/issue-78442.rs:+5:1: +5:2 } - bb4 (cleanup): { -- drop(_1) -> bb5; // scope 0 at $DIR/issue-78442.rs:+5:1: +5:2 + bb6 (cleanup): { +- drop(_1) -> bb7; // scope 0 at $DIR/issue-78442.rs:+5:1: +5:2 + resume; // scope 0 at $DIR/issue-78442.rs:+0:1: +5:2 } -- bb5 (cleanup): { +- bb7 (cleanup): { - resume; // scope 0 at $DIR/issue-78442.rs:+0:1: +5:2 -+ bb5: { ++ bb7: { + StorageDead(_5); // scope 0 at $DIR/issue-78442.rs:+4:16: +4:17 + StorageDead(_3); // scope 0 at $DIR/issue-78442.rs:+4:16: +4:17 -+ StorageDead(_4); // scope 0 at $DIR/issue-78442.rs:+4:17: +4:18 -+ StorageDead(_2); // scope 0 at $DIR/issue-78442.rs:+4:17: +4:18 -+ _0 = const (); // scope 0 at $DIR/issue-78442.rs:+3:3: +5:2 -+ drop(_1) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:+5:1: +5:2 ++ drop(_4) -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/issue-78442.rs:+4:17: +4:18 } } diff --git a/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff b/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff index 0faa522cbaa9c..61a9f383d0f41 100644 --- a/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff +++ b/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff @@ -15,7 +15,7 @@ StorageLive(_2); // scope 0 at $DIR/issue-78442.rs:+4:5: +4:17 StorageLive(_3); // scope 0 at $DIR/issue-78442.rs:+4:5: +4:15 StorageLive(_4); // scope 0 at $DIR/issue-78442.rs:+4:5: +4:15 - _4 = hide_foo() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:+4:5: +4:15 + _4 = hide_foo() -> [return: bb1, unwind: bb6]; // scope 0 at $DIR/issue-78442.rs:+4:5: +4:15 // mir::Constant // + span: $DIR/issue-78442.rs:11:5: 11:13 // + literal: Const { ty: fn() -> impl Fn() {hide_foo}, val: Value() } @@ -25,8 +25,8 @@ _3 = &_4; // scope 0 at $DIR/issue-78442.rs:+4:5: +4:15 StorageLive(_5); // scope 0 at $DIR/issue-78442.rs:+4:5: +4:17 Deinit(_5); // scope 0 at $DIR/issue-78442.rs:+4:5: +4:17 -- _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:+4:5: +4:17 -+ _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:+4:5: +4:17 +- _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/issue-78442.rs:+4:5: +4:17 ++ _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/issue-78442.rs:+4:5: +4:17 // mir::Constant // + span: $DIR/issue-78442.rs:11:5: 11:15 - // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl Fn(), ()) -> >::Output {>::call}, val: Value() } @@ -36,21 +36,29 @@ bb2: { StorageDead(_5); // scope 0 at $DIR/issue-78442.rs:+4:16: +4:17 StorageDead(_3); // scope 0 at $DIR/issue-78442.rs:+4:16: +4:17 + drop(_4) -> [return: bb3, unwind: bb6]; // scope 0 at $DIR/issue-78442.rs:+4:17: +4:18 + } + + bb3: { StorageDead(_4); // scope 0 at $DIR/issue-78442.rs:+4:17: +4:18 StorageDead(_2); // scope 0 at $DIR/issue-78442.rs:+4:17: +4:18 _0 = const (); // scope 0 at $DIR/issue-78442.rs:+3:3: +5:2 - drop(_1) -> [return: bb3, unwind: bb5]; // scope 0 at $DIR/issue-78442.rs:+5:1: +5:2 + drop(_1) -> [return: bb4, unwind: bb7]; // scope 0 at $DIR/issue-78442.rs:+5:1: +5:2 } - bb3: { + bb4: { return; // scope 0 at $DIR/issue-78442.rs:+5:2: +5:2 } - bb4 (cleanup): { - drop(_1) -> bb5; // scope 0 at $DIR/issue-78442.rs:+5:1: +5:2 + bb5 (cleanup): { + drop(_4) -> bb6; // scope 0 at $DIR/issue-78442.rs:+4:17: +4:18 } - bb5 (cleanup): { + bb6 (cleanup): { + drop(_1) -> bb7; // scope 0 at $DIR/issue-78442.rs:+5:1: +5:2 + } + + bb7 (cleanup): { resume; // scope 0 at $DIR/issue-78442.rs:+0:1: +5:2 } } diff --git a/src/test/ui/const-generics/issues/issue-83765.stderr b/src/test/ui/const-generics/issues/issue-83765.stderr index d5f914f46f873..b2464b07e65f1 100644 --- a/src/test/ui/const-generics/issues/issue-83765.stderr +++ b/src/test/ui/const-generics/issues/issue-83765.stderr @@ -10,11 +10,11 @@ note: ...which requires computing candidate for ` LL | trait TensorDimension { | ^^^^^^^^^^^^^^^^^^^^^ = note: ...which again requires resolving instance ` as TensorDimension>::DIM`, completing the cycle -note: cycle used when computing candidate for ` as TensorDimension>` - --> $DIR/issue-83765.rs:4:1 +note: cycle used when const-evaluating + checking `TensorSize::size::{constant#0}` + --> $DIR/issue-83765.rs:16:31 | -LL | trait TensorDimension { - | ^^^^^^^^^^^^^^^^^^^^^ +LL | fn size(&self) -> [usize; Self::DIM]; + | ^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/consts/const-size_of-cycle.stderr b/src/test/ui/consts/const-size_of-cycle.stderr index 46f02ce8a4533..c34f472490245 100644 --- a/src/test/ui/consts/const-size_of-cycle.stderr +++ b/src/test/ui/consts/const-size_of-cycle.stderr @@ -7,11 +7,6 @@ LL | bytes: [u8; std::mem::size_of::()] note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`... --> $DIR/const-size_of-cycle.rs:4:17 | -LL | bytes: [u8; std::mem::size_of::()] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`... - --> $DIR/const-size_of-cycle.rs:4:17 - | LL | bytes: [u8; std::mem::size_of::()] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing layout of `Foo`... diff --git a/src/test/ui/consts/issue-44415.stderr b/src/test/ui/consts/issue-44415.stderr index 57f94f8c6ab52..2ee2741042507 100644 --- a/src/test/ui/consts/issue-44415.stderr +++ b/src/test/ui/consts/issue-44415.stderr @@ -7,11 +7,6 @@ LL | bytes: [u8; unsafe { intrinsics::size_of::() }], note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`... --> $DIR/issue-44415.rs:6:17 | -LL | bytes: [u8; unsafe { intrinsics::size_of::() }], - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`... - --> $DIR/issue-44415.rs:6:17 - | LL | bytes: [u8; unsafe { intrinsics::size_of::() }], | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing layout of `Foo`... diff --git a/src/test/ui/impl-trait/in-ctfe/array-len-size-of.rs b/src/test/ui/impl-trait/in-ctfe/array-len-size-of.rs new file mode 100644 index 0000000000000..6bdea1a6e4027 --- /dev/null +++ b/src/test/ui/impl-trait/in-ctfe/array-len-size-of.rs @@ -0,0 +1,22 @@ +// This previously compiled, but was intentionally changed in #101478. +// This was used in https://github.com/GoldsteinE/name-it. +// +// See that PR for more details. +// +// check-pass +use std::mem; +fn returns_opaque() -> impl Sized { + 0u8 +} + +struct NamedOpaqueType { + data: [mem::MaybeUninit; size_of_fut(returns_opaque)] + //~^ WARNING relying on the underlying type of an opaque type in the type system + //~| WARNING this was previously accepted by the compiler +} + +const fn size_of_fut(x: fn() -> FUT) -> usize { + mem::size_of::() +} + +fn main() {} diff --git a/src/test/ui/impl-trait/in-ctfe/array-len-size-of.stderr b/src/test/ui/impl-trait/in-ctfe/array-len-size-of.stderr new file mode 100644 index 0000000000000..a86e1e474f038 --- /dev/null +++ b/src/test/ui/impl-trait/in-ctfe/array-len-size-of.stderr @@ -0,0 +1,13 @@ +warning: relying on the underlying type of an opaque type in the type system + --> $DIR/array-len-size-of.rs:13:34 + | +LL | data: [mem::MaybeUninit; size_of_fut(returns_opaque)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(hidden_type_of_opaque_types_in_type_system)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue # + = note: evaluating this constant relies on the underlying type of an opaque type + +warning: 1 warning emitted + diff --git a/src/test/ui/impl-trait/in-ctfe/array-len.rs b/src/test/ui/impl-trait/in-ctfe/array-len.rs new file mode 100644 index 0000000000000..425b93f9e2d2b --- /dev/null +++ b/src/test/ui/impl-trait/in-ctfe/array-len.rs @@ -0,0 +1,29 @@ +// This previously compiled, but was intentionally changed in #101478. +// +// See that PR for more details. +// +// check-pass +trait MyTrait: Copy { + const ASSOC: usize; +} + +impl MyTrait for u8 { + const ASSOC: usize = 32; +} + +const fn yeet() -> impl MyTrait { + 0u8 +} + +const fn output(_: T) -> usize { + ::ASSOC +} + +fn main() { + let x = [0u8; output(yeet())]; + //~^ WARNING relying on the underlying type of an opaque type in the type system + //~| WARNING this was previously accepted by the compiler + //~| WARNING relying on the underlying type of an opaque type in the type system + //~| WARNING this was previously accepted by the compiler + println!("{:?}", x); +} diff --git a/src/test/ui/impl-trait/in-ctfe/array-len.stderr b/src/test/ui/impl-trait/in-ctfe/array-len.stderr new file mode 100644 index 0000000000000..a852d71dcb411 --- /dev/null +++ b/src/test/ui/impl-trait/in-ctfe/array-len.stderr @@ -0,0 +1,23 @@ +warning: relying on the underlying type of an opaque type in the type system + --> $DIR/array-len.rs:23:19 + | +LL | let x = [0u8; output(yeet())]; + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(hidden_type_of_opaque_types_in_type_system)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue # + = note: evaluating this constant relies on the underlying type of an opaque type + +warning: relying on the underlying type of an opaque type in the type system + --> $DIR/array-len.rs:23:19 + | +LL | let x = [0u8; output(yeet())]; + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue # + = note: evaluating this constant relies on the underlying type of an opaque type + +warning: 2 warnings emitted + diff --git a/src/test/ui/impl-trait/in-ctfe/enum-discr.rs b/src/test/ui/impl-trait/in-ctfe/enum-discr.rs new file mode 100644 index 0000000000000..53c0bdcd030eb --- /dev/null +++ b/src/test/ui/impl-trait/in-ctfe/enum-discr.rs @@ -0,0 +1,31 @@ +// This previously compiled, but was intentionally changed in #101478. +// +// See that PR for more details. +// +// check-pass +trait MyTrait: Copy { + const ASSOC: usize; +} + +impl MyTrait for u8 { + const ASSOC: usize = 32; +} + +const fn yeet() -> impl MyTrait { + 0u8 +} + +const fn output(_: T) -> usize { + ::ASSOC +} + +#[repr(usize)] +enum Foo { + Bar = output(yeet()), + //~^ WARNING relying on the underlying type of an opaque type in the type system + //~| WARNING this was previously accepted by the compiler +} + +fn main() { + println!("{}", Foo::Bar as usize); +} diff --git a/src/test/ui/impl-trait/in-ctfe/enum-discr.stderr b/src/test/ui/impl-trait/in-ctfe/enum-discr.stderr new file mode 100644 index 0000000000000..e4f3a5dbf762c --- /dev/null +++ b/src/test/ui/impl-trait/in-ctfe/enum-discr.stderr @@ -0,0 +1,13 @@ +warning: relying on the underlying type of an opaque type in the type system + --> $DIR/enum-discr.rs:24:11 + | +LL | Bar = output(yeet()), + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(hidden_type_of_opaque_types_in_type_system)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue # + = note: evaluating this constant relies on the underlying type of an opaque type + +warning: 1 warning emitted + diff --git a/src/test/ui/impl-trait/in-ctfe/match-arm-exhaustive.rs b/src/test/ui/impl-trait/in-ctfe/match-arm-exhaustive.rs new file mode 100644 index 0000000000000..c60c06f75d1a5 --- /dev/null +++ b/src/test/ui/impl-trait/in-ctfe/match-arm-exhaustive.rs @@ -0,0 +1,27 @@ +// This previously compiled, but was intentionally changed in #101478. +// +// See that PR for more details. +trait MyTrait: Copy { + const ASSOC: u8; +} + +impl MyTrait for () { + const ASSOC: u8 = 0; +} + +const fn yeet() -> impl MyTrait {} + +const fn output(_: T) -> u8 { + ::ASSOC +} + +const CT: u8 = output(yeet()); + +fn main() { + match 0 { + CT => (), + //~^ ERROR constant pattern depends on a generic parameter + //~| ERROR constant pattern depends on a generic parameter + 1.. => (), + } +} diff --git a/src/test/ui/impl-trait/in-ctfe/match-arm-exhaustive.stderr b/src/test/ui/impl-trait/in-ctfe/match-arm-exhaustive.stderr new file mode 100644 index 0000000000000..dfdebeb0e101a --- /dev/null +++ b/src/test/ui/impl-trait/in-ctfe/match-arm-exhaustive.stderr @@ -0,0 +1,14 @@ +error: constant pattern depends on a generic parameter + --> $DIR/match-arm-exhaustive.rs:22:9 + | +LL | CT => (), + | ^^ + +error: constant pattern depends on a generic parameter + --> $DIR/match-arm-exhaustive.rs:22:9 + | +LL | CT => (), + | ^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/impl-trait/issues/issue-78722.rs b/src/test/ui/impl-trait/issues/issue-78722.rs index 90d1cd3798a83..b13ab6bad7fbe 100644 --- a/src/test/ui/impl-trait/issues/issue-78722.rs +++ b/src/test/ui/impl-trait/issues/issue-78722.rs @@ -7,7 +7,6 @@ type F = impl core::future::Future; struct Bug { V1: [(); { fn concrete_use() -> F { - //~^ ERROR expected `impl Future` to be a future that resolves to `u8`, but it resolves to `()` async {} } let f: F = async { 1 }; diff --git a/src/test/ui/impl-trait/issues/issue-78722.stderr b/src/test/ui/impl-trait/issues/issue-78722.stderr index 9a0ffbc89d92e..975c771759f9b 100644 --- a/src/test/ui/impl-trait/issues/issue-78722.stderr +++ b/src/test/ui/impl-trait/issues/issue-78722.stderr @@ -1,5 +1,5 @@ error[E0658]: `async` blocks are not allowed in constants - --> $DIR/issue-78722.rs:13:20 + --> $DIR/issue-78722.rs:12:20 | LL | let f: F = async { 1 }; | ^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let f: F = async { 1 }; = help: add `#![feature(const_async_blocks)]` to the crate attributes to enable error[E0493]: destructors cannot be evaluated at compile-time - --> $DIR/issue-78722.rs:13:13 + --> $DIR/issue-78722.rs:12:13 | LL | let f: F = async { 1 }; | ^ constants cannot evaluate destructors @@ -16,13 +16,7 @@ LL | let f: F = async { 1 }; LL | }], | - value is dropped here -error[E0271]: expected `impl Future` to be a future that resolves to `u8`, but it resolves to `()` - --> $DIR/issue-78722.rs:9:30 - | -LL | fn concrete_use() -> F { - | ^ expected `()`, found `u8` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0271, E0493, E0658. -For more information about an error, try `rustc --explain E0271`. +Some errors have detailed explanations: E0493, E0658. +For more information about an error, try `rustc --explain E0493`. diff --git a/src/test/ui/impl-trait/transmute/in-defining-scope.rs b/src/test/ui/impl-trait/transmute/in-defining-scope.rs new file mode 100644 index 0000000000000..eacd1e8cf301d --- /dev/null +++ b/src/test/ui/impl-trait/transmute/in-defining-scope.rs @@ -0,0 +1,16 @@ +// This causes a query cycle due to incorrectly using `Reveal::All`, +// in #101478 this was changed to a future compat error which only +// triggers after the query cycle. +// +// See that PR for more details. +use std::mem::transmute; +fn foo() -> impl Sized { + //~^ ERROR cycle detected when computing type of + unsafe { + transmute::<_, u8>(foo()); + //~^ ERROR cannot transmute between types of different sizes + } + 0u8 +} + +fn main() {} diff --git a/src/test/ui/impl-trait/transmute/in-defining-scope.stderr b/src/test/ui/impl-trait/transmute/in-defining-scope.stderr new file mode 100644 index 0000000000000..d00d4eca59999 --- /dev/null +++ b/src/test/ui/impl-trait/transmute/in-defining-scope.stderr @@ -0,0 +1,68 @@ +error[E0391]: cycle detected when computing type of `foo::{opaque#0}` + --> $DIR/in-defining-scope.rs:7:13 + | +LL | fn foo() -> impl Sized { + | ^^^^^^^^^^ + | +note: ...which requires borrow-checking `foo`... + --> $DIR/in-defining-scope.rs:7:1 + | +LL | fn foo() -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing `foo`... + --> $DIR/in-defining-scope.rs:7:1 + | +LL | fn foo() -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing MIR for `foo`... + --> $DIR/in-defining-scope.rs:7:1 + | +LL | fn foo() -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires unsafety-checking `foo`... + --> $DIR/in-defining-scope.rs:7:1 + | +LL | fn foo() -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires building MIR for `foo`... + --> $DIR/in-defining-scope.rs:7:1 + | +LL | fn foo() -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires building THIR for `foo`... + --> $DIR/in-defining-scope.rs:7:1 + | +LL | fn foo() -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires type-checking `foo`... + --> $DIR/in-defining-scope.rs:7:1 + | +LL | fn foo() -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires normalizing `impl Sized`... + = note: ...which again requires computing type of `foo::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/in-defining-scope.rs:6:1 + | +LL | / use std::mem::transmute; +LL | | fn foo() -> impl Sized { +LL | | +LL | | unsafe { +... | +LL | | +LL | | fn main() {} + | |____________^ + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/in-defining-scope.rs:10:9 + | +LL | transmute::<_, u8>(foo()); + | ^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[type error]` (this type does not have a fixed size) + = note: target type: `u8` (8 bits) + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0391, E0512. +For more information about an error, try `rustc --explain E0391`. diff --git a/src/test/ui/impl-trait/transmute/outside-of-defining-scope.rs b/src/test/ui/impl-trait/transmute/outside-of-defining-scope.rs new file mode 100644 index 0000000000000..94c851e396a89 --- /dev/null +++ b/src/test/ui/impl-trait/transmute/outside-of-defining-scope.rs @@ -0,0 +1,18 @@ +// This previously compiled, but was intentionally changed in #101478. +// Lowered back to a future compat lint. +// +// See that PR for more details. +// +// check-pass +use std::mem::transmute; +fn foo() -> impl Sized { + 0u8 +} + +fn main() { + unsafe { + transmute::<_, u8>(foo()); + //~^ WARN relying on the underlying type of an opaque type in the type system + //~| WARN this was previously accepted by the compiler but is being phased out + } +} diff --git a/src/test/ui/impl-trait/transmute/outside-of-defining-scope.stderr b/src/test/ui/impl-trait/transmute/outside-of-defining-scope.stderr new file mode 100644 index 0000000000000..5c311d2c7a364 --- /dev/null +++ b/src/test/ui/impl-trait/transmute/outside-of-defining-scope.stderr @@ -0,0 +1,13 @@ +warning: relying on the underlying type of an opaque type in the type system + --> $DIR/outside-of-defining-scope.rs:14:9 + | +LL | transmute::<_, u8>(foo()); + | ^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(hidden_type_of_opaque_types_in_type_system)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue # + = note: checking whether this transmute is valid relies on the underlying type of an opaque type + +warning: 1 warning emitted + diff --git a/src/test/ui/pattern/non-structural-match-types.rs b/src/test/ui/pattern/non-structural-match-types.rs index 5c33154736650..39eadedbf4bc0 100644 --- a/src/test/ui/pattern/non-structural-match-types.rs +++ b/src/test/ui/pattern/non-structural-match-types.rs @@ -9,6 +9,8 @@ fn main() { const { || {} } => {}, //~ ERROR cannot be used in patterns } match loop {} { - const { async {} } => {}, //~ ERROR cannot be used in patterns + const { async {} } => {}, + //~^ ERROR constant pattern depends on a generic parameter + //~| ERROR constant pattern depends on a generic parameter } } diff --git a/src/test/ui/pattern/non-structural-match-types.stderr b/src/test/ui/pattern/non-structural-match-types.stderr index 45e1626497388..230543ebf241a 100644 --- a/src/test/ui/pattern/non-structural-match-types.stderr +++ b/src/test/ui/pattern/non-structural-match-types.stderr @@ -4,11 +4,17 @@ error: `[closure@$DIR/non-structural-match-types.rs:9:17: 9:19]` cannot be used LL | const { || {} } => {}, | ^^^^^^^^^^^^^^^ -error: `impl Future` cannot be used in patterns +error: constant pattern depends on a generic parameter --> $DIR/non-structural-match-types.rs:12:9 | LL | const { async {} } => {}, | ^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: constant pattern depends on a generic parameter + --> $DIR/non-structural-match-types.rs:12:9 + | +LL | const { async {} } => {}, + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors diff --git a/src/test/ui/recursion/issue-26548-recursion-via-normalize.rs b/src/test/ui/recursion/issue-26548-recursion-via-normalize.rs index 91958dffcf4df..6266ee105c95b 100644 --- a/src/test/ui/recursion/issue-26548-recursion-via-normalize.rs +++ b/src/test/ui/recursion/issue-26548-recursion-via-normalize.rs @@ -1,10 +1,10 @@ -//~ ERROR cycle detected when computing layout of `core::option::Option` +//~ ERROR cycle detected when computing layout of `core::option::Option<::It>` +//~| NOTE ...which requires computing layout of `core::option::Option`... //~| NOTE ...which requires computing layout of `S`... -//~| NOTE ...which requires computing layout of `core::option::Option<::It>`... -//~| NOTE ...which again requires computing layout of `core::option::Option`, completing the cycle -//~| NOTE cycle used when computing layout of `core::option::Option<::It>` +//~| NOTE ...which again requires computing layout of `core::option::Option<::It>`, completing the cycle trait Mirror { + //~^ NOTE cycle used when checking deathness of variables in top-level module type It: ?Sized; } impl Mirror for T { diff --git a/src/test/ui/recursion/issue-26548-recursion-via-normalize.stderr b/src/test/ui/recursion/issue-26548-recursion-via-normalize.stderr index a75097cdbfbda..d5ad0d640186c 100644 --- a/src/test/ui/recursion/issue-26548-recursion-via-normalize.stderr +++ b/src/test/ui/recursion/issue-26548-recursion-via-normalize.stderr @@ -1,9 +1,19 @@ -error[E0391]: cycle detected when computing layout of `core::option::Option` +error[E0391]: cycle detected when computing layout of `core::option::Option<::It>` | + = note: ...which requires computing layout of `core::option::Option`... = note: ...which requires computing layout of `S`... - = note: ...which requires computing layout of `core::option::Option<::It>`... - = note: ...which again requires computing layout of `core::option::Option`, completing the cycle - = note: cycle used when computing layout of `core::option::Option<::It>` + = note: ...which again requires computing layout of `core::option::Option<::It>`, completing the cycle +note: cycle used when checking deathness of variables in top-level module + --> $DIR/issue-26548-recursion-via-normalize.rs:6:1 + | +LL | / trait Mirror { +LL | | +LL | | type It: ?Sized; +LL | | } +... | +LL | | let _s = S(None); +LL | | } + | |_^ error: aborting due to previous error diff --git a/src/test/ui/specialization/ctfe/default-assoc-const.rs b/src/test/ui/specialization/ctfe/default-assoc-const.rs new file mode 100644 index 0000000000000..3d091c93ad34d --- /dev/null +++ b/src/test/ui/specialization/ctfe/default-assoc-const.rs @@ -0,0 +1,26 @@ +// ICE fixed by #101478. +// +// See that PR for more details. +// +// check-pass +#![feature(specialization)] +//~^ WARNING the feature `specialization` is incomplete and may not be safe to use + +trait Foo { + const ASSOC: usize; +} + + +impl Foo for u32 { + default const ASSOC: usize = 0; +} + +fn foo() -> [u8; 0] { + [0; ::ASSOC] + //~^ WARNING relying on the underlying type of an opaque type in the type system + //~| WARNING this was previously accepted by the compiler + //~| WARNING relying on the underlying type of an opaque type in the type system + //~| WARNING this was previously accepted by the compiler +} + +fn main() {} diff --git a/src/test/ui/specialization/ctfe/default-assoc-const.stderr b/src/test/ui/specialization/ctfe/default-assoc-const.stderr new file mode 100644 index 0000000000000..1093754771ebf --- /dev/null +++ b/src/test/ui/specialization/ctfe/default-assoc-const.stderr @@ -0,0 +1,33 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/default-assoc-const.rs:6:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + +warning: relying on the underlying type of an opaque type in the type system + --> $DIR/default-assoc-const.rs:19:9 + | +LL | [0; ::ASSOC] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(hidden_type_of_opaque_types_in_type_system)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue # + = note: evaluating this constant relies on the underlying type of an opaque type + +warning: relying on the underlying type of an opaque type in the type system + --> $DIR/default-assoc-const.rs:19:9 + | +LL | [0; ::ASSOC] + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue # + = note: evaluating this constant relies on the underlying type of an opaque type + +warning: 3 warnings emitted + diff --git a/src/test/ui/specialization/ctfe/default-assoc-type.rs b/src/test/ui/specialization/ctfe/default-assoc-type.rs new file mode 100644 index 0000000000000..89dabf108ec36 --- /dev/null +++ b/src/test/ui/specialization/ctfe/default-assoc-type.rs @@ -0,0 +1,33 @@ +// ICE fixed by #101478. +// +// See that PR for more details. +// +// check-pass +#![feature(specialization)] +//~^ WARNING the feature `specialization` is incomplete and may not be safe to use + +trait Foo { + type Assoc: Trait; +} + +impl Foo for Vec { + default type Assoc = u32; +} + +trait Trait { + const ASSOC: usize; +} + +impl Trait for u32 { + const ASSOC: usize = 0; +} + +fn foo() -> [u8; 0] { + [0; < as Foo>::Assoc as Trait>::ASSOC] + //~^ WARNING relying on the underlying type of an opaque type in the type system + //~| WARNING this was previously accepted by the compiler + //~| WARNING relying on the underlying type of an opaque type in the type system + //~| WARNING this was previously accepted by the compiler +} + +fn main() {} diff --git a/src/test/ui/specialization/ctfe/default-assoc-type.stderr b/src/test/ui/specialization/ctfe/default-assoc-type.stderr new file mode 100644 index 0000000000000..4d0e69430d950 --- /dev/null +++ b/src/test/ui/specialization/ctfe/default-assoc-type.stderr @@ -0,0 +1,33 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/default-assoc-type.rs:6:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + +warning: relying on the underlying type of an opaque type in the type system + --> $DIR/default-assoc-type.rs:26:9 + | +LL | [0; < as Foo>::Assoc as Trait>::ASSOC] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(hidden_type_of_opaque_types_in_type_system)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue # + = note: evaluating this constant relies on the underlying type of an opaque type + +warning: relying on the underlying type of an opaque type in the type system + --> $DIR/default-assoc-type.rs:26:9 + | +LL | [0; < as Foo>::Assoc as Trait>::ASSOC] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue # + = note: evaluating this constant relies on the underlying type of an opaque type + +warning: 3 warnings emitted + diff --git a/src/test/ui/specialization/transmute-specialization.rs b/src/test/ui/specialization/transmute-specialization.rs index 499334d983b1f..d2587cdce2226 100644 --- a/src/test/ui/specialization/transmute-specialization.rs +++ b/src/test/ui/specialization/transmute-specialization.rs @@ -1,5 +1,4 @@ -// run-pass - +// check-pass #![feature(specialization)] //~ WARN the feature `specialization` is incomplete trait Specializable { type Output; } @@ -11,5 +10,7 @@ impl Specializable for T { fn main() { unsafe { std::mem::transmute::::Output>(0); + //~^ WARN relying on the underlying type of an opaque type in the type system + //~| WARN this was previously accepted by the compiler but is being phased out } } diff --git a/src/test/ui/specialization/transmute-specialization.stderr b/src/test/ui/specialization/transmute-specialization.stderr index a0ea72415a189..5a15577816f6b 100644 --- a/src/test/ui/specialization/transmute-specialization.stderr +++ b/src/test/ui/specialization/transmute-specialization.stderr @@ -1,5 +1,5 @@ warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/transmute-specialization.rs:3:12 + --> $DIR/transmute-specialization.rs:2:12 | LL | #![feature(specialization)] | ^^^^^^^^^^^^^^ @@ -8,5 +8,16 @@ LL | #![feature(specialization)] = note: see issue #31844 for more information = help: consider using `min_specialization` instead, which is more stable and complete -warning: 1 warning emitted +warning: relying on the underlying type of an opaque type in the type system + --> $DIR/transmute-specialization.rs:12:9 + | +LL | std::mem::transmute::::Output>(0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(hidden_type_of_opaque_types_in_type_system)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue # + = note: checking whether this transmute is valid relies on the underlying type of an opaque type + +warning: 2 warnings emitted diff --git a/src/test/ui/type-alias-impl-trait/in-where-clause.rs b/src/test/ui/type-alias-impl-trait/in-where-clause.rs new file mode 100644 index 0000000000000..ea7e132a02638 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/in-where-clause.rs @@ -0,0 +1,15 @@ +// check-pass +// This previously caused a query cycle as we evaluated +// `1 + 2` with `Reveal::All` during typeck, causing us to +// to get the concrete type of `Bar` while computing it. +#![feature(type_alias_impl_trait)] +type Bar = impl Sized; + +fn foo() -> Bar +where + Bar: Send, +{ + [0; 1 + 2] +} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/issue-53092-2.rs b/src/test/ui/type-alias-impl-trait/issue-53092-2.rs index 438ac35fdea51..1f8169683482d 100644 --- a/src/test/ui/type-alias-impl-trait/issue-53092-2.rs +++ b/src/test/ui/type-alias-impl-trait/issue-53092-2.rs @@ -7,7 +7,8 @@ const CONST_BUG: Bug = unsafe { std::mem::transmute(|_: u8| ()) }; //~^ ERROR: cannot transmute fn make_bug>() -> Bug { - |x| x.into() //~ ERROR the trait bound `U: From` is not satisfied + |x| x.into() + //~^ ERROR the trait bound `U: From` is not satisfied } fn main() { diff --git a/src/test/ui/type-alias-impl-trait/issue-53092-2.stderr b/src/test/ui/type-alias-impl-trait/issue-53092-2.stderr index 1b89d55711dbd..1f51652c70731 100644 --- a/src/test/ui/type-alias-impl-trait/issue-53092-2.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-53092-2.stderr @@ -9,7 +9,6 @@ note: ...which requires type-checking `CONST_BUG`... | LL | const CONST_BUG: Bug = unsafe { std::mem::transmute(|_: u8| ()) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which requires computing layout of `Bug`... = note: ...which requires normalizing `Bug`... = note: ...which again requires computing type of `Bug::{opaque#0}`, completing the cycle note: cycle used when checking item types in top-level module @@ -31,7 +30,7 @@ LL | const CONST_BUG: Bug = unsafe { std::mem::transmute(|_: u8| ()) }; | ^^^^^^^^^^^^^^^^^^^ | = note: source type: `[closure@$DIR/issue-53092-2.rs:6:61: 6:68]` (0 bits) - = note: target type: `Bug` (size can vary because of [type error]) + = note: target type: `[type error]` (this type does not have a fixed size) error[E0277]: the trait bound `U: From` is not satisfied --> $DIR/issue-53092-2.rs:10:5 diff --git a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr index 337708b876524..7434b75ca1e8b 100644 --- a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr +++ b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr @@ -13,7 +13,7 @@ LL | let _: foo::Foo = std::mem::transmute(0u8); | ^^^^^^^^^^^^^^^^^^^ | = note: source type: `u8` (8 bits) - = note: target type: `Foo` (size can vary because of [type error]) + = note: target type: `[type error]` (this type does not have a fixed size) error: aborting due to 2 previous errors diff --git a/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs index c2ab6a9d10aa6..5117d83a4203d 100644 --- a/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs +++ b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs @@ -12,7 +12,8 @@ const LEAK_FREE: Bar = leak_free(); fn leak_free_test() { match LEAK_FREE { LEAK_FREE => (), - //~^ `Bar` cannot be used in patterns + //~^ ERROR constant pattern depends on a generic parameter + //~| ERROR constant pattern depends on a generic parameter _ => (), } } diff --git a/src/test/ui/type-alias-impl-trait/structural-match-no-leak.stderr b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.stderr index dbc183f54f46b..eda1cc3ac51da 100644 --- a/src/test/ui/type-alias-impl-trait/structural-match-no-leak.stderr +++ b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.stderr @@ -1,8 +1,14 @@ -error: `Bar` cannot be used in patterns +error: constant pattern depends on a generic parameter --> $DIR/structural-match-no-leak.rs:14:9 | LL | LEAK_FREE => (), | ^^^^^^^^^ -error: aborting due to previous error +error: constant pattern depends on a generic parameter + --> $DIR/structural-match-no-leak.rs:14:9 + | +LL | LEAK_FREE => (), + | ^^^^^^^^^ + +error: aborting due to 2 previous errors diff --git a/src/test/ui/type-alias-impl-trait/structural-match.rs b/src/test/ui/type-alias-impl-trait/structural-match.rs index 7cc9ccaabdca4..77a2b95adcb92 100644 --- a/src/test/ui/type-alias-impl-trait/structural-match.rs +++ b/src/test/ui/type-alias-impl-trait/structural-match.rs @@ -13,7 +13,8 @@ const VALUE: Foo = value(); fn test() { match VALUE { VALUE => (), - //~^ `Foo` cannot be used in patterns + //~^ ERROR constant pattern depends on a generic parameter + //~| ERROR constant pattern depends on a generic parameter _ => (), } } diff --git a/src/test/ui/type-alias-impl-trait/structural-match.stderr b/src/test/ui/type-alias-impl-trait/structural-match.stderr index 61287f268066e..bec2c2318440d 100644 --- a/src/test/ui/type-alias-impl-trait/structural-match.stderr +++ b/src/test/ui/type-alias-impl-trait/structural-match.stderr @@ -1,8 +1,14 @@ -error: `Foo` cannot be used in patterns +error: constant pattern depends on a generic parameter --> $DIR/structural-match.rs:15:9 | LL | VALUE => (), | ^^^^^ -error: aborting due to previous error +error: constant pattern depends on a generic parameter + --> $DIR/structural-match.rs:15:9 + | +LL | VALUE => (), + | ^^^^^ + +error: aborting due to 2 previous errors