Skip to content

Commit a475551

Browse files
committed
Auto merge of rust-lang#133339 - jieyouxu:rollup-gav0nvr, r=jieyouxu
Rollup of 8 pull requests Successful merges: - rust-lang#133238 (re-export `is_loongarch_feature_detected`) - rust-lang#133288 (Support `each_ref` and `each_mut` in `[T; N]` in constant expressions.) - rust-lang#133311 (Miri subtree update) - rust-lang#133313 (Use arc4random of libc for RTEMS target) - rust-lang#133319 (Simplify `fulfill_implication`) - rust-lang#133323 (Bail in effects in old solver if self ty is ty var) - rust-lang#133330 (library: update comment around close()) - rust-lang#133337 (Fix typo in `std::thread::Scope::spawn` documentation.) r? `@ghost` `@rustbot` modify labels: rollup
2 parents a7d9ebd + 874cf85 commit a475551

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+1701
-921
lines changed

compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs

+2-7
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ use rustc_hir as hir;
7070
use rustc_hir::def_id::{DefId, LocalDefId};
7171
use rustc_infer::infer::TyCtxtInferExt;
7272
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
73+
use rustc_infer::traits::ObligationCause;
7374
use rustc_infer::traits::specialization_graph::Node;
7475
use rustc_middle::ty::trait_def::TraitSpecializationKind;
7576
use rustc_middle::ty::{
@@ -210,13 +211,7 @@ fn get_impl_args(
210211
impl1_def_id.to_def_id(),
211212
impl1_args,
212213
impl2_node,
213-
|_, span| {
214-
traits::ObligationCause::new(
215-
impl1_span,
216-
impl1_def_id,
217-
traits::ObligationCauseCode::WhereClause(impl2_node.def_id(), span),
218-
)
219-
},
214+
&ObligationCause::misc(impl1_span, impl1_def_id),
220215
);
221216

222217
let errors = ocx.select_all_or_error();

compiler/rustc_trait_selection/src/traits/effects.rs

+5
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ pub fn evaluate_host_effect_obligation<'tcx>(
2727
);
2828
}
2929

30+
// Force ambiguity for infer self ty.
31+
if obligation.predicate.self_ty().is_ty_var() {
32+
return Err(EvaluationFailure::Ambiguous);
33+
}
34+
3035
match evaluate_host_effect_from_bounds(selcx, obligation) {
3136
Ok(result) => return Ok(result),
3237
Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),

compiler/rustc_trait_selection/src/traits/specialize/mod.rs

+100-91
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,24 @@ use rustc_data_structures::fx::FxIndexSet;
1515
use rustc_errors::codes::*;
1616
use rustc_errors::{Diag, EmissionGuarantee};
1717
use rustc_hir::def_id::{DefId, LocalDefId};
18-
use rustc_infer::infer::DefineOpaqueTypes;
1918
use rustc_middle::bug;
2019
use rustc_middle::query::LocalCrate;
2120
use rustc_middle::ty::print::PrintTraitRefExt as _;
22-
use rustc_middle::ty::{
23-
self, GenericArgsRef, ImplSubject, Ty, TyCtxt, TypeVisitableExt, TypingMode,
24-
};
21+
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt, TypingMode};
2522
use rustc_session::lint::builtin::{COHERENCE_LEAK_CHECK, ORDER_DEPENDENT_TRAIT_OBJECTS};
2623
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, sym};
24+
use rustc_type_ir::solve::NoSolution;
2725
use specialization_graph::GraphExt;
2826
use tracing::{debug, instrument};
2927

30-
use super::{SelectionContext, util};
3128
use crate::error_reporting::traits::to_pretty_impl_header;
3229
use crate::errors::NegativePositiveConflict;
33-
use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt};
30+
use crate::infer::{InferCtxt, TyCtxtInferExt};
3431
use crate::traits::select::IntercrateAmbiguityCause;
35-
use crate::traits::{FutureCompatOverlapErrorKind, ObligationCause, ObligationCtxt, coherence};
32+
use crate::traits::{
33+
FutureCompatOverlapErrorKind, ObligationCause, ObligationCtxt, coherence,
34+
predicates_for_generics,
35+
};
3636

3737
/// Information pertinent to an overlapping impl error.
3838
#[derive(Debug)]
@@ -87,9 +87,14 @@ pub fn translate_args<'tcx>(
8787
source_args: GenericArgsRef<'tcx>,
8888
target_node: specialization_graph::Node,
8989
) -> GenericArgsRef<'tcx> {
90-
translate_args_with_cause(infcx, param_env, source_impl, source_args, target_node, |_, _| {
91-
ObligationCause::dummy()
92-
})
90+
translate_args_with_cause(
91+
infcx,
92+
param_env,
93+
source_impl,
94+
source_args,
95+
target_node,
96+
&ObligationCause::dummy(),
97+
)
9398
}
9499

95100
/// Like [translate_args], but obligations from the parent implementation
@@ -104,7 +109,7 @@ pub fn translate_args_with_cause<'tcx>(
104109
source_impl: DefId,
105110
source_args: GenericArgsRef<'tcx>,
106111
target_node: specialization_graph::Node,
107-
cause: impl Fn(usize, Span) -> ObligationCause<'tcx>,
112+
cause: &ObligationCause<'tcx>,
108113
) -> GenericArgsRef<'tcx> {
109114
debug!(
110115
"translate_args({:?}, {:?}, {:?}, {:?})",
@@ -123,7 +128,7 @@ pub fn translate_args_with_cause<'tcx>(
123128
}
124129

125130
fulfill_implication(infcx, param_env, source_trait_ref, source_impl, target_impl, cause)
126-
.unwrap_or_else(|()| {
131+
.unwrap_or_else(|_| {
127132
bug!(
128133
"When translating generic parameters from {source_impl:?} to \
129134
{target_impl:?}, the expected specialization failed to hold"
@@ -137,6 +142,84 @@ pub fn translate_args_with_cause<'tcx>(
137142
source_args.rebase_onto(infcx.tcx, source_impl, target_args)
138143
}
139144

145+
/// Attempt to fulfill all obligations of `target_impl` after unification with
146+
/// `source_trait_ref`. If successful, returns the generic parameters for *all* the
147+
/// generics of `target_impl`, including both those needed to unify with
148+
/// `source_trait_ref` and those whose identity is determined via a where
149+
/// clause in the impl.
150+
fn fulfill_implication<'tcx>(
151+
infcx: &InferCtxt<'tcx>,
152+
param_env: ty::ParamEnv<'tcx>,
153+
source_trait_ref: ty::TraitRef<'tcx>,
154+
source_impl: DefId,
155+
target_impl: DefId,
156+
cause: &ObligationCause<'tcx>,
157+
) -> Result<GenericArgsRef<'tcx>, NoSolution> {
158+
debug!(
159+
"fulfill_implication({:?}, trait_ref={:?} |- {:?} applies)",
160+
param_env, source_trait_ref, target_impl
161+
);
162+
163+
let ocx = ObligationCtxt::new(infcx);
164+
let source_trait_ref = ocx.normalize(cause, param_env, source_trait_ref);
165+
166+
if !ocx.select_all_or_error().is_empty() {
167+
infcx.dcx().span_delayed_bug(
168+
infcx.tcx.def_span(source_impl),
169+
format!("failed to fully normalize {source_trait_ref}"),
170+
);
171+
return Err(NoSolution);
172+
}
173+
174+
let target_args = infcx.fresh_args_for_item(DUMMY_SP, target_impl);
175+
let target_trait_ref = ocx.normalize(
176+
cause,
177+
param_env,
178+
infcx
179+
.tcx
180+
.impl_trait_ref(target_impl)
181+
.expect("expected source impl to be a trait impl")
182+
.instantiate(infcx.tcx, target_args),
183+
);
184+
185+
// do the impls unify? If not, no specialization.
186+
ocx.eq(cause, param_env, source_trait_ref, target_trait_ref)?;
187+
188+
// Now check that the source trait ref satisfies all the where clauses of the target impl.
189+
// This is not just for correctness; we also need this to constrain any params that may
190+
// only be referenced via projection predicates.
191+
let predicates = ocx.normalize(
192+
cause,
193+
param_env,
194+
infcx.tcx.predicates_of(target_impl).instantiate(infcx.tcx, target_args),
195+
);
196+
let obligations = predicates_for_generics(|_, _| cause.clone(), param_env, predicates);
197+
ocx.register_obligations(obligations);
198+
199+
let errors = ocx.select_all_or_error();
200+
if !errors.is_empty() {
201+
// no dice!
202+
debug!(
203+
"fulfill_implication: for impls on {:?} and {:?}, \
204+
could not fulfill: {:?} given {:?}",
205+
source_trait_ref,
206+
target_trait_ref,
207+
errors,
208+
param_env.caller_bounds()
209+
);
210+
return Err(NoSolution);
211+
}
212+
213+
debug!(
214+
"fulfill_implication: an impl for {:?} specializes {:?}",
215+
source_trait_ref, target_trait_ref
216+
);
217+
218+
// Now resolve the *generic parameters* we built for the target earlier, replacing
219+
// the inference variables inside with whatever we got from fulfillment.
220+
Ok(infcx.resolve_vars_if_possible(target_args))
221+
}
222+
140223
pub(super) fn specialization_enabled_in(tcx: TyCtxt<'_>, _: LocalCrate) -> bool {
141224
tcx.features().specialization() || tcx.features().min_specialization()
142225
}
@@ -182,99 +265,25 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId,
182265
return false;
183266
}
184267

185-
// create a parameter environment corresponding to a (placeholder) instantiation of impl1
186-
let penv = tcx.param_env(impl1_def_id);
268+
// create a parameter environment corresponding to an identity instantiation of impl1,
269+
// i.e. the most generic instantiation of impl1.
270+
let param_env = tcx.param_env(impl1_def_id);
187271

188272
// Create an infcx, taking the predicates of impl1 as assumptions:
189273
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
190274

191275
// Attempt to prove that impl2 applies, given all of the above.
192276
fulfill_implication(
193277
&infcx,
194-
penv,
278+
param_env,
195279
impl1_trait_header.trait_ref.instantiate_identity(),
196280
impl1_def_id,
197281
impl2_def_id,
198-
|_, _| ObligationCause::dummy(),
282+
&ObligationCause::dummy(),
199283
)
200284
.is_ok()
201285
}
202286

203-
/// Attempt to fulfill all obligations of `target_impl` after unification with
204-
/// `source_trait_ref`. If successful, returns the generic parameters for *all* the
205-
/// generics of `target_impl`, including both those needed to unify with
206-
/// `source_trait_ref` and those whose identity is determined via a where
207-
/// clause in the impl.
208-
fn fulfill_implication<'tcx>(
209-
infcx: &InferCtxt<'tcx>,
210-
param_env: ty::ParamEnv<'tcx>,
211-
source_trait_ref: ty::TraitRef<'tcx>,
212-
source_impl: DefId,
213-
target_impl: DefId,
214-
error_cause: impl Fn(usize, Span) -> ObligationCause<'tcx>,
215-
) -> Result<GenericArgsRef<'tcx>, ()> {
216-
debug!(
217-
"fulfill_implication({:?}, trait_ref={:?} |- {:?} applies)",
218-
param_env, source_trait_ref, target_impl
219-
);
220-
221-
let ocx = ObligationCtxt::new(infcx);
222-
let source_trait_ref = ocx.normalize(&ObligationCause::dummy(), param_env, source_trait_ref);
223-
224-
if !ocx.select_all_or_error().is_empty() {
225-
infcx.dcx().span_delayed_bug(
226-
infcx.tcx.def_span(source_impl),
227-
format!("failed to fully normalize {source_trait_ref}"),
228-
);
229-
}
230-
231-
let source_trait_ref = infcx.resolve_vars_if_possible(source_trait_ref);
232-
let source_trait = ImplSubject::Trait(source_trait_ref);
233-
234-
let selcx = SelectionContext::new(infcx);
235-
let target_args = infcx.fresh_args_for_item(DUMMY_SP, target_impl);
236-
let (target_trait, obligations) =
237-
util::impl_subject_and_oblig(&selcx, param_env, target_impl, target_args, error_cause);
238-
239-
// do the impls unify? If not, no specialization.
240-
let Ok(InferOk { obligations: more_obligations, .. }) = infcx
241-
.at(&ObligationCause::dummy(), param_env)
242-
// Ok to use `Yes`, as all the generic params are already replaced by inference variables,
243-
// which will match the opaque type no matter if it is defining or not.
244-
// Any concrete type that would match the opaque would already be handled by coherence rules,
245-
// and thus either be ok to match here and already have errored, or it won't match, in which
246-
// case there is no issue anyway.
247-
.eq(DefineOpaqueTypes::Yes, source_trait, target_trait)
248-
else {
249-
debug!("fulfill_implication: {:?} does not unify with {:?}", source_trait, target_trait);
250-
return Err(());
251-
};
252-
253-
// attempt to prove all of the predicates for impl2 given those for impl1
254-
// (which are packed up in penv)
255-
ocx.register_obligations(obligations.chain(more_obligations));
256-
257-
let errors = ocx.select_all_or_error();
258-
if !errors.is_empty() {
259-
// no dice!
260-
debug!(
261-
"fulfill_implication: for impls on {:?} and {:?}, \
262-
could not fulfill: {:?} given {:?}",
263-
source_trait,
264-
target_trait,
265-
errors,
266-
param_env.caller_bounds()
267-
);
268-
return Err(());
269-
}
270-
271-
debug!("fulfill_implication: an impl for {:?} specializes {:?}", source_trait, target_trait);
272-
273-
// Now resolve the *generic parameters* we built for the target earlier, replacing
274-
// the inference variables inside with whatever we got from fulfillment.
275-
Ok(infcx.resolve_vars_if_possible(target_args))
276-
}
277-
278287
/// Query provider for `specialization_graph_of`.
279288
pub(super) fn specialization_graph_provider(
280289
tcx: TyCtxt<'_>,

compiler/rustc_trait_selection/src/traits/util.rs

+2-33
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,16 @@ use std::collections::BTreeMap;
33
use rustc_data_structures::fx::FxIndexMap;
44
use rustc_errors::Diag;
55
use rustc_hir::def_id::DefId;
6-
use rustc_infer::infer::{InferCtxt, InferOk};
6+
use rustc_infer::infer::InferCtxt;
77
pub use rustc_infer::traits::util::*;
88
use rustc_middle::bug;
99
use rustc_middle::ty::{
10-
self, GenericArgsRef, ImplSubject, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
11-
TypeVisitableExt, Upcast,
10+
self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, Upcast,
1211
};
1312
use rustc_span::Span;
1413
use smallvec::{SmallVec, smallvec};
1514
use tracing::debug;
1615

17-
use super::{NormalizeExt, ObligationCause, PredicateObligation, SelectionContext};
18-
1916
///////////////////////////////////////////////////////////////////////////
2017
// `TraitAliasExpander` iterator
2118
///////////////////////////////////////////////////////////////////////////
@@ -166,34 +163,6 @@ impl<'tcx> Iterator for TraitAliasExpander<'tcx> {
166163
// Other
167164
///////////////////////////////////////////////////////////////////////////
168165

169-
/// Instantiate all bound parameters of the impl subject with the given args,
170-
/// returning the resulting subject and all obligations that arise.
171-
/// The obligations are closed under normalization.
172-
pub(crate) fn impl_subject_and_oblig<'a, 'tcx>(
173-
selcx: &SelectionContext<'a, 'tcx>,
174-
param_env: ty::ParamEnv<'tcx>,
175-
impl_def_id: DefId,
176-
impl_args: GenericArgsRef<'tcx>,
177-
cause: impl Fn(usize, Span) -> ObligationCause<'tcx>,
178-
) -> (ImplSubject<'tcx>, impl Iterator<Item = PredicateObligation<'tcx>>) {
179-
let subject = selcx.tcx().impl_subject(impl_def_id);
180-
let subject = subject.instantiate(selcx.tcx(), impl_args);
181-
182-
let InferOk { value: subject, obligations: normalization_obligations1 } =
183-
selcx.infcx.at(&ObligationCause::dummy(), param_env).normalize(subject);
184-
185-
let predicates = selcx.tcx().predicates_of(impl_def_id);
186-
let predicates = predicates.instantiate(selcx.tcx(), impl_args);
187-
let InferOk { value: predicates, obligations: normalization_obligations2 } =
188-
selcx.infcx.at(&ObligationCause::dummy(), param_env).normalize(predicates);
189-
let impl_obligations = super::predicates_for_generics(cause, param_env, predicates);
190-
191-
let impl_obligations =
192-
impl_obligations.chain(normalization_obligations1).chain(normalization_obligations2);
193-
194-
(subject, impl_obligations)
195-
}
196-
197166
/// Casts a trait reference into a reference to one of its super
198167
/// traits; returns `None` if `target_trait_def_id` is not a
199168
/// supertrait.

0 commit comments

Comments
 (0)