diff options
| author | bors <bors@rust-lang.org> | 2024-02-09 21:06:12 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-02-09 21:06:12 +0000 |
| commit | d44e3b95cb9d410d89cb8ab3233906a33f43756a (patch) | |
| tree | 0e7416fd47b7d79015233d6516cdece2ebd0fe88 /compiler | |
| parent | f4cfd872028398da2b2d85c368c51f4d007dc6af (diff) | |
| parent | 3c1b7a741f4adcc29324836db6e4fe078589debb (diff) | |
| download | rust-d44e3b95cb9d410d89cb8ab3233906a33f43756a.tar.gz rust-d44e3b95cb9d410d89cb8ab3233906a33f43756a.zip | |
Auto merge of #120852 - matthiaskrgr:rollup-01pr8gj, r=matthiaskrgr
Rollup of 11 pull requests Successful merges: - #120351 (Implement SystemTime for UEFI) - #120354 (improve normalization of `Pointee::Metadata`) - #120776 (Move path implementations into `sys`) - #120790 (better error message on download CI LLVM failure) - #120806 (Clippy subtree update) - #120815 (Improve `Option::inspect` docs) - #120822 (Emit more specific diagnostics when enums fail to cast with `as`) - #120827 (Print image input file and checksum in CI only) - #120836 (hide impls if trait bound is proven from env) - #120844 (Build DebugInfo for async closures) - #120851 (Remove duplicate release note) r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
9 files changed, 192 insertions, 108 deletions
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 76c9ac6614a..f961cd2d00b 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -461,6 +461,7 @@ pub fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll D } ty::FnDef(..) | ty::FnPtr(_) => build_subroutine_type_di_node(cx, unique_type_id), ty::Closure(..) => build_closure_env_di_node(cx, unique_type_id), + ty::CoroutineClosure(..) => build_closure_env_di_node(cx, unique_type_id), ty::Coroutine(..) => enums::build_coroutine_di_node(cx, unique_type_id), ty::Adt(def, ..) => match def.adt_kind() { AdtKind::Struct => build_struct_type_di_node(cx, unique_type_id), @@ -1068,6 +1069,7 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>( let (&def_id, up_var_tys) = match closure_or_coroutine_ty.kind() { ty::Coroutine(def_id, args) => (def_id, args.as_coroutine().prefix_tys()), ty::Closure(def_id, args) => (def_id, args.as_closure().upvar_tys()), + ty::CoroutineClosure(def_id, args) => (def_id, args.as_coroutine_closure().upvar_tys()), _ => { bug!( "build_upvar_field_di_nodes() called with non-closure-or-coroutine-type: {:?}", @@ -1153,7 +1155,8 @@ fn build_closure_env_di_node<'ll, 'tcx>( unique_type_id: UniqueTypeId<'tcx>, ) -> DINodeCreationResult<'ll> { let closure_env_type = unique_type_id.expect_ty(); - let &ty::Closure(def_id, _args) = closure_env_type.kind() else { + let &(ty::Closure(def_id, _) | ty::CoroutineClosure(def_id, _)) = closure_env_type.kind() + else { bug!("build_closure_env_di_node() called with non-closure-type: {:?}", closure_env_type) }; let containing_scope = get_namespace_for_item(cx, def_id); diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index b4512af38e3..e3e48ecb3aa 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1985,10 +1985,9 @@ fn generic_simd_intrinsic<'ll, 'tcx>( match in_elem.kind() { ty::RawPtr(p) => { - let (metadata, check_sized) = p.ty.ptr_metadata_ty(bx.tcx, |ty| { + let metadata = p.ty.ptr_metadata_ty(bx.tcx, |ty| { bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty) }); - assert!(!check_sized); // we are in codegen, so we shouldn't see these types require!( metadata.is_unit(), InvalidMonomorphization::CastFatPointer { span, name, ty: in_elem } @@ -2000,10 +1999,9 @@ fn generic_simd_intrinsic<'ll, 'tcx>( } match out_elem.kind() { ty::RawPtr(p) => { - let (metadata, check_sized) = p.ty.ptr_metadata_ty(bx.tcx, |ty| { + let metadata = p.ty.ptr_metadata_ty(bx.tcx, |ty| { bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty) }); - assert!(!check_sized); // we are in codegen, so we shouldn't see these types require!( metadata.is_unit(), InvalidMonomorphization::CastFatPointer { span, name, ty: out_elem } diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index 85a2e4778d2..ff20fc5092c 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -377,12 +377,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // to fields, which can yield non-normalized types. So we need to provide a // normalization function. let normalize = |ty| self.tcx.normalize_erasing_regions(self.param_env, ty); - let (meta, only_if_sized) = ty.ptr_metadata_ty(*self.tcx, normalize); - assert!( - !only_if_sized, - "there should be no more 'maybe has that metadata' types during interpretation" - ); - meta + ty.ptr_metadata_ty(*self.tcx, normalize) }; return Ok(meta_ty(caller) == meta_ty(callee)); } diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 58823ea30ce..f21de1609cb 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -448,13 +448,35 @@ impl<'a, 'tcx> CastCheck<'tcx> { ); } } - let msg = "an `as` expression can only be used to convert between primitive \ - types or to coerce to a specific trait object"; + + let (msg, note) = if let ty::Adt(adt, _) = self.expr_ty.kind() + && adt.is_enum() + && self.cast_ty.is_numeric() + { + ( + "an `as` expression can be used to convert enum types to numeric \ + types only if the enum type is unit-only or field-less", + Some( + "see https://doc.rust-lang.org/reference/items/enumerations.html#casting for more information", + ), + ) + } else { + ( + "an `as` expression can only be used to convert between primitive \ + types or to coerce to a specific trait object", + None, + ) + }; + if label { err.span_label(self.span, msg); } else { err.note(msg); } + + if let Some(note) = note { + err.note(note); + } } else { err.span_label(self.span, "invalid cast"); } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index d6e3385c600..f592acd4b6f 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2279,12 +2279,12 @@ impl<'tcx> Ty<'tcx> { } /// Returns the type of metadata for (potentially fat) pointers to this type, - /// and a boolean signifying if this is conditional on this type being `Sized`. - pub fn ptr_metadata_ty( + /// or the struct tail if the metadata type cannot be determined. + pub fn ptr_metadata_ty_or_tail( self, tcx: TyCtxt<'tcx>, normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>, - ) -> (Ty<'tcx>, bool) { + ) -> Result<Ty<'tcx>, Ty<'tcx>> { let tail = tcx.struct_tail_with_normalize(self, normalize, || {}); match tail.kind() { // Sized types @@ -2307,31 +2307,47 @@ impl<'tcx> Ty<'tcx> { | ty::Error(_) // Extern types have metadata = (). | ty::Foreign(..) - // `dyn*` has no metadata + // `dyn*` has metadata = (). | ty::Dynamic(_, _, ty::DynStar) - // If returned by `struct_tail_without_normalization` this is a unit struct + // If returned by `struct_tail_with_normalize` this is a unit struct // without any fields, or not a struct, and therefore is Sized. | ty::Adt(..) - // If returned by `struct_tail_without_normalization` this is the empty tuple, + // If returned by `struct_tail_with_normalize` this is the empty tuple, // a.k.a. unit type, which is Sized - | ty::Tuple(..) => (tcx.types.unit, false), + | ty::Tuple(..) => Ok(tcx.types.unit), + + ty::Str | ty::Slice(_) => Ok(tcx.types.usize), - ty::Str | ty::Slice(_) => (tcx.types.usize, false), ty::Dynamic(_, _, ty::Dyn) => { let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, None); - (tcx.type_of(dyn_metadata).instantiate(tcx, &[tail.into()]), false) - }, + Ok(tcx.type_of(dyn_metadata).instantiate(tcx, &[tail.into()])) + } - // type parameters only have unit metadata if they're sized, so return true - // to make sure we double check this during confirmation - ty::Param(_) | ty::Alias(..) => (tcx.types.unit, true), + // We don't know the metadata of `self`, but it must be equal to the + // metadata of `tail`. + ty::Param(_) | ty::Alias(..) => Err(tail), ty::Infer(ty::TyVar(_)) | ty::Bound(..) | ty::Placeholder(..) - | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { - bug!("`ptr_metadata_ty` applied to unexpected type: {:?} (tail = {:?})", self, tail) - } + | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => bug!( + "`ptr_metadata_ty_or_tail` applied to unexpected type: {self:?} (tail = {tail:?})" + ), + } + } + + /// Returns the type of metadata for (potentially fat) pointers to this type. + /// Causes an ICE if the metadata type cannot be determined. + pub fn ptr_metadata_ty( + self, + tcx: TyCtxt<'tcx>, + normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>, + ) -> Ty<'tcx> { + match self.ptr_metadata_ty_or_tail(tcx, normalize) { + Ok(metadata) => metadata, + Err(tail) => bug!( + "`ptr_metadata_ty` failed to get metadata for type: {self:?} (tail = {tail:?})" + ), } } diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 239072dfc8e..3b9515e1670 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -8,7 +8,7 @@ use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::Reveal; use rustc_middle::traits::solve::inspect::ProbeKind; use rustc_middle::traits::solve::{ - CandidateSource, CanonicalResponse, Certainty, Goal, QueryResult, + CandidateSource, CanonicalResponse, Certainty, Goal, MaybeCause, QueryResult, }; use rustc_middle::traits::BuiltinImplSource; use rustc_middle::ty::fast_reject::{SimplifiedType, TreatParams}; @@ -276,25 +276,16 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { &mut self, goal: Goal<'tcx, G>, ) -> Vec<Candidate<'tcx>> { - let dummy_candidate = |this: &mut EvalCtxt<'_, 'tcx>, certainty| { - let source = CandidateSource::BuiltinImpl(BuiltinImplSource::Misc); - let result = this.evaluate_added_goals_and_make_canonical_response(certainty).unwrap(); - let mut dummy_probe = this.inspect.new_probe(); - dummy_probe.probe_kind(ProbeKind::TraitCandidate { source, result: Ok(result) }); - this.inspect.finish_probe(dummy_probe); - vec![Candidate { source, result }] - }; - let Some(normalized_self_ty) = self.try_normalize_ty(goal.param_env, goal.predicate.self_ty()) else { debug!("overflow while evaluating self type"); - return dummy_candidate(self, Certainty::OVERFLOW); + return self.forced_ambiguity(MaybeCause::Overflow); }; if normalized_self_ty.is_ty_var() { debug!("self type has been normalized to infer"); - return dummy_candidate(self, Certainty::AMBIGUOUS); + return self.forced_ambiguity(MaybeCause::Ambiguity); } let goal = @@ -315,11 +306,26 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { self.assemble_param_env_candidates(goal, &mut candidates); - self.assemble_coherence_unknowable_candidates(goal, &mut candidates); + match self.solver_mode() { + SolverMode::Normal => self.discard_impls_shadowed_by_env(goal, &mut candidates), + SolverMode::Coherence => { + self.assemble_coherence_unknowable_candidates(goal, &mut candidates) + } + } candidates } + fn forced_ambiguity(&mut self, cause: MaybeCause) -> Vec<Candidate<'tcx>> { + let source = CandidateSource::BuiltinImpl(BuiltinImplSource::Misc); + let certainty = Certainty::Maybe(cause); + let result = self.evaluate_added_goals_and_make_canonical_response(certainty).unwrap(); + let mut dummy_probe = self.inspect.new_probe(); + dummy_probe.probe_kind(ProbeKind::TraitCandidate { source, result: Ok(result) }); + self.inspect.finish_probe(dummy_probe); + vec![Candidate { source, result }] + } + #[instrument(level = "debug", skip_all)] fn assemble_non_blanket_impl_candidates<G: GoalKind<'tcx>>( &mut self, @@ -779,6 +785,12 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } } + /// In coherence we have to not only care about all impls we know about, but + /// also consider impls which may get added in a downstream or sibling crate + /// or which an upstream impl may add in a minor release. + /// + /// To do so we add an ambiguous candidate in case such an unknown impl could + /// apply to the current goal. #[instrument(level = "debug", skip_all)] fn assemble_coherence_unknowable_candidates<G: GoalKind<'tcx>>( &mut self, @@ -786,11 +798,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { candidates: &mut Vec<Candidate<'tcx>>, ) { let tcx = self.tcx(); - match self.solver_mode() { - SolverMode::Normal => return, - SolverMode::Coherence => {} - }; - let result = self.probe_misc_candidate("coherence unknowable").enter(|ecx| { let trait_ref = goal.predicate.trait_ref(tcx); #[derive(Debug)] @@ -820,6 +827,51 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } } + /// If there's a where-bound for the current goal, do not use any impl candidates + /// to prove the current goal. Most importantly, if there is a where-bound which does + /// not specify any associated types, we do not allow normalizing the associated type + /// by using an impl, even if it would apply. + /// + /// <https://github.com/rust-lang/trait-system-refactor-initiative/issues/76> + // FIXME(@lcnr): The current structure here makes me unhappy and feels ugly. idk how + // to improve this however. However, this should make it fairly straightforward to refine + // the filtering going forward, so it seems alright-ish for now. + fn discard_impls_shadowed_by_env<G: GoalKind<'tcx>>( + &mut self, + goal: Goal<'tcx, G>, + candidates: &mut Vec<Candidate<'tcx>>, + ) { + let tcx = self.tcx(); + let trait_goal: Goal<'tcx, ty::TraitPredicate<'tcx>> = + goal.with(tcx, goal.predicate.trait_ref(tcx)); + let mut trait_candidates_from_env = Vec::new(); + self.assemble_param_env_candidates(trait_goal, &mut trait_candidates_from_env); + self.assemble_alias_bound_candidates(trait_goal, &mut trait_candidates_from_env); + if !trait_candidates_from_env.is_empty() { + let trait_env_result = self.merge_candidates(trait_candidates_from_env); + match trait_env_result.unwrap().value.certainty { + // If proving the trait goal succeeds by using the env, + // we freely drop all impl candidates. + // + // FIXME(@lcnr): It feels like this could easily hide + // a forced ambiguity candidate added earlier. + // This feels dangerous. + Certainty::Yes => { + candidates.retain(|c| match c.source { + CandidateSource::Impl(_) | CandidateSource::BuiltinImpl(_) => false, + CandidateSource::ParamEnv(_) | CandidateSource::AliasBound => true, + }); + } + // If it is still ambiguous we instead just force the whole goal + // to be ambig and wait for inference constraints. See + // tests/ui/traits/next-solver/env-shadows-impls/ambig-env-no-shadow.rs + Certainty::Maybe(cause) => { + *candidates = self.forced_ambiguity(cause); + } + } + } + } + /// If there are multiple ways to prove a trait or projection goal, we have /// to somehow try to merge the candidates into one. If that fails, we return /// ambiguity. @@ -832,34 +884,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { let responses = candidates.iter().map(|c| c.result).collect::<Vec<_>>(); if let Some(result) = self.try_merge_responses(&responses) { return Ok(result); + } else { + self.flounder(&responses) } - - // We then check whether we should prioritize `ParamEnv` candidates. - // - // Doing so is incomplete and would therefore be unsound during coherence. - match self.solver_mode() { - SolverMode::Coherence => (), - // Prioritize `ParamEnv` candidates only if they do not guide inference. - // - // This is still incomplete as we may add incorrect region bounds. - SolverMode::Normal => { - let param_env_responses = candidates - .iter() - .filter(|c| { - matches!( - c.source, - CandidateSource::ParamEnv(_) | CandidateSource::AliasBound - ) - }) - .map(|c| c.result) - .collect::<Vec<_>>(); - if let Some(result) = self.try_merge_responses(¶m_env_responses) { - // We strongly prefer alias and param-env bounds here, even if they affect inference. - // See https://github.com/rust-lang/trait-system-refactor-initiative/issues/11. - return Ok(result); - } - } - } - self.flounder(&responses) } } diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs index 47ba549022d..d177109c420 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs @@ -491,6 +491,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { let tcx = ecx.tcx(); + let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, None); + assert_eq!(metadata_def_id, goal.predicate.def_id()); ecx.probe_misc_candidate("builtin pointee").enter(|ecx| { let metadata_ty = match goal.predicate.self_ty().kind() { ty::Bool @@ -522,7 +524,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { } ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => { - // FIXME(ptr_metadata): It would also be possible to return a `Ok(Ambig)` with no constraints. + // This is the "fallback impl" for type parameters, unnormalizable projections + // and opaque types: If the `self_ty` is `Sized`, then the metadata is `()`. + // FIXME(ptr_metadata): This impl overlaps with the other impls and shouldn't + // exist. Instead, `Pointee<Metadata = ()>` should be a supertrait of `Sized`. let sized_predicate = ty::TraitRef::from_lang_item( tcx, LangItem::Sized, @@ -536,30 +541,16 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { ty::Adt(def, args) if def.is_struct() => match def.non_enum_variant().tail_opt() { None => tcx.types.unit, - Some(field_def) => { - let self_ty = field_def.ty(tcx, args); - // FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`? - ecx.add_goal( - GoalSource::Misc, - goal.with(tcx, goal.predicate.with_self_ty(tcx, self_ty)), - ); - return ecx - .evaluate_added_goals_and_make_canonical_response(Certainty::Yes); + Some(tail_def) => { + let tail_ty = tail_def.ty(tcx, args); + Ty::new_projection(tcx, metadata_def_id, [tail_ty]) } }, ty::Adt(_, _) => tcx.types.unit, ty::Tuple(elements) => match elements.last() { None => tcx.types.unit, - Some(&self_ty) => { - // FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`? - ecx.add_goal( - GoalSource::Misc, - goal.with(tcx, goal.predicate.with_self_ty(tcx, self_ty)), - ); - return ecx - .evaluate_added_goals_and_make_canonical_response(Certainty::Yes); - } + Some(&tail_ty) => Ty::new_projection(tcx, metadata_def_id, [tail_ty]), }, ty::Infer( diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index fd8306bbc0b..d271a0ea33b 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1935,10 +1935,11 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // Integers and floats are always Sized, and so have unit type metadata. | ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true, - // type parameters, opaques, and unnormalized projections have pointer - // metadata if they're known (e.g. by the param_env) to be sized + // We normalize from `Wrapper<Tail>::Metadata` to `Tail::Metadata` if able. + // Otherwise, type parameters, opaques, and unnormalized projections have + // unit metadata if they're known (e.g. by the param_env) to be sized. ty::Param(_) | ty::Alias(..) - if selcx.infcx.predicate_must_hold_modulo_regions( + if self_ty != tail || selcx.infcx.predicate_must_hold_modulo_regions( &obligation.with( selcx.tcx(), ty::TraitRef::from_lang_item(selcx.tcx(), LangItem::Sized, obligation.cause.span(),[self_ty]), @@ -2312,7 +2313,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>( assert_eq!(metadata_def_id, item_def_id); let mut obligations = Vec::new(); - let (metadata_ty, check_is_sized) = self_ty.ptr_metadata_ty(tcx, |ty| { + let normalize = |ty| { normalize_with_depth_to( selcx, obligation.param_env, @@ -2321,16 +2322,27 @@ fn confirm_builtin_candidate<'cx, 'tcx>( ty, &mut obligations, ) + }; + let metadata_ty = self_ty.ptr_metadata_ty_or_tail(tcx, normalize).unwrap_or_else(|tail| { + if tail == self_ty { + // This is the "fallback impl" for type parameters, unnormalizable projections + // and opaque types: If the `self_ty` is `Sized`, then the metadata is `()`. + // FIXME(ptr_metadata): This impl overlaps with the other impls and shouldn't + // exist. Instead, `Pointee<Metadata = ()>` should be a supertrait of `Sized`. + let sized_predicate = ty::TraitRef::from_lang_item( + tcx, + LangItem::Sized, + obligation.cause.span(), + [self_ty], + ); + obligations.push(obligation.with(tcx, sized_predicate)); + tcx.types.unit + } else { + // We know that `self_ty` has the same metadata as `tail`. This allows us + // to prove predicates like `Wrapper<Tail>::Metadata == Tail::Metadata`. + Ty::new_projection(tcx, metadata_def_id, [tail]) + } }); - if check_is_sized { - let sized_predicate = ty::TraitRef::from_lang_item( - tcx, - LangItem::Sized, - obligation.cause.span(), - [self_ty], - ); - obligations.push(obligation.with(tcx, sized_predicate)); - } (metadata_ty.into(), obligations) } else { bug!("unexpected builtin trait with associated type: {:?}", obligation.predicate); diff --git a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs index 4c0c57377e0..a050b30317a 100644 --- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs +++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs @@ -41,7 +41,28 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { /// not entirely accurate if inference variables are involved. /// /// This version may conservatively fail when outlives obligations - /// are required. + /// are required. Therefore, this version should only be used for + /// optimizations or diagnostics and be treated as if it can always + /// return `false`. + /// + /// # Example + /// + /// ``` + /// # #![allow(dead_code)] + /// trait Trait {} + /// + /// fn check<T: Trait>() {} + /// + /// fn foo<T: 'static>() + /// where + /// &'static T: Trait, + /// { + /// // Evaluating `&'?0 T: Trait` adds a `'?0: 'static` outlives obligation, + /// // which means that `predicate_must_hold_considering_regions` will return + /// // `false`. + /// check::<&'_ T>(); + /// } + /// ``` fn predicate_must_hold_considering_regions( &self, obligation: &PredicateObligation<'tcx>, |
