Auto merge of #126979 - matthiaskrgr:rollup-fdqledz, r=matthiaskrgr
Rollup of 10 pull requests Successful merges: - #126724 (Fix a span in `parse_ty_bare_fn`.) - #126812 (Rename `tcx` to `cx` in new solver generic code) - #126879 (fix Drop items getting leaked in Filter::next_chunk) - #126925 (Change E0369 to give note informations for foreign items.) - #126938 (miri: make sure we can find link_section statics even for the local crate) - #126954 (resolve: Tweak some naming around import ambiguities) - #126964 (Migrate `lto-empty`, `invalid-so` and `issue-20626` `run-make` tests to rmake.rs) - #126968 (Don't ICE during RPITIT refinement checking for resolution errors after normalization) - #126971 (Bump black, ruff and platformdirs) - #126973 (Fix bad replacement for unsafe extern block suggestion) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
7731802570
62 changed files with 906 additions and 607 deletions
|
@ -2126,7 +2126,8 @@ pub struct BareFnTy {
|
|||
pub ext: Extern,
|
||||
pub generic_params: ThinVec<GenericParam>,
|
||||
pub decl: P<FnDecl>,
|
||||
/// Span of the `fn(...) -> ...` part.
|
||||
/// Span of the `[unsafe] [extern] fn(...) -> ...` part, i.e. everything
|
||||
/// after the generic params (if there are any, e.g. `for<'a>`).
|
||||
pub decl_span: Span,
|
||||
}
|
||||
|
||||
|
|
|
@ -464,7 +464,7 @@ impl<'a> AstValidator<'a> {
|
|||
{
|
||||
self.dcx().emit_err(errors::InvalidSafetyOnExtern {
|
||||
item_span: span,
|
||||
block: self.current_extern_span(),
|
||||
block: self.current_extern_span().shrink_to_lo(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -221,7 +221,7 @@ pub enum ExternBlockSuggestion {
|
|||
pub struct InvalidSafetyOnExtern {
|
||||
#[primary_span]
|
||||
pub item_span: Span,
|
||||
#[suggestion(code = "", applicability = "maybe-incorrect")]
|
||||
#[suggestion(code = "unsafe ", applicability = "machine-applicable", style = "verbose")]
|
||||
pub block: Span,
|
||||
}
|
||||
|
||||
|
|
|
@ -171,10 +171,10 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
|
|||
}
|
||||
// Resolve any lifetime variables that may have been introduced during normalization.
|
||||
let Ok((trait_bounds, impl_bounds)) = infcx.fully_resolve((trait_bounds, impl_bounds)) else {
|
||||
// This code path is not reached in any tests, but may be reachable. If
|
||||
// this is triggered, it should be converted to `delayed_bug` and the
|
||||
// triggering case turned into a test.
|
||||
tcx.dcx().bug("encountered errors when checking RPITIT refinement (resolution)");
|
||||
// If resolution didn't fully complete, we cannot continue checking RPITIT refinement, and
|
||||
// delay a bug as the original code contains load-bearing errors.
|
||||
tcx.dcx().delayed_bug("encountered errors when checking RPITIT refinement (resolution)");
|
||||
return;
|
||||
};
|
||||
|
||||
// For quicker lookup, use an `IndexSet` (we don't use one earlier because
|
||||
|
|
|
@ -2831,32 +2831,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
errors: Vec<FulfillmentError<'tcx>>,
|
||||
suggest_derive: bool,
|
||||
) {
|
||||
let all_local_types_needing_impls =
|
||||
errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() {
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
|
||||
match pred.self_ty().kind() {
|
||||
ty::Adt(def, _) => def.did().is_local(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
_ => false,
|
||||
});
|
||||
let mut preds: Vec<_> = errors
|
||||
let preds: Vec<_> = errors
|
||||
.iter()
|
||||
.filter_map(|e| match e.obligation.predicate.kind().skip_binder() {
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => Some(pred),
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
|
||||
match pred.self_ty().kind() {
|
||||
ty::Adt(_, _) => Some(pred),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
preds.sort_by_key(|pred| pred.trait_ref.to_string());
|
||||
let def_ids = preds
|
||||
|
||||
// Note for local items and foreign items respectively.
|
||||
let (mut local_preds, mut foreign_preds): (Vec<_>, Vec<_>) =
|
||||
preds.iter().partition(|&pred| {
|
||||
if let ty::Adt(def, _) = pred.self_ty().kind() {
|
||||
def.did().is_local()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
});
|
||||
|
||||
local_preds.sort_by_key(|pred: &&ty::TraitPredicate<'_>| pred.trait_ref.to_string());
|
||||
let local_def_ids = local_preds
|
||||
.iter()
|
||||
.filter_map(|pred| match pred.self_ty().kind() {
|
||||
ty::Adt(def, _) => Some(def.did()),
|
||||
_ => None,
|
||||
})
|
||||
.collect::<FxIndexSet<_>>();
|
||||
let mut spans: MultiSpan = def_ids
|
||||
let mut local_spans: MultiSpan = local_def_ids
|
||||
.iter()
|
||||
.filter_map(|def_id| {
|
||||
let span = self.tcx.def_span(*def_id);
|
||||
|
@ -2864,11 +2870,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
})
|
||||
.collect::<Vec<_>>()
|
||||
.into();
|
||||
|
||||
for pred in &preds {
|
||||
for pred in &local_preds {
|
||||
match pred.self_ty().kind() {
|
||||
ty::Adt(def, _) if def.did().is_local() => {
|
||||
spans.push_span_label(
|
||||
ty::Adt(def, _) => {
|
||||
local_spans.push_span_label(
|
||||
self.tcx.def_span(def.did()),
|
||||
format!("must implement `{}`", pred.trait_ref.print_trait_sugared()),
|
||||
);
|
||||
|
@ -2876,24 +2881,69 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
if all_local_types_needing_impls && spans.primary_span().is_some() {
|
||||
let msg = if preds.len() == 1 {
|
||||
if local_spans.primary_span().is_some() {
|
||||
let msg = if local_preds.len() == 1 {
|
||||
format!(
|
||||
"an implementation of `{}` might be missing for `{}`",
|
||||
preds[0].trait_ref.print_trait_sugared(),
|
||||
preds[0].self_ty()
|
||||
local_preds[0].trait_ref.print_trait_sugared(),
|
||||
local_preds[0].self_ty()
|
||||
)
|
||||
} else {
|
||||
format!(
|
||||
"the following type{} would have to `impl` {} required trait{} for this \
|
||||
operation to be valid",
|
||||
pluralize!(def_ids.len()),
|
||||
if def_ids.len() == 1 { "its" } else { "their" },
|
||||
pluralize!(preds.len()),
|
||||
pluralize!(local_def_ids.len()),
|
||||
if local_def_ids.len() == 1 { "its" } else { "their" },
|
||||
pluralize!(local_preds.len()),
|
||||
)
|
||||
};
|
||||
err.span_note(spans, msg);
|
||||
err.span_note(local_spans, msg);
|
||||
}
|
||||
|
||||
foreign_preds.sort_by_key(|pred: &&ty::TraitPredicate<'_>| pred.trait_ref.to_string());
|
||||
let foreign_def_ids = foreign_preds
|
||||
.iter()
|
||||
.filter_map(|pred| match pred.self_ty().kind() {
|
||||
ty::Adt(def, _) => Some(def.did()),
|
||||
_ => None,
|
||||
})
|
||||
.collect::<FxIndexSet<_>>();
|
||||
let mut foreign_spans: MultiSpan = foreign_def_ids
|
||||
.iter()
|
||||
.filter_map(|def_id| {
|
||||
let span = self.tcx.def_span(*def_id);
|
||||
if span.is_dummy() { None } else { Some(span) }
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.into();
|
||||
for pred in &foreign_preds {
|
||||
match pred.self_ty().kind() {
|
||||
ty::Adt(def, _) => {
|
||||
foreign_spans.push_span_label(
|
||||
self.tcx.def_span(def.did()),
|
||||
format!("not implement `{}`", pred.trait_ref.print_trait_sugared()),
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
if foreign_spans.primary_span().is_some() {
|
||||
let msg = if foreign_preds.len() == 1 {
|
||||
format!(
|
||||
"the foreign item type `{}` doesn't implement `{}`",
|
||||
foreign_preds[0].self_ty(),
|
||||
foreign_preds[0].trait_ref.print_trait_sugared()
|
||||
)
|
||||
} else {
|
||||
format!(
|
||||
"the foreign item type{} {} implement required trait{} for this \
|
||||
operation to be valid",
|
||||
pluralize!(foreign_def_ids.len()),
|
||||
if foreign_def_ids.len() > 1 { "don't" } else { "doesn't" },
|
||||
pluralize!(foreign_preds.len()),
|
||||
)
|
||||
};
|
||||
err.span_note(foreign_spans, msg);
|
||||
}
|
||||
|
||||
let preds: Vec<_> = errors
|
||||
|
|
|
@ -32,14 +32,14 @@ where
|
|||
&mut self,
|
||||
goal: Goal<I, (I::Term, I::Term, ty::AliasRelationDirection)>,
|
||||
) -> QueryResult<I> {
|
||||
let tcx = self.cx();
|
||||
let cx = self.cx();
|
||||
let Goal { param_env, predicate: (lhs, rhs, direction) } = goal;
|
||||
debug_assert!(lhs.to_alias_term().is_some() || rhs.to_alias_term().is_some());
|
||||
|
||||
// Structurally normalize the lhs.
|
||||
let lhs = if let Some(alias) = lhs.to_alias_term() {
|
||||
let term = self.next_term_infer_of_kind(lhs);
|
||||
self.add_normalizes_to_goal(goal.with(tcx, ty::NormalizesTo { alias, term }));
|
||||
self.add_normalizes_to_goal(goal.with(cx, ty::NormalizesTo { alias, term }));
|
||||
term
|
||||
} else {
|
||||
lhs
|
||||
|
@ -48,7 +48,7 @@ where
|
|||
// Structurally normalize the rhs.
|
||||
let rhs = if let Some(alias) = rhs.to_alias_term() {
|
||||
let term = self.next_term_infer_of_kind(rhs);
|
||||
self.add_normalizes_to_goal(goal.with(tcx, ty::NormalizesTo { alias, term }));
|
||||
self.add_normalizes_to_goal(goal.with(cx, ty::NormalizesTo { alias, term }));
|
||||
term
|
||||
} else {
|
||||
rhs
|
||||
|
|
|
@ -36,11 +36,11 @@ where
|
|||
{
|
||||
fn self_ty(self) -> I::Ty;
|
||||
|
||||
fn trait_ref(self, tcx: I) -> ty::TraitRef<I>;
|
||||
fn trait_ref(self, cx: I) -> ty::TraitRef<I>;
|
||||
|
||||
fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> Self;
|
||||
fn with_self_ty(self, cx: I, self_ty: I::Ty) -> Self;
|
||||
|
||||
fn trait_def_id(self, tcx: I) -> I::DefId;
|
||||
fn trait_def_id(self, cx: I) -> I::DefId;
|
||||
|
||||
/// Try equating an assumption predicate against a goal's predicate. If it
|
||||
/// holds, then execute the `then` callback, which should do any additional
|
||||
|
@ -82,7 +82,7 @@ where
|
|||
assumption: I::Clause,
|
||||
) -> Result<Candidate<I>, NoSolution> {
|
||||
Self::probe_and_match_goal_against_assumption(ecx, source, goal, assumption, |ecx| {
|
||||
let tcx = ecx.cx();
|
||||
let cx = ecx.cx();
|
||||
let ty::Dynamic(bounds, _, _) = goal.predicate.self_ty().kind() else {
|
||||
panic!("expected object type in `probe_and_consider_object_bound_candidate`");
|
||||
};
|
||||
|
@ -91,7 +91,7 @@ where
|
|||
structural_traits::predicates_for_object_candidate(
|
||||
ecx,
|
||||
goal.param_env,
|
||||
goal.predicate.trait_ref(tcx),
|
||||
goal.predicate.trait_ref(cx),
|
||||
bounds,
|
||||
),
|
||||
);
|
||||
|
@ -340,15 +340,15 @@ where
|
|||
goal: Goal<I, G>,
|
||||
candidates: &mut Vec<Candidate<I>>,
|
||||
) {
|
||||
let tcx = self.cx();
|
||||
tcx.for_each_relevant_impl(
|
||||
goal.predicate.trait_def_id(tcx),
|
||||
let cx = self.cx();
|
||||
cx.for_each_relevant_impl(
|
||||
goal.predicate.trait_def_id(cx),
|
||||
goal.predicate.self_ty(),
|
||||
|impl_def_id| {
|
||||
// For every `default impl`, there's always a non-default `impl`
|
||||
// that will *also* apply. There's no reason to register a candidate
|
||||
// for this impl, since it is *not* proof that the trait goal holds.
|
||||
if tcx.impl_is_default(impl_def_id) {
|
||||
if cx.impl_is_default(impl_def_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -366,8 +366,8 @@ where
|
|||
goal: Goal<I, G>,
|
||||
candidates: &mut Vec<Candidate<I>>,
|
||||
) {
|
||||
let tcx = self.cx();
|
||||
let trait_def_id = goal.predicate.trait_def_id(tcx);
|
||||
let cx = self.cx();
|
||||
let trait_def_id = goal.predicate.trait_def_id(cx);
|
||||
|
||||
// N.B. When assembling built-in candidates for lang items that are also
|
||||
// `auto` traits, then the auto trait candidate that is assembled in
|
||||
|
@ -378,47 +378,47 @@ where
|
|||
// `solve::trait_goals` instead.
|
||||
let result = if let Err(guar) = goal.predicate.error_reported() {
|
||||
G::consider_error_guaranteed_candidate(self, guar)
|
||||
} else if tcx.trait_is_auto(trait_def_id) {
|
||||
} else if cx.trait_is_auto(trait_def_id) {
|
||||
G::consider_auto_trait_candidate(self, goal)
|
||||
} else if tcx.trait_is_alias(trait_def_id) {
|
||||
} else if cx.trait_is_alias(trait_def_id) {
|
||||
G::consider_trait_alias_candidate(self, goal)
|
||||
} else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::Sized) {
|
||||
} else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::Sized) {
|
||||
G::consider_builtin_sized_candidate(self, goal)
|
||||
} else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::Copy)
|
||||
|| tcx.is_lang_item(trait_def_id, TraitSolverLangItem::Clone)
|
||||
} else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::Copy)
|
||||
|| cx.is_lang_item(trait_def_id, TraitSolverLangItem::Clone)
|
||||
{
|
||||
G::consider_builtin_copy_clone_candidate(self, goal)
|
||||
} else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::PointerLike) {
|
||||
} else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::PointerLike) {
|
||||
G::consider_builtin_pointer_like_candidate(self, goal)
|
||||
} else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::FnPtrTrait) {
|
||||
} else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::FnPtrTrait) {
|
||||
G::consider_builtin_fn_ptr_trait_candidate(self, goal)
|
||||
} else if let Some(kind) = self.cx().fn_trait_kind_from_def_id(trait_def_id) {
|
||||
G::consider_builtin_fn_trait_candidates(self, goal, kind)
|
||||
} else if let Some(kind) = self.cx().async_fn_trait_kind_from_def_id(trait_def_id) {
|
||||
G::consider_builtin_async_fn_trait_candidates(self, goal, kind)
|
||||
} else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::AsyncFnKindHelper) {
|
||||
} else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::AsyncFnKindHelper) {
|
||||
G::consider_builtin_async_fn_kind_helper_candidate(self, goal)
|
||||
} else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::Tuple) {
|
||||
} else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::Tuple) {
|
||||
G::consider_builtin_tuple_candidate(self, goal)
|
||||
} else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::PointeeTrait) {
|
||||
} else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::PointeeTrait) {
|
||||
G::consider_builtin_pointee_candidate(self, goal)
|
||||
} else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::Future) {
|
||||
} else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::Future) {
|
||||
G::consider_builtin_future_candidate(self, goal)
|
||||
} else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::Iterator) {
|
||||
} else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::Iterator) {
|
||||
G::consider_builtin_iterator_candidate(self, goal)
|
||||
} else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::FusedIterator) {
|
||||
} else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::FusedIterator) {
|
||||
G::consider_builtin_fused_iterator_candidate(self, goal)
|
||||
} else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::AsyncIterator) {
|
||||
} else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::AsyncIterator) {
|
||||
G::consider_builtin_async_iterator_candidate(self, goal)
|
||||
} else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::Coroutine) {
|
||||
} else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::Coroutine) {
|
||||
G::consider_builtin_coroutine_candidate(self, goal)
|
||||
} else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::DiscriminantKind) {
|
||||
} else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::DiscriminantKind) {
|
||||
G::consider_builtin_discriminant_kind_candidate(self, goal)
|
||||
} else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::AsyncDestruct) {
|
||||
} else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::AsyncDestruct) {
|
||||
G::consider_builtin_async_destruct_candidate(self, goal)
|
||||
} else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::Destruct) {
|
||||
} else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::Destruct) {
|
||||
G::consider_builtin_destruct_candidate(self, goal)
|
||||
} else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::TransmuteTrait) {
|
||||
} else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::TransmuteTrait) {
|
||||
G::consider_builtin_transmute_candidate(self, goal)
|
||||
} else {
|
||||
Err(NoSolution)
|
||||
|
@ -428,7 +428,7 @@ where
|
|||
|
||||
// There may be multiple unsize candidates for a trait with several supertraits:
|
||||
// `trait Foo: Bar<A> + Bar<B>` and `dyn Foo: Unsize<dyn Bar<_>>`
|
||||
if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::Unsize) {
|
||||
if cx.is_lang_item(trait_def_id, TraitSolverLangItem::Unsize) {
|
||||
candidates.extend(G::consider_structural_builtin_unsize_candidates(self, goal));
|
||||
}
|
||||
}
|
||||
|
@ -557,8 +557,8 @@ where
|
|||
goal: Goal<I, G>,
|
||||
candidates: &mut Vec<Candidate<I>>,
|
||||
) {
|
||||
let tcx = self.cx();
|
||||
if !tcx.trait_may_be_implemented_via_object(goal.predicate.trait_def_id(tcx)) {
|
||||
let cx = self.cx();
|
||||
if !cx.trait_may_be_implemented_via_object(goal.predicate.trait_def_id(cx)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -596,7 +596,7 @@ where
|
|||
};
|
||||
|
||||
// Do not consider built-in object impls for non-object-safe types.
|
||||
if bounds.principal_def_id().is_some_and(|def_id| !tcx.trait_is_object_safe(def_id)) {
|
||||
if bounds.principal_def_id().is_some_and(|def_id| !cx.trait_is_object_safe(def_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -614,7 +614,7 @@ where
|
|||
self,
|
||||
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
|
||||
goal,
|
||||
bound.with_self_ty(tcx, self_ty),
|
||||
bound.with_self_ty(cx, self_ty),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -624,14 +624,13 @@ where
|
|||
// since we don't need to look at any supertrait or anything if we are doing
|
||||
// a projection goal.
|
||||
if let Some(principal) = bounds.principal() {
|
||||
let principal_trait_ref = principal.with_self_ty(tcx, self_ty);
|
||||
for (idx, assumption) in D::elaborate_supertraits(tcx, principal_trait_ref).enumerate()
|
||||
{
|
||||
let principal_trait_ref = principal.with_self_ty(cx, self_ty);
|
||||
for (idx, assumption) in D::elaborate_supertraits(cx, principal_trait_ref).enumerate() {
|
||||
candidates.extend(G::probe_and_consider_object_bound_candidate(
|
||||
self,
|
||||
CandidateSource::BuiltinImpl(BuiltinImplSource::Object(idx)),
|
||||
goal,
|
||||
assumption.upcast(tcx),
|
||||
assumption.upcast(cx),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -649,11 +648,11 @@ where
|
|||
goal: Goal<I, G>,
|
||||
candidates: &mut Vec<Candidate<I>>,
|
||||
) {
|
||||
let tcx = self.cx();
|
||||
let cx = self.cx();
|
||||
|
||||
candidates.extend(self.probe_trait_candidate(CandidateSource::CoherenceUnknowable).enter(
|
||||
|ecx| {
|
||||
let trait_ref = goal.predicate.trait_ref(tcx);
|
||||
let trait_ref = goal.predicate.trait_ref(cx);
|
||||
if ecx.trait_ref_is_knowable(goal.param_env, trait_ref)? {
|
||||
Err(NoSolution)
|
||||
} else {
|
||||
|
@ -678,9 +677,9 @@ where
|
|||
goal: Goal<I, G>,
|
||||
candidates: &mut Vec<Candidate<I>>,
|
||||
) {
|
||||
let tcx = self.cx();
|
||||
let cx = self.cx();
|
||||
let trait_goal: Goal<I, ty::TraitPredicate<I>> =
|
||||
goal.with(tcx, goal.predicate.trait_ref(tcx));
|
||||
goal.with(cx, goal.predicate.trait_ref(cx));
|
||||
|
||||
let mut trait_candidates_from_env = vec![];
|
||||
self.probe(|_| ProbeKind::ShadowedEnvProbing).enter(|ecx| {
|
||||
|
|
|
@ -23,7 +23,7 @@ where
|
|||
D: SolverDelegate<Interner = I>,
|
||||
I: Interner,
|
||||
{
|
||||
let tcx = ecx.cx();
|
||||
let cx = ecx.cx();
|
||||
match ty.kind() {
|
||||
ty::Uint(_)
|
||||
| ty::Int(_)
|
||||
|
@ -36,7 +36,7 @@ where
|
|||
| ty::Char => Ok(vec![]),
|
||||
|
||||
// Treat `str` like it's defined as `struct str([u8]);`
|
||||
ty::Str => Ok(vec![ty::Binder::dummy(Ty::new_slice(tcx, Ty::new_u8(tcx)))]),
|
||||
ty::Str => Ok(vec![ty::Binder::dummy(Ty::new_slice(cx, Ty::new_u8(cx)))]),
|
||||
|
||||
ty::Dynamic(..)
|
||||
| ty::Param(..)
|
||||
|
@ -79,21 +79,21 @@ where
|
|||
.cx()
|
||||
.bound_coroutine_hidden_types(def_id)
|
||||
.into_iter()
|
||||
.map(|bty| bty.instantiate(tcx, args))
|
||||
.map(|bty| bty.instantiate(cx, args))
|
||||
.collect()),
|
||||
|
||||
// For `PhantomData<T>`, we pass `T`.
|
||||
ty::Adt(def, args) if def.is_phantom_data() => Ok(vec![ty::Binder::dummy(args.type_at(0))]),
|
||||
|
||||
ty::Adt(def, args) => {
|
||||
Ok(def.all_field_tys(tcx).iter_instantiated(tcx, args).map(ty::Binder::dummy).collect())
|
||||
Ok(def.all_field_tys(cx).iter_instantiated(cx, args).map(ty::Binder::dummy).collect())
|
||||
}
|
||||
|
||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
|
||||
// We can resolve the `impl Trait` to its concrete type,
|
||||
// which enforces a DAG between the functions requiring
|
||||
// the auto trait bounds in question.
|
||||
Ok(vec![ty::Binder::dummy(tcx.type_of(def_id).instantiate(tcx, args))])
|
||||
Ok(vec![ty::Binder::dummy(cx.type_of(def_id).instantiate(cx, args))])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -247,18 +247,18 @@ where
|
|||
|
||||
// Returns a binder of the tupled inputs types and output type from a builtin callable type.
|
||||
pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<I: Interner>(
|
||||
tcx: I,
|
||||
cx: I,
|
||||
self_ty: I::Ty,
|
||||
goal_kind: ty::ClosureKind,
|
||||
) -> Result<Option<ty::Binder<I, (I::Ty, I::Ty)>>, NoSolution> {
|
||||
match self_ty.kind() {
|
||||
// keep this in sync with assemble_fn_pointer_candidates until the old solver is removed.
|
||||
ty::FnDef(def_id, args) => {
|
||||
let sig = tcx.fn_sig(def_id);
|
||||
if sig.skip_binder().is_fn_trait_compatible() && !tcx.has_target_features(def_id) {
|
||||
let sig = cx.fn_sig(def_id);
|
||||
if sig.skip_binder().is_fn_trait_compatible() && !cx.has_target_features(def_id) {
|
||||
Ok(Some(
|
||||
sig.instantiate(tcx, args)
|
||||
.map_bound(|sig| (Ty::new_tup(tcx, sig.inputs().as_slice()), sig.output())),
|
||||
sig.instantiate(cx, args)
|
||||
.map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
|
||||
))
|
||||
} else {
|
||||
Err(NoSolution)
|
||||
|
@ -268,7 +268,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<I: Intern
|
|||
ty::FnPtr(sig) => {
|
||||
if sig.is_fn_trait_compatible() {
|
||||
Ok(Some(
|
||||
sig.map_bound(|sig| (Ty::new_tup(tcx, sig.inputs().as_slice()), sig.output())),
|
||||
sig.map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
|
||||
))
|
||||
} else {
|
||||
Err(NoSolution)
|
||||
|
@ -323,10 +323,10 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<I: Intern
|
|||
}
|
||||
|
||||
coroutine_closure_to_certain_coroutine(
|
||||
tcx,
|
||||
cx,
|
||||
goal_kind,
|
||||
// No captures by ref, so this doesn't matter.
|
||||
Region::new_static(tcx),
|
||||
Region::new_static(cx),
|
||||
def_id,
|
||||
args,
|
||||
sig,
|
||||
|
@ -339,9 +339,9 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<I: Intern
|
|||
}
|
||||
|
||||
coroutine_closure_to_ambiguous_coroutine(
|
||||
tcx,
|
||||
cx,
|
||||
goal_kind, // No captures by ref, so this doesn't matter.
|
||||
Region::new_static(tcx),
|
||||
Region::new_static(cx),
|
||||
def_id,
|
||||
args,
|
||||
sig,
|
||||
|
@ -403,7 +403,7 @@ pub(in crate::solve) struct AsyncCallableRelevantTypes<I: Interner> {
|
|||
// which enforces the closure is actually callable with the given trait. When we
|
||||
// know the kind already, we can short-circuit this check.
|
||||
pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I: Interner>(
|
||||
tcx: I,
|
||||
cx: I,
|
||||
self_ty: I::Ty,
|
||||
goal_kind: ty::ClosureKind,
|
||||
env_region: I::Region,
|
||||
|
@ -422,9 +422,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
|
|||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
coroutine_closure_to_certain_coroutine(
|
||||
tcx, goal_kind, env_region, def_id, args, sig,
|
||||
)
|
||||
coroutine_closure_to_certain_coroutine(cx, goal_kind, env_region, def_id, args, sig)
|
||||
} else {
|
||||
// When we don't know the closure kind (and therefore also the closure's upvars,
|
||||
// which are computed at the same time), we must delay the computation of the
|
||||
|
@ -435,15 +433,15 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
|
|||
// coroutine upvars respecting the closure kind.
|
||||
nested.push(
|
||||
ty::TraitRef::new(
|
||||
tcx,
|
||||
tcx.require_lang_item(TraitSolverLangItem::AsyncFnKindHelper),
|
||||
[kind_ty, Ty::from_closure_kind(tcx, goal_kind)],
|
||||
cx,
|
||||
cx.require_lang_item(TraitSolverLangItem::AsyncFnKindHelper),
|
||||
[kind_ty, Ty::from_closure_kind(cx, goal_kind)],
|
||||
)
|
||||
.upcast(tcx),
|
||||
.upcast(cx),
|
||||
);
|
||||
|
||||
coroutine_closure_to_ambiguous_coroutine(
|
||||
tcx, goal_kind, env_region, def_id, args, sig,
|
||||
cx, goal_kind, env_region, def_id, args, sig,
|
||||
)
|
||||
};
|
||||
|
||||
|
@ -458,21 +456,21 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
|
|||
}
|
||||
|
||||
ty::FnDef(..) | ty::FnPtr(..) => {
|
||||
let bound_sig = self_ty.fn_sig(tcx);
|
||||
let bound_sig = self_ty.fn_sig(cx);
|
||||
let sig = bound_sig.skip_binder();
|
||||
let future_trait_def_id = tcx.require_lang_item(TraitSolverLangItem::Future);
|
||||
let future_trait_def_id = cx.require_lang_item(TraitSolverLangItem::Future);
|
||||
// `FnDef` and `FnPtr` only implement `AsyncFn*` when their
|
||||
// return type implements `Future`.
|
||||
let nested = vec![
|
||||
bound_sig
|
||||
.rebind(ty::TraitRef::new(tcx, future_trait_def_id, [sig.output()]))
|
||||
.upcast(tcx),
|
||||
.rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()]))
|
||||
.upcast(cx),
|
||||
];
|
||||
let future_output_def_id = tcx.require_lang_item(TraitSolverLangItem::FutureOutput);
|
||||
let future_output_ty = Ty::new_projection(tcx, future_output_def_id, [sig.output()]);
|
||||
let future_output_def_id = cx.require_lang_item(TraitSolverLangItem::FutureOutput);
|
||||
let future_output_ty = Ty::new_projection(cx, future_output_def_id, [sig.output()]);
|
||||
Ok((
|
||||
bound_sig.rebind(AsyncCallableRelevantTypes {
|
||||
tupled_inputs_ty: Ty::new_tup(tcx, sig.inputs().as_slice()),
|
||||
tupled_inputs_ty: Ty::new_tup(cx, sig.inputs().as_slice()),
|
||||
output_coroutine_ty: sig.output(),
|
||||
coroutine_return_ty: future_output_ty,
|
||||
}),
|
||||
|
@ -483,13 +481,13 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
|
|||
let args = args.as_closure();
|
||||
let bound_sig = args.sig();
|
||||
let sig = bound_sig.skip_binder();
|
||||
let future_trait_def_id = tcx.require_lang_item(TraitSolverLangItem::Future);
|
||||
let future_trait_def_id = cx.require_lang_item(TraitSolverLangItem::Future);
|
||||
// `Closure`s only implement `AsyncFn*` when their return type
|
||||
// implements `Future`.
|
||||
let mut nested = vec![
|
||||
bound_sig
|
||||
.rebind(ty::TraitRef::new(tcx, future_trait_def_id, [sig.output()]))
|
||||
.upcast(tcx),
|
||||
.rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()]))
|
||||
.upcast(cx),
|
||||
];
|
||||
|
||||
// Additionally, we need to check that the closure kind
|
||||
|
@ -501,7 +499,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
|
|||
}
|
||||
} else {
|
||||
let async_fn_kind_trait_def_id =
|
||||
tcx.require_lang_item(TraitSolverLangItem::AsyncFnKindHelper);
|
||||
cx.require_lang_item(TraitSolverLangItem::AsyncFnKindHelper);
|
||||
// When we don't know the closure kind (and therefore also the closure's upvars,
|
||||
// which are computed at the same time), we must delay the computation of the
|
||||
// generator's upvars. We do this using the `AsyncFnKindHelper`, which as a trait
|
||||
|
@ -511,16 +509,16 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
|
|||
// coroutine upvars respecting the closure kind.
|
||||
nested.push(
|
||||
ty::TraitRef::new(
|
||||
tcx,
|
||||
cx,
|
||||
async_fn_kind_trait_def_id,
|
||||
[kind_ty, Ty::from_closure_kind(tcx, goal_kind)],
|
||||
[kind_ty, Ty::from_closure_kind(cx, goal_kind)],
|
||||
)
|
||||
.upcast(tcx),
|
||||
.upcast(cx),
|
||||
);
|
||||
}
|
||||
|
||||
let future_output_def_id = tcx.require_lang_item(TraitSolverLangItem::FutureOutput);
|
||||
let future_output_ty = Ty::new_projection(tcx, future_output_def_id, [sig.output()]);
|
||||
let future_output_def_id = cx.require_lang_item(TraitSolverLangItem::FutureOutput);
|
||||
let future_output_ty = Ty::new_projection(cx, future_output_def_id, [sig.output()]);
|
||||
Ok((
|
||||
bound_sig.rebind(AsyncCallableRelevantTypes {
|
||||
tupled_inputs_ty: sig.inputs().get(0).unwrap(),
|
||||
|
@ -565,7 +563,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
|
|||
/// Given a coroutine-closure, project to its returned coroutine when we are *certain*
|
||||
/// that the closure's kind is compatible with the goal.
|
||||
fn coroutine_closure_to_certain_coroutine<I: Interner>(
|
||||
tcx: I,
|
||||
cx: I,
|
||||
goal_kind: ty::ClosureKind,
|
||||
goal_region: I::Region,
|
||||
def_id: I::DefId,
|
||||
|
@ -573,9 +571,9 @@ fn coroutine_closure_to_certain_coroutine<I: Interner>(
|
|||
sig: ty::CoroutineClosureSignature<I>,
|
||||
) -> I::Ty {
|
||||
sig.to_coroutine_given_kind_and_upvars(
|
||||
tcx,
|
||||
cx,
|
||||
args.parent_args(),
|
||||
tcx.coroutine_for_closure(def_id),
|
||||
cx.coroutine_for_closure(def_id),
|
||||
goal_kind,
|
||||
goal_region,
|
||||
args.tupled_upvars_ty(),
|
||||
|
@ -589,20 +587,20 @@ fn coroutine_closure_to_certain_coroutine<I: Interner>(
|
|||
///
|
||||
/// Note that we do not also push a `AsyncFnKindHelper` goal here.
|
||||
fn coroutine_closure_to_ambiguous_coroutine<I: Interner>(
|
||||
tcx: I,
|
||||
cx: I,
|
||||
goal_kind: ty::ClosureKind,
|
||||
goal_region: I::Region,
|
||||
def_id: I::DefId,
|
||||
args: ty::CoroutineClosureArgs<I>,
|
||||
sig: ty::CoroutineClosureSignature<I>,
|
||||
) -> I::Ty {
|
||||
let upvars_projection_def_id = tcx.require_lang_item(TraitSolverLangItem::AsyncFnKindUpvars);
|
||||
let upvars_projection_def_id = cx.require_lang_item(TraitSolverLangItem::AsyncFnKindUpvars);
|
||||
let tupled_upvars_ty = Ty::new_projection(
|
||||
tcx,
|
||||
cx,
|
||||
upvars_projection_def_id,
|
||||
[
|
||||
I::GenericArg::from(args.kind_ty()),
|
||||
Ty::from_closure_kind(tcx, goal_kind).into(),
|
||||
Ty::from_closure_kind(cx, goal_kind).into(),
|
||||
goal_region.into(),
|
||||
sig.tupled_inputs_ty.into(),
|
||||
args.tupled_upvars_ty().into(),
|
||||
|
@ -610,10 +608,10 @@ fn coroutine_closure_to_ambiguous_coroutine<I: Interner>(
|
|||
],
|
||||
);
|
||||
sig.to_coroutine(
|
||||
tcx,
|
||||
cx,
|
||||
args.parent_args(),
|
||||
Ty::from_closure_kind(tcx, goal_kind),
|
||||
tcx.coroutine_for_closure(def_id),
|
||||
Ty::from_closure_kind(cx, goal_kind),
|
||||
cx.coroutine_for_closure(def_id),
|
||||
tupled_upvars_ty,
|
||||
)
|
||||
}
|
||||
|
@ -668,28 +666,28 @@ where
|
|||
D: SolverDelegate<Interner = I>,
|
||||
I: Interner,
|
||||
{
|
||||
let tcx = ecx.cx();
|
||||
let cx = ecx.cx();
|
||||
let mut requirements = vec![];
|
||||
requirements
|
||||
.extend(tcx.super_predicates_of(trait_ref.def_id).iter_instantiated(tcx, trait_ref.args));
|
||||
.extend(cx.super_predicates_of(trait_ref.def_id).iter_instantiated(cx, trait_ref.args));
|
||||
|
||||
// FIXME(associated_const_equality): Also add associated consts to
|
||||
// the requirements here.
|
||||
for associated_type_def_id in tcx.associated_type_def_ids(trait_ref.def_id) {
|
||||
for associated_type_def_id in cx.associated_type_def_ids(trait_ref.def_id) {
|
||||
// associated types that require `Self: Sized` do not show up in the built-in
|
||||
// implementation of `Trait for dyn Trait`, and can be dropped here.
|
||||
if tcx.generics_require_sized_self(associated_type_def_id) {
|
||||
if cx.generics_require_sized_self(associated_type_def_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
requirements
|
||||
.extend(tcx.item_bounds(associated_type_def_id).iter_instantiated(tcx, trait_ref.args));
|
||||
.extend(cx.item_bounds(associated_type_def_id).iter_instantiated(cx, trait_ref.args));
|
||||
}
|
||||
|
||||
let mut replace_projection_with = HashMap::default();
|
||||
for bound in object_bounds.iter() {
|
||||
if let ty::ExistentialPredicate::Projection(proj) = bound.skip_binder() {
|
||||
let proj = proj.with_self_ty(tcx, trait_ref.self_ty());
|
||||
let proj = proj.with_self_ty(cx, trait_ref.self_ty());
|
||||
let old_ty = replace_projection_with.insert(proj.def_id(), bound.rebind(proj));
|
||||
assert_eq!(
|
||||
old_ty,
|
||||
|
@ -709,7 +707,7 @@ where
|
|||
folder
|
||||
.nested
|
||||
.into_iter()
|
||||
.chain(folded_requirements.into_iter().map(|clause| Goal::new(tcx, param_env, clause)))
|
||||
.chain(folded_requirements.into_iter().map(|clause| Goal::new(cx, param_env, clause)))
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
|
|
@ -239,14 +239,14 @@ where
|
|||
/// This function takes care of setting up the inference context, setting the anchor,
|
||||
/// and registering opaques from the canonicalized input.
|
||||
fn enter_canonical<R>(
|
||||
tcx: I,
|
||||
cx: I,
|
||||
search_graph: &'a mut search_graph::SearchGraph<I>,
|
||||
canonical_input: CanonicalInput<I>,
|
||||
canonical_goal_evaluation: &mut ProofTreeBuilder<D>,
|
||||
f: impl FnOnce(&mut EvalCtxt<'_, D>, Goal<I, I::Predicate>) -> R,
|
||||
) -> R {
|
||||
let (ref delegate, input, var_values) =
|
||||
SolverDelegate::build_with_canonical(tcx, search_graph.solver_mode(), &canonical_input);
|
||||
SolverDelegate::build_with_canonical(cx, search_graph.solver_mode(), &canonical_input);
|
||||
|
||||
let mut ecx = EvalCtxt {
|
||||
delegate,
|
||||
|
@ -292,9 +292,9 @@ where
|
|||
/// Instead of calling this function directly, use either [EvalCtxt::evaluate_goal]
|
||||
/// if you're inside of the solver or [SolverDelegateEvalExt::evaluate_root_goal] if you're
|
||||
/// outside of it.
|
||||
#[instrument(level = "debug", skip(tcx, search_graph, goal_evaluation), ret)]
|
||||
#[instrument(level = "debug", skip(cx, search_graph, goal_evaluation), ret)]
|
||||
fn evaluate_canonical_goal(
|
||||
tcx: I,
|
||||
cx: I,
|
||||
search_graph: &'a mut search_graph::SearchGraph<I>,
|
||||
canonical_input: CanonicalInput<I>,
|
||||
goal_evaluation: &mut ProofTreeBuilder<D>,
|
||||
|
@ -307,12 +307,12 @@ where
|
|||
// The actual solver logic happens in `ecx.compute_goal`.
|
||||
let result = ensure_sufficient_stack(|| {
|
||||
search_graph.with_new_goal(
|
||||
tcx,
|
||||
cx,
|
||||
canonical_input,
|
||||
&mut canonical_goal_evaluation,
|
||||
|search_graph, canonical_goal_evaluation| {
|
||||
EvalCtxt::enter_canonical(
|
||||
tcx,
|
||||
cx,
|
||||
search_graph,
|
||||
canonical_input,
|
||||
canonical_goal_evaluation,
|
||||
|
@ -506,7 +506,7 @@ where
|
|||
///
|
||||
/// Goals for the next step get directly added to the nested goals of the `EvalCtxt`.
|
||||
fn evaluate_added_goals_step(&mut self) -> Result<Option<Certainty>, NoSolution> {
|
||||
let tcx = self.cx();
|
||||
let cx = self.cx();
|
||||
let mut goals = core::mem::take(&mut self.nested_goals);
|
||||
|
||||
// If this loop did not result in any progress, what's our final certainty.
|
||||
|
@ -516,7 +516,7 @@ where
|
|||
// RHS does not affect projection candidate assembly.
|
||||
let unconstrained_rhs = self.next_term_infer_of_kind(goal.predicate.term);
|
||||
let unconstrained_goal = goal.with(
|
||||
tcx,
|
||||
cx,
|
||||
ty::NormalizesTo { alias: goal.predicate.alias, term: unconstrained_rhs },
|
||||
);
|
||||
|
||||
|
@ -777,7 +777,7 @@ where
|
|||
// NOTE: this check is purely an optimization, the structural eq would
|
||||
// always fail if the term is not an inference variable.
|
||||
if term.is_infer() {
|
||||
let tcx = self.cx();
|
||||
let cx = self.cx();
|
||||
// We need to relate `alias` to `term` treating only the outermost
|
||||
// constructor as rigid, relating any contained generic arguments as
|
||||
// normal. We do this by first structurally equating the `term`
|
||||
|
@ -787,8 +787,8 @@ where
|
|||
// Alternatively we could modify `Equate` for this case by adding another
|
||||
// variant to `StructurallyRelateAliases`.
|
||||
let identity_args = self.fresh_args_for_item(alias.def_id);
|
||||
let rigid_ctor = ty::AliasTerm::new_from_args(tcx, alias.def_id, identity_args);
|
||||
let ctor_term = rigid_ctor.to_term(tcx);
|
||||
let rigid_ctor = ty::AliasTerm::new_from_args(cx, alias.def_id, identity_args);
|
||||
let ctor_term = rigid_ctor.to_term(cx);
|
||||
let obligations =
|
||||
self.delegate.eq_structurally_relating_aliases(param_env, term, ctor_term)?;
|
||||
debug_assert!(obligations.is_empty());
|
||||
|
|
|
@ -323,13 +323,13 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
|
|||
|
||||
pub fn finalize_canonical_goal_evaluation(
|
||||
&mut self,
|
||||
tcx: I,
|
||||
cx: I,
|
||||
) -> Option<I::CanonicalGoalEvaluationStepRef> {
|
||||
self.as_mut().map(|this| match this {
|
||||
DebugSolver::CanonicalGoalEvaluation(evaluation) => {
|
||||
let final_revision = mem::take(&mut evaluation.final_revision).unwrap();
|
||||
let final_revision =
|
||||
tcx.intern_canonical_goal_evaluation_step(final_revision.finalize());
|
||||
cx.intern_canonical_goal_evaluation_step(final_revision.finalize());
|
||||
let kind = WipCanonicalGoalEvaluationKind::Interned { final_revision };
|
||||
assert_eq!(evaluation.kind.replace(kind), None);
|
||||
final_revision
|
||||
|
|
|
@ -34,7 +34,7 @@ use crate::delegate::SolverDelegate;
|
|||
/// How many fixpoint iterations we should attempt inside of the solver before bailing
|
||||
/// with overflow.
|
||||
///
|
||||
/// We previously used `tcx.recursion_limit().0.checked_ilog2().unwrap_or(0)` for this.
|
||||
/// We previously used `cx.recursion_limit().0.checked_ilog2().unwrap_or(0)` for this.
|
||||
/// However, it feels unlikely that uncreasing the recursion limit by a power of two
|
||||
/// to get one more itereation is every useful or desirable. We now instead used a constant
|
||||
/// here. If there ever ends up some use-cases where a bigger number of fixpoint iterations
|
||||
|
@ -285,7 +285,7 @@ where
|
|||
}
|
||||
|
||||
fn response_no_constraints_raw<I: Interner>(
|
||||
tcx: I,
|
||||
cx: I,
|
||||
max_universe: ty::UniverseIndex,
|
||||
variables: I::CanonicalVars,
|
||||
certainty: Certainty,
|
||||
|
@ -294,10 +294,10 @@ fn response_no_constraints_raw<I: Interner>(
|
|||
max_universe,
|
||||
variables,
|
||||
value: Response {
|
||||
var_values: ty::CanonicalVarValues::make_identity(tcx, variables),
|
||||
// FIXME: maybe we should store the "no response" version in tcx, like
|
||||
// we do for tcx.types and stuff.
|
||||
external_constraints: tcx.mk_external_constraints(ExternalConstraintsData::default()),
|
||||
var_values: ty::CanonicalVarValues::make_identity(cx, variables),
|
||||
// FIXME: maybe we should store the "no response" version in cx, like
|
||||
// we do for cx.types and stuff.
|
||||
external_constraints: cx.mk_external_constraints(ExternalConstraintsData::default()),
|
||||
certainty,
|
||||
},
|
||||
defining_opaque_types: Default::default(),
|
||||
|
|
|
@ -19,21 +19,21 @@ where
|
|||
&mut self,
|
||||
goal: Goal<I, ty::NormalizesTo<I>>,
|
||||
) -> QueryResult<I> {
|
||||
let tcx = self.cx();
|
||||
let inherent = goal.predicate.alias.expect_ty(tcx);
|
||||
let cx = self.cx();
|
||||
let inherent = goal.predicate.alias.expect_ty(cx);
|
||||
|
||||
let impl_def_id = tcx.parent(inherent.def_id);
|
||||
let impl_def_id = cx.parent(inherent.def_id);
|
||||
let impl_args = self.fresh_args_for_item(impl_def_id);
|
||||
|
||||
// Equate impl header and add impl where clauses
|
||||
self.eq(
|
||||
goal.param_env,
|
||||
inherent.self_ty(),
|
||||
tcx.type_of(impl_def_id).instantiate(tcx, impl_args),
|
||||
cx.type_of(impl_def_id).instantiate(cx, impl_args),
|
||||
)?;
|
||||
|
||||
// Equate IAT with the RHS of the project goal
|
||||
let inherent_args = inherent.rebase_inherent_args_onto_impl(impl_args, tcx);
|
||||
let inherent_args = inherent.rebase_inherent_args_onto_impl(impl_args, cx);
|
||||
|
||||
// Check both where clauses on the impl and IAT
|
||||
//
|
||||
|
@ -43,12 +43,12 @@ where
|
|||
// and I don't think the assoc item where-bounds are allowed to be coinductive.
|
||||
self.add_goals(
|
||||
GoalSource::Misc,
|
||||
tcx.predicates_of(inherent.def_id)
|
||||
.iter_instantiated(tcx, inherent_args)
|
||||
.map(|pred| goal.with(tcx, pred)),
|
||||
cx.predicates_of(inherent.def_id)
|
||||
.iter_instantiated(cx, inherent_args)
|
||||
.map(|pred| goal.with(cx, pred)),
|
||||
);
|
||||
|
||||
let normalized = tcx.type_of(inherent.def_id).instantiate(tcx, inherent_args);
|
||||
let normalized = cx.type_of(inherent.def_id).instantiate(cx, inherent_args);
|
||||
self.instantiate_normalizes_to_term(goal, normalized.into());
|
||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
}
|
||||
|
|
|
@ -84,16 +84,16 @@ where
|
|||
self.self_ty()
|
||||
}
|
||||
|
||||
fn trait_ref(self, tcx: I) -> ty::TraitRef<I> {
|
||||
self.alias.trait_ref(tcx)
|
||||
fn trait_ref(self, cx: I) -> ty::TraitRef<I> {
|
||||
self.alias.trait_ref(cx)
|
||||
}
|
||||
|
||||
fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> Self {
|
||||
self.with_self_ty(tcx, self_ty)
|
||||
fn with_self_ty(self, cx: I, self_ty: I::Ty) -> Self {
|
||||
self.with_self_ty(cx, self_ty)
|
||||
}
|
||||
|
||||
fn trait_def_id(self, tcx: I) -> I::DefId {
|
||||
self.trait_def_id(tcx)
|
||||
fn trait_def_id(self, cx: I) -> I::DefId {
|
||||
self.trait_def_id(cx)
|
||||
}
|
||||
|
||||
fn probe_and_match_goal_against_assumption(
|
||||
|
@ -105,7 +105,7 @@ where
|
|||
) -> Result<Candidate<I>, NoSolution> {
|
||||
if let Some(projection_pred) = assumption.as_projection_clause() {
|
||||
if projection_pred.projection_def_id() == goal.predicate.def_id() {
|
||||
let tcx = ecx.cx();
|
||||
let cx = ecx.cx();
|
||||
ecx.probe_trait_candidate(source).enter(|ecx| {
|
||||
let assumption_projection_pred =
|
||||
ecx.instantiate_binder_with_infer(projection_pred);
|
||||
|
@ -120,9 +120,9 @@ where
|
|||
// Add GAT where clauses from the trait's definition
|
||||
ecx.add_goals(
|
||||
GoalSource::Misc,
|
||||
tcx.own_predicates_of(goal.predicate.def_id())
|
||||
.iter_instantiated(tcx, goal.predicate.alias.args)
|
||||
.map(|pred| goal.with(tcx, pred)),
|
||||
cx.own_predicates_of(goal.predicate.def_id())
|
||||
.iter_instantiated(cx, goal.predicate.alias.args)
|
||||
.map(|pred| goal.with(cx, pred)),
|
||||
);
|
||||
|
||||
then(ecx)
|
||||
|
@ -140,19 +140,19 @@ where
|
|||
goal: Goal<I, NormalizesTo<I>>,
|
||||
impl_def_id: I::DefId,
|
||||
) -> Result<Candidate<I>, NoSolution> {
|
||||
let tcx = ecx.cx();
|
||||
let cx = ecx.cx();
|
||||
|
||||
let goal_trait_ref = goal.predicate.alias.trait_ref(tcx);
|
||||
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id);
|
||||
let goal_trait_ref = goal.predicate.alias.trait_ref(cx);
|
||||
let impl_trait_ref = cx.impl_trait_ref(impl_def_id);
|
||||
if !ecx.cx().args_may_unify_deep(
|
||||
goal.predicate.alias.trait_ref(tcx).args,
|
||||
goal.predicate.alias.trait_ref(cx).args,
|
||||
impl_trait_ref.skip_binder().args,
|
||||
) {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
// We have to ignore negative impls when projecting.
|
||||
let impl_polarity = tcx.impl_polarity(impl_def_id);
|
||||
let impl_polarity = cx.impl_polarity(impl_def_id);
|
||||
match impl_polarity {
|
||||
ty::ImplPolarity::Negative => return Err(NoSolution),
|
||||
ty::ImplPolarity::Reservation => {
|
||||
|
@ -163,22 +163,22 @@ where
|
|||
|
||||
ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
|
||||
let impl_args = ecx.fresh_args_for_item(impl_def_id);
|
||||
let impl_trait_ref = impl_trait_ref.instantiate(tcx, impl_args);
|
||||
let impl_trait_ref = impl_trait_ref.instantiate(cx, impl_args);
|
||||
|
||||
ecx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?;
|
||||
|
||||
let where_clause_bounds = tcx
|
||||
let where_clause_bounds = cx
|
||||
.predicates_of(impl_def_id)
|
||||
.iter_instantiated(tcx, impl_args)
|
||||
.map(|pred| goal.with(tcx, pred));
|
||||
.iter_instantiated(cx, impl_args)
|
||||
.map(|pred| goal.with(cx, pred));
|
||||
ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds);
|
||||
|
||||
// Add GAT where clauses from the trait's definition
|
||||
ecx.add_goals(
|
||||
GoalSource::Misc,
|
||||
tcx.own_predicates_of(goal.predicate.def_id())
|
||||
.iter_instantiated(tcx, goal.predicate.alias.args)
|
||||
.map(|pred| goal.with(tcx, pred)),
|
||||
cx.own_predicates_of(goal.predicate.def_id())
|
||||
.iter_instantiated(cx, goal.predicate.alias.args)
|
||||
.map(|pred| goal.with(cx, pred)),
|
||||
);
|
||||
|
||||
// In case the associated item is hidden due to specialization, we have to
|
||||
|
@ -195,21 +195,21 @@ where
|
|||
};
|
||||
|
||||
let error_response = |ecx: &mut EvalCtxt<'_, D>, msg: &str| {
|
||||
let guar = tcx.delay_bug(msg);
|
||||
let error_term = match goal.predicate.alias.kind(tcx) {
|
||||
ty::AliasTermKind::ProjectionTy => Ty::new_error(tcx, guar).into(),
|
||||
ty::AliasTermKind::ProjectionConst => Const::new_error(tcx, guar).into(),
|
||||
let guar = cx.delay_bug(msg);
|
||||
let error_term = match goal.predicate.alias.kind(cx) {
|
||||
ty::AliasTermKind::ProjectionTy => Ty::new_error(cx, guar).into(),
|
||||
ty::AliasTermKind::ProjectionConst => Const::new_error(cx, guar).into(),
|
||||
kind => panic!("expected projection, found {kind:?}"),
|
||||
};
|
||||
ecx.instantiate_normalizes_to_term(goal, error_term);
|
||||
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
};
|
||||
|
||||
if !tcx.has_item_definition(target_item_def_id) {
|
||||
if !cx.has_item_definition(target_item_def_id) {
|
||||
return error_response(ecx, "missing item");
|
||||
}
|
||||
|
||||
let target_container_def_id = tcx.parent(target_item_def_id);
|
||||
let target_container_def_id = cx.parent(target_item_def_id);
|
||||
|
||||
// Getting the right args here is complex, e.g. given:
|
||||
// - a goal `<Vec<u32> as Trait<i32>>::Assoc<u64>`
|
||||
|
@ -229,22 +229,22 @@ where
|
|||
target_container_def_id,
|
||||
)?;
|
||||
|
||||
if !tcx.check_args_compatible(target_item_def_id, target_args) {
|
||||
if !cx.check_args_compatible(target_item_def_id, target_args) {
|
||||
return error_response(ecx, "associated item has mismatched arguments");
|
||||
}
|
||||
|
||||
// Finally we construct the actual value of the associated type.
|
||||
let term = match goal.predicate.alias.kind(tcx) {
|
||||
let term = match goal.predicate.alias.kind(cx) {
|
||||
ty::AliasTermKind::ProjectionTy => {
|
||||
tcx.type_of(target_item_def_id).map_bound(|ty| ty.into())
|
||||
cx.type_of(target_item_def_id).map_bound(|ty| ty.into())
|
||||
}
|
||||
ty::AliasTermKind::ProjectionConst => {
|
||||
if tcx.features().associated_const_equality() {
|
||||
if cx.features().associated_const_equality() {
|
||||
panic!("associated const projection is not supported yet")
|
||||
} else {
|
||||
ty::EarlyBinder::bind(
|
||||
Const::new_error_with_message(
|
||||
tcx,
|
||||
cx,
|
||||
"associated const projection is not supported yet",
|
||||
)
|
||||
.into(),
|
||||
|
@ -254,7 +254,7 @@ where
|
|||
kind => panic!("expected projection, found {kind:?}"),
|
||||
};
|
||||
|
||||
ecx.instantiate_normalizes_to_term(goal, term.instantiate(tcx, target_args));
|
||||
ecx.instantiate_normalizes_to_term(goal, term.instantiate(cx, target_args));
|
||||
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
})
|
||||
}
|
||||
|
@ -316,10 +316,10 @@ where
|
|||
goal: Goal<I, Self>,
|
||||
goal_kind: ty::ClosureKind,
|
||||
) -> Result<Candidate<I>, NoSolution> {
|
||||
let tcx = ecx.cx();
|
||||
let cx = ecx.cx();
|
||||
let tupled_inputs_and_output =
|
||||
match structural_traits::extract_tupled_inputs_and_output_from_callable(
|
||||
tcx,
|
||||
cx,
|
||||
goal.predicate.self_ty(),
|
||||
goal_kind,
|
||||
)? {
|
||||
|
@ -329,19 +329,19 @@ where
|
|||
}
|
||||
};
|
||||
let output_is_sized_pred = tupled_inputs_and_output.map_bound(|(_, output)| {
|
||||
ty::TraitRef::new(tcx, tcx.require_lang_item(TraitSolverLangItem::Sized), [output])
|
||||
ty::TraitRef::new(cx, cx.require_lang_item(TraitSolverLangItem::Sized), [output])
|
||||
});
|
||||
|
||||
let pred = tupled_inputs_and_output
|
||||
.map_bound(|(inputs, output)| ty::ProjectionPredicate {
|
||||
projection_term: ty::AliasTerm::new(
|
||||
tcx,
|
||||
cx,
|
||||
goal.predicate.def_id(),
|
||||
[goal.predicate.self_ty(), inputs],
|
||||
),
|
||||
term: output.into(),
|
||||
})
|
||||
.upcast(tcx);
|
||||
.upcast(cx);
|
||||
|
||||
// A built-in `Fn` impl only holds if the output is sized.
|
||||
// (FIXME: technically we only need to check this if the type is a fn ptr...)
|
||||
|
@ -350,7 +350,7 @@ where
|
|||
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
|
||||
goal,
|
||||
pred,
|
||||
[(GoalSource::ImplWhereBound, goal.with(tcx, output_is_sized_pred))],
|
||||
[(GoalSource::ImplWhereBound, goal.with(cx, output_is_sized_pred))],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -359,27 +359,23 @@ where
|
|||
goal: Goal<I, Self>,
|
||||
goal_kind: ty::ClosureKind,
|
||||
) -> Result<Candidate<I>, NoSolution> {
|
||||
let tcx = ecx.cx();
|
||||
let cx = ecx.cx();
|
||||
|
||||
let env_region = match goal_kind {
|
||||
ty::ClosureKind::Fn | ty::ClosureKind::FnMut => goal.predicate.alias.args.region_at(2),
|
||||
// Doesn't matter what this region is
|
||||
ty::ClosureKind::FnOnce => Region::new_static(tcx),
|
||||
ty::ClosureKind::FnOnce => Region::new_static(cx),
|
||||
};
|
||||
let (tupled_inputs_and_output_and_coroutine, nested_preds) =
|
||||
structural_traits::extract_tupled_inputs_and_output_from_async_callable(
|
||||
tcx,
|
||||
cx,
|
||||
goal.predicate.self_ty(),
|
||||
goal_kind,
|
||||
env_region,
|
||||
)?;
|
||||
let output_is_sized_pred = tupled_inputs_and_output_and_coroutine.map_bound(
|
||||
|AsyncCallableRelevantTypes { output_coroutine_ty: output_ty, .. }| {
|
||||
ty::TraitRef::new(
|
||||
tcx,
|
||||
tcx.require_lang_item(TraitSolverLangItem::Sized),
|
||||
[output_ty],
|
||||
)
|
||||
ty::TraitRef::new(cx, cx.require_lang_item(TraitSolverLangItem::Sized), [output_ty])
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -390,23 +386,23 @@ where
|
|||
output_coroutine_ty,
|
||||
coroutine_return_ty,
|
||||
}| {
|
||||
let (projection_term, term) = if tcx
|
||||
let (projection_term, term) = if cx
|
||||
.is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::CallOnceFuture)
|
||||
{
|
||||
(
|
||||
ty::AliasTerm::new(
|
||||
tcx,
|
||||
cx,
|
||||
goal.predicate.def_id(),
|
||||
[goal.predicate.self_ty(), tupled_inputs_ty],
|
||||
),
|
||||
output_coroutine_ty.into(),
|
||||
)
|
||||
} else if tcx
|
||||
} else if cx
|
||||
.is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::CallRefFuture)
|
||||
{
|
||||
(
|
||||
ty::AliasTerm::new(
|
||||
tcx,
|
||||
cx,
|
||||
goal.predicate.def_id(),
|
||||
[
|
||||
I::GenericArg::from(goal.predicate.self_ty()),
|
||||
|
@ -416,13 +412,13 @@ where
|
|||
),
|
||||
output_coroutine_ty.into(),
|
||||
)
|
||||
} else if tcx.is_lang_item(
|
||||
} else if cx.is_lang_item(
|
||||
goal.predicate.def_id(),
|
||||
TraitSolverLangItem::AsyncFnOnceOutput,
|
||||
) {
|
||||
(
|
||||
ty::AliasTerm::new(
|
||||
tcx,
|
||||
cx,
|
||||
goal.predicate.def_id(),
|
||||
[
|
||||
I::GenericArg::from(goal.predicate.self_ty()),
|
||||
|
@ -440,7 +436,7 @@ where
|
|||
ty::ProjectionPredicate { projection_term, term }
|
||||
},
|
||||
)
|
||||
.upcast(tcx);
|
||||
.upcast(cx);
|
||||
|
||||
// A built-in `AsyncFn` impl only holds if the output is sized.
|
||||
// (FIXME: technically we only need to check this if the type is a fn ptr...)
|
||||
|
@ -449,9 +445,9 @@ where
|
|||
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
|
||||
goal,
|
||||
pred,
|
||||
[goal.with(tcx, output_is_sized_pred)]
|
||||
[goal.with(cx, output_is_sized_pred)]
|
||||
.into_iter()
|
||||
.chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred)))
|
||||
.chain(nested_preds.into_iter().map(|pred| goal.with(cx, pred)))
|
||||
.map(|goal| (GoalSource::ImplWhereBound, goal)),
|
||||
)
|
||||
}
|
||||
|
@ -514,8 +510,8 @@ where
|
|||
ecx: &mut EvalCtxt<'_, D>,
|
||||
goal: Goal<I, Self>,
|
||||
) -> Result<Candidate<I>, NoSolution> {
|
||||
let tcx = ecx.cx();
|
||||
let metadata_def_id = tcx.require_lang_item(TraitSolverLangItem::Metadata);
|
||||
let cx = ecx.cx();
|
||||
let metadata_def_id = cx.require_lang_item(TraitSolverLangItem::Metadata);
|
||||
assert_eq!(metadata_def_id, goal.predicate.def_id());
|
||||
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
|
||||
let metadata_ty = match goal.predicate.self_ty().kind() {
|
||||
|
@ -537,16 +533,16 @@ where
|
|||
| ty::CoroutineWitness(..)
|
||||
| ty::Never
|
||||
| ty::Foreign(..)
|
||||
| ty::Dynamic(_, _, ty::DynStar) => Ty::new_unit(tcx),
|
||||
| ty::Dynamic(_, _, ty::DynStar) => Ty::new_unit(cx),
|
||||
|
||||
ty::Error(e) => Ty::new_error(tcx, e),
|
||||
ty::Error(e) => Ty::new_error(cx, e),
|
||||
|
||||
ty::Str | ty::Slice(_) => Ty::new_usize(tcx),
|
||||
ty::Str | ty::Slice(_) => Ty::new_usize(cx),
|
||||
|
||||
ty::Dynamic(_, _, ty::Dyn) => {
|
||||
let dyn_metadata = tcx.require_lang_item(TraitSolverLangItem::DynMetadata);
|
||||
tcx.type_of(dyn_metadata)
|
||||
.instantiate(tcx, &[I::GenericArg::from(goal.predicate.self_ty())])
|
||||
let dyn_metadata = cx.require_lang_item(TraitSolverLangItem::DynMetadata);
|
||||
cx.type_of(dyn_metadata)
|
||||
.instantiate(cx, &[I::GenericArg::from(goal.predicate.self_ty())])
|
||||
}
|
||||
|
||||
ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => {
|
||||
|
@ -555,26 +551,26 @@ where
|
|||
// 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::new(
|
||||
tcx,
|
||||
tcx.require_lang_item(TraitSolverLangItem::Sized),
|
||||
cx,
|
||||
cx.require_lang_item(TraitSolverLangItem::Sized),
|
||||
[I::GenericArg::from(goal.predicate.self_ty())],
|
||||
);
|
||||
// FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`?
|
||||
ecx.add_goal(GoalSource::Misc, goal.with(tcx, sized_predicate));
|
||||
Ty::new_unit(tcx)
|
||||
ecx.add_goal(GoalSource::Misc, goal.with(cx, sized_predicate));
|
||||
Ty::new_unit(cx)
|
||||
}
|
||||
|
||||
ty::Adt(def, args) if def.is_struct() => match def.struct_tail_ty(tcx) {
|
||||
None => Ty::new_unit(tcx),
|
||||
ty::Adt(def, args) if def.is_struct() => match def.struct_tail_ty(cx) {
|
||||
None => Ty::new_unit(cx),
|
||||
Some(tail_ty) => {
|
||||
Ty::new_projection(tcx, metadata_def_id, [tail_ty.instantiate(tcx, args)])
|
||||
Ty::new_projection(cx, metadata_def_id, [tail_ty.instantiate(cx, args)])
|
||||
}
|
||||
},
|
||||
ty::Adt(_, _) => Ty::new_unit(tcx),
|
||||
ty::Adt(_, _) => Ty::new_unit(cx),
|
||||
|
||||
ty::Tuple(elements) => match elements.last() {
|
||||
None => Ty::new_unit(tcx),
|
||||
Some(tail_ty) => Ty::new_projection(tcx, metadata_def_id, [tail_ty]),
|
||||
None => Ty::new_unit(cx),
|
||||
Some(tail_ty) => Ty::new_projection(cx, metadata_def_id, [tail_ty]),
|
||||
},
|
||||
|
||||
ty::Infer(
|
||||
|
@ -601,8 +597,8 @@ where
|
|||
};
|
||||
|
||||
// Coroutines are not futures unless they come from `async` desugaring
|
||||
let tcx = ecx.cx();
|
||||
if !tcx.coroutine_is_async(def_id) {
|
||||
let cx = ecx.cx();
|
||||
if !cx.coroutine_is_async(def_id) {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
|
@ -616,7 +612,7 @@ where
|
|||
projection_term: ty::AliasTerm::new(ecx.cx(), goal.predicate.def_id(), [self_ty]),
|
||||
term,
|
||||
}
|
||||
.upcast(tcx),
|
||||
.upcast(cx),
|
||||
// Technically, we need to check that the future type is Sized,
|
||||
// but that's already proven by the coroutine being WF.
|
||||
[],
|
||||
|
@ -633,8 +629,8 @@ where
|
|||
};
|
||||
|
||||
// Coroutines are not Iterators unless they come from `gen` desugaring
|
||||
let tcx = ecx.cx();
|
||||
if !tcx.coroutine_is_gen(def_id) {
|
||||
let cx = ecx.cx();
|
||||
if !cx.coroutine_is_gen(def_id) {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
|
@ -648,7 +644,7 @@ where
|
|||
projection_term: ty::AliasTerm::new(ecx.cx(), goal.predicate.def_id(), [self_ty]),
|
||||
term,
|
||||
}
|
||||
.upcast(tcx),
|
||||
.upcast(cx),
|
||||
// Technically, we need to check that the iterator type is Sized,
|
||||
// but that's already proven by the generator being WF.
|
||||
[],
|
||||
|
@ -672,8 +668,8 @@ where
|
|||
};
|
||||
|
||||
// Coroutines are not AsyncIterators unless they come from `gen` desugaring
|
||||
let tcx = ecx.cx();
|
||||
if !tcx.coroutine_is_async_gen(def_id) {
|
||||
let cx = ecx.cx();
|
||||
if !cx.coroutine_is_async_gen(def_id) {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
|
@ -682,12 +678,12 @@ where
|
|||
// Take `AsyncIterator<Item = I>` and turn it into the corresponding
|
||||
// coroutine yield ty `Poll<Option<I>>`.
|
||||
let wrapped_expected_ty = Ty::new_adt(
|
||||
tcx,
|
||||
tcx.adt_def(tcx.require_lang_item(TraitSolverLangItem::Poll)),
|
||||
tcx.mk_args(&[Ty::new_adt(
|
||||
tcx,
|
||||
tcx.adt_def(tcx.require_lang_item(TraitSolverLangItem::Option)),
|
||||
tcx.mk_args(&[expected_ty.into()]),
|
||||
cx,
|
||||
cx.adt_def(cx.require_lang_item(TraitSolverLangItem::Poll)),
|
||||
cx.mk_args(&[Ty::new_adt(
|
||||
cx,
|
||||
cx.adt_def(cx.require_lang_item(TraitSolverLangItem::Option)),
|
||||
cx.mk_args(&[expected_ty.into()]),
|
||||
)
|
||||
.into()]),
|
||||
);
|
||||
|
@ -708,18 +704,17 @@ where
|
|||
};
|
||||
|
||||
// `async`-desugared coroutines do not implement the coroutine trait
|
||||
let tcx = ecx.cx();
|
||||
if !tcx.is_general_coroutine(def_id) {
|
||||
let cx = ecx.cx();
|
||||
if !cx.is_general_coroutine(def_id) {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
let coroutine = args.as_coroutine();
|
||||
|
||||
let term = if tcx
|
||||
.is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::CoroutineReturn)
|
||||
let term = if cx.is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::CoroutineReturn)
|
||||
{
|
||||
coroutine.return_ty().into()
|
||||
} else if tcx.is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::CoroutineYield) {
|
||||
} else if cx.is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::CoroutineYield) {
|
||||
coroutine.yield_ty().into()
|
||||
} else {
|
||||
panic!("unexpected associated item `{:?}` for `{self_ty:?}`", goal.predicate.def_id())
|
||||
|
@ -737,7 +732,7 @@ where
|
|||
),
|
||||
term,
|
||||
}
|
||||
.upcast(tcx),
|
||||
.upcast(cx),
|
||||
// Technically, we need to check that the coroutine type is Sized,
|
||||
// but that's already proven by the coroutine being WF.
|
||||
[],
|
||||
|
@ -884,29 +879,29 @@ where
|
|||
impl_trait_ref: rustc_type_ir::TraitRef<I>,
|
||||
target_container_def_id: I::DefId,
|
||||
) -> Result<I::GenericArgs, NoSolution> {
|
||||
let tcx = self.cx();
|
||||
let cx = self.cx();
|
||||
Ok(if target_container_def_id == impl_trait_ref.def_id {
|
||||
// Default value from the trait definition. No need to rebase.
|
||||
goal.predicate.alias.args
|
||||
} else if target_container_def_id == impl_def_id {
|
||||
// Same impl, no need to fully translate, just a rebase from
|
||||
// the trait is sufficient.
|
||||
goal.predicate.alias.args.rebase_onto(tcx, impl_trait_ref.def_id, impl_args)
|
||||
goal.predicate.alias.args.rebase_onto(cx, impl_trait_ref.def_id, impl_args)
|
||||
} else {
|
||||
let target_args = self.fresh_args_for_item(target_container_def_id);
|
||||
let target_trait_ref =
|
||||
tcx.impl_trait_ref(target_container_def_id).instantiate(tcx, target_args);
|
||||
cx.impl_trait_ref(target_container_def_id).instantiate(cx, target_args);
|
||||
// Relate source impl to target impl by equating trait refs.
|
||||
self.eq(goal.param_env, impl_trait_ref, target_trait_ref)?;
|
||||
// Also add predicates since they may be needed to constrain the
|
||||
// target impl's params.
|
||||
self.add_goals(
|
||||
GoalSource::Misc,
|
||||
tcx.predicates_of(target_container_def_id)
|
||||
.iter_instantiated(tcx, target_args)
|
||||
.map(|pred| goal.with(tcx, pred)),
|
||||
cx.predicates_of(target_container_def_id)
|
||||
.iter_instantiated(cx, target_args)
|
||||
.map(|pred| goal.with(cx, pred)),
|
||||
);
|
||||
goal.predicate.alias.args.rebase_onto(tcx, impl_trait_ref.def_id, target_args)
|
||||
goal.predicate.alias.args.rebase_onto(cx, impl_trait_ref.def_id, target_args)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ where
|
|||
&mut self,
|
||||
goal: Goal<I, ty::NormalizesTo<I>>,
|
||||
) -> QueryResult<I> {
|
||||
let tcx = self.cx();
|
||||
let cx = self.cx();
|
||||
let opaque_ty = goal.predicate.alias;
|
||||
let expected = goal.predicate.term.as_type().expect("no such thing as an opaque const");
|
||||
|
||||
|
@ -86,7 +86,7 @@ where
|
|||
}
|
||||
(Reveal::All, _) => {
|
||||
// FIXME: Add an assertion that opaque type storage is empty.
|
||||
let actual = tcx.type_of(opaque_ty.def_id).instantiate(tcx, opaque_ty.args);
|
||||
let actual = cx.type_of(opaque_ty.def_id).instantiate(cx, opaque_ty.args);
|
||||
self.eq(goal.param_env, expected, actual)?;
|
||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ where
|
|||
///
|
||||
/// FIXME: Interner argument is needed to constrain the `I` parameter.
|
||||
pub fn uses_unique_placeholders_ignoring_regions<I: Interner>(
|
||||
_interner: I,
|
||||
_cx: I,
|
||||
args: I::GenericArgs,
|
||||
) -> Result<(), NotUniqueParam<I>> {
|
||||
let mut seen = GrowableBitSet::default();
|
||||
|
|
|
@ -18,18 +18,18 @@ where
|
|||
&mut self,
|
||||
goal: Goal<I, ty::NormalizesTo<I>>,
|
||||
) -> QueryResult<I> {
|
||||
let tcx = self.cx();
|
||||
let cx = self.cx();
|
||||
let weak_ty = goal.predicate.alias;
|
||||
|
||||
// Check where clauses
|
||||
self.add_goals(
|
||||
GoalSource::Misc,
|
||||
tcx.predicates_of(weak_ty.def_id)
|
||||
.iter_instantiated(tcx, weak_ty.args)
|
||||
.map(|pred| goal.with(tcx, pred)),
|
||||
cx.predicates_of(weak_ty.def_id)
|
||||
.iter_instantiated(cx, weak_ty.args)
|
||||
.map(|pred| goal.with(cx, pred)),
|
||||
);
|
||||
|
||||
let actual = tcx.type_of(weak_ty.def_id).instantiate(tcx, weak_ty.args);
|
||||
let actual = cx.type_of(weak_ty.def_id).instantiate(cx, weak_ty.args);
|
||||
self.instantiate_normalizes_to_term(goal, actual.into());
|
||||
|
||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
|
|
|
@ -14,10 +14,10 @@ where
|
|||
&mut self,
|
||||
goal: Goal<I, ProjectionPredicate<I>>,
|
||||
) -> QueryResult<I> {
|
||||
let tcx = self.cx();
|
||||
let projection_term = goal.predicate.projection_term.to_term(tcx);
|
||||
let cx = self.cx();
|
||||
let projection_term = goal.predicate.projection_term.to_term(cx);
|
||||
let goal = goal.with(
|
||||
tcx,
|
||||
cx,
|
||||
ty::PredicateKind::AliasRelate(
|
||||
projection_term,
|
||||
goal.predicate.term,
|
||||
|
|
|
@ -164,7 +164,7 @@ impl<I: Interner> SearchGraph<I> {
|
|||
/// the remaining depth of all nested goals to prevent hangs
|
||||
/// in case there is exponential blowup.
|
||||
fn allowed_depth_for_nested(
|
||||
tcx: I,
|
||||
cx: I,
|
||||
stack: &IndexVec<StackDepth, StackEntry<I>>,
|
||||
) -> Option<SolverLimit> {
|
||||
if let Some(last) = stack.raw.last() {
|
||||
|
@ -178,18 +178,18 @@ impl<I: Interner> SearchGraph<I> {
|
|||
SolverLimit(last.available_depth.0 - 1)
|
||||
})
|
||||
} else {
|
||||
Some(SolverLimit(tcx.recursion_limit()))
|
||||
Some(SolverLimit(cx.recursion_limit()))
|
||||
}
|
||||
}
|
||||
|
||||
fn stack_coinductive_from(
|
||||
tcx: I,
|
||||
cx: I,
|
||||
stack: &IndexVec<StackDepth, StackEntry<I>>,
|
||||
head: StackDepth,
|
||||
) -> bool {
|
||||
stack.raw[head.index()..]
|
||||
.iter()
|
||||
.all(|entry| entry.input.value.goal.predicate.is_coinductive(tcx))
|
||||
.all(|entry| entry.input.value.goal.predicate.is_coinductive(cx))
|
||||
}
|
||||
|
||||
// When encountering a solver cycle, the result of the current goal
|
||||
|
@ -247,8 +247,8 @@ impl<I: Interner> SearchGraph<I> {
|
|||
/// so we use a separate cache. Alternatively we could use
|
||||
/// a single cache and share it between coherence and ordinary
|
||||
/// trait solving.
|
||||
pub(super) fn global_cache(&self, tcx: I) -> I::EvaluationCache {
|
||||
tcx.evaluation_cache(self.mode)
|
||||
pub(super) fn global_cache(&self, cx: I) -> I::EvaluationCache {
|
||||
cx.evaluation_cache(self.mode)
|
||||
}
|
||||
|
||||
/// Probably the most involved method of the whole solver.
|
||||
|
@ -257,24 +257,24 @@ impl<I: Interner> SearchGraph<I> {
|
|||
/// handles caching, overflow, and coinductive cycles.
|
||||
pub(super) fn with_new_goal<D: SolverDelegate<Interner = I>>(
|
||||
&mut self,
|
||||
tcx: I,
|
||||
cx: I,
|
||||
input: CanonicalInput<I>,
|
||||
inspect: &mut ProofTreeBuilder<D>,
|
||||
mut prove_goal: impl FnMut(&mut Self, &mut ProofTreeBuilder<D>) -> QueryResult<I>,
|
||||
) -> QueryResult<I> {
|
||||
self.check_invariants();
|
||||
// Check for overflow.
|
||||
let Some(available_depth) = Self::allowed_depth_for_nested(tcx, &self.stack) else {
|
||||
let Some(available_depth) = Self::allowed_depth_for_nested(cx, &self.stack) else {
|
||||
if let Some(last) = self.stack.raw.last_mut() {
|
||||
last.encountered_overflow = true;
|
||||
}
|
||||
|
||||
inspect
|
||||
.canonical_goal_evaluation_kind(inspect::WipCanonicalGoalEvaluationKind::Overflow);
|
||||
return Self::response_no_constraints(tcx, input, Certainty::overflow(true));
|
||||
return Self::response_no_constraints(cx, input, Certainty::overflow(true));
|
||||
};
|
||||
|
||||
if let Some(result) = self.lookup_global_cache(tcx, input, available_depth, inspect) {
|
||||
if let Some(result) = self.lookup_global_cache(cx, input, available_depth, inspect) {
|
||||
debug!("global cache hit");
|
||||
return result;
|
||||
}
|
||||
|
@ -287,12 +287,12 @@ impl<I: Interner> SearchGraph<I> {
|
|||
if let Some(entry) = cache_entry
|
||||
.with_coinductive_stack
|
||||
.as_ref()
|
||||
.filter(|p| Self::stack_coinductive_from(tcx, &self.stack, p.head))
|
||||
.filter(|p| Self::stack_coinductive_from(cx, &self.stack, p.head))
|
||||
.or_else(|| {
|
||||
cache_entry
|
||||
.with_inductive_stack
|
||||
.as_ref()
|
||||
.filter(|p| !Self::stack_coinductive_from(tcx, &self.stack, p.head))
|
||||
.filter(|p| !Self::stack_coinductive_from(cx, &self.stack, p.head))
|
||||
})
|
||||
{
|
||||
debug!("provisional cache hit");
|
||||
|
@ -315,7 +315,7 @@ impl<I: Interner> SearchGraph<I> {
|
|||
inspect.canonical_goal_evaluation_kind(
|
||||
inspect::WipCanonicalGoalEvaluationKind::CycleInStack,
|
||||
);
|
||||
let is_coinductive_cycle = Self::stack_coinductive_from(tcx, &self.stack, stack_depth);
|
||||
let is_coinductive_cycle = Self::stack_coinductive_from(cx, &self.stack, stack_depth);
|
||||
let usage_kind = if is_coinductive_cycle {
|
||||
HasBeenUsed::COINDUCTIVE_CYCLE
|
||||
} else {
|
||||
|
@ -328,9 +328,9 @@ impl<I: Interner> SearchGraph<I> {
|
|||
return if let Some(result) = self.stack[stack_depth].provisional_result {
|
||||
result
|
||||
} else if is_coinductive_cycle {
|
||||
Self::response_no_constraints(tcx, input, Certainty::Yes)
|
||||
Self::response_no_constraints(cx, input, Certainty::Yes)
|
||||
} else {
|
||||
Self::response_no_constraints(tcx, input, Certainty::overflow(false))
|
||||
Self::response_no_constraints(cx, input, Certainty::overflow(false))
|
||||
};
|
||||
} else {
|
||||
// No entry, we push this goal on the stack and try to prove it.
|
||||
|
@ -355,9 +355,9 @@ impl<I: Interner> SearchGraph<I> {
|
|||
// not tracked by the cache key and from outside of this anon task, it
|
||||
// must not be added to the global cache. Notably, this is the case for
|
||||
// trait solver cycles participants.
|
||||
let ((final_entry, result), dep_node) = tcx.with_cached_task(|| {
|
||||
let ((final_entry, result), dep_node) = cx.with_cached_task(|| {
|
||||
for _ in 0..FIXPOINT_STEP_LIMIT {
|
||||
match self.fixpoint_step_in_task(tcx, input, inspect, &mut prove_goal) {
|
||||
match self.fixpoint_step_in_task(cx, input, inspect, &mut prove_goal) {
|
||||
StepResult::Done(final_entry, result) => return (final_entry, result),
|
||||
StepResult::HasChanged => debug!("fixpoint changed provisional results"),
|
||||
}
|
||||
|
@ -366,17 +366,17 @@ impl<I: Interner> SearchGraph<I> {
|
|||
debug!("canonical cycle overflow");
|
||||
let current_entry = self.pop_stack();
|
||||
debug_assert!(current_entry.has_been_used.is_empty());
|
||||
let result = Self::response_no_constraints(tcx, input, Certainty::overflow(false));
|
||||
let result = Self::response_no_constraints(cx, input, Certainty::overflow(false));
|
||||
(current_entry, result)
|
||||
});
|
||||
|
||||
let proof_tree = inspect.finalize_canonical_goal_evaluation(tcx);
|
||||
let proof_tree = inspect.finalize_canonical_goal_evaluation(cx);
|
||||
|
||||
// We're now done with this goal. In case this goal is involved in a larger cycle
|
||||
// do not remove it from the provisional cache and update its provisional result.
|
||||
// We only add the root of cycles to the global cache.
|
||||
if let Some(head) = final_entry.non_root_cycle_participant {
|
||||
let coinductive_stack = Self::stack_coinductive_from(tcx, &self.stack, head);
|
||||
let coinductive_stack = Self::stack_coinductive_from(cx, &self.stack, head);
|
||||
|
||||
let entry = self.provisional_cache.get_mut(&input).unwrap();
|
||||
entry.stack_depth = None;
|
||||
|
@ -396,8 +396,8 @@ impl<I: Interner> SearchGraph<I> {
|
|||
// participant is on the stack. This is necessary to prevent unstable
|
||||
// results. See the comment of `StackEntry::cycle_participants` for
|
||||
// more details.
|
||||
self.global_cache(tcx).insert(
|
||||
tcx,
|
||||
self.global_cache(cx).insert(
|
||||
cx,
|
||||
input,
|
||||
proof_tree,
|
||||
reached_depth,
|
||||
|
@ -418,15 +418,15 @@ impl<I: Interner> SearchGraph<I> {
|
|||
/// this goal.
|
||||
fn lookup_global_cache<D: SolverDelegate<Interner = I>>(
|
||||
&mut self,
|
||||
tcx: I,
|
||||
cx: I,
|
||||
input: CanonicalInput<I>,
|
||||
available_depth: SolverLimit,
|
||||
inspect: &mut ProofTreeBuilder<D>,
|
||||
) -> Option<QueryResult<I>> {
|
||||
let CacheData { result, proof_tree, additional_depth, encountered_overflow } = self
|
||||
.global_cache(tcx)
|
||||
.global_cache(cx)
|
||||
// FIXME: Awkward `Limit -> usize -> Limit`.
|
||||
.get(tcx, input, self.stack.iter().map(|e| e.input), available_depth.0)?;
|
||||
.get(cx, input, self.stack.iter().map(|e| e.input), available_depth.0)?;
|
||||
|
||||
// If we're building a proof tree and the current cache entry does not
|
||||
// contain a proof tree, we do not use the entry but instead recompute
|
||||
|
@ -467,7 +467,7 @@ impl<I: Interner> SearchGraph<I> {
|
|||
/// point we are done.
|
||||
fn fixpoint_step_in_task<D, F>(
|
||||
&mut self,
|
||||
tcx: I,
|
||||
cx: I,
|
||||
input: CanonicalInput<I>,
|
||||
inspect: &mut ProofTreeBuilder<D>,
|
||||
prove_goal: &mut F,
|
||||
|
@ -506,9 +506,9 @@ impl<I: Interner> SearchGraph<I> {
|
|||
let reached_fixpoint = if let Some(r) = stack_entry.provisional_result {
|
||||
r == result
|
||||
} else if stack_entry.has_been_used == HasBeenUsed::COINDUCTIVE_CYCLE {
|
||||
Self::response_no_constraints(tcx, input, Certainty::Yes) == result
|
||||
Self::response_no_constraints(cx, input, Certainty::Yes) == result
|
||||
} else if stack_entry.has_been_used == HasBeenUsed::INDUCTIVE_CYCLE {
|
||||
Self::response_no_constraints(tcx, input, Certainty::overflow(false)) == result
|
||||
Self::response_no_constraints(cx, input, Certainty::overflow(false)) == result
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
@ -528,11 +528,11 @@ impl<I: Interner> SearchGraph<I> {
|
|||
}
|
||||
|
||||
fn response_no_constraints(
|
||||
tcx: I,
|
||||
cx: I,
|
||||
goal: CanonicalInput<I>,
|
||||
certainty: Certainty,
|
||||
) -> QueryResult<I> {
|
||||
Ok(super::response_no_constraints_raw(tcx, goal.max_universe, goal.variables, certainty))
|
||||
Ok(super::response_no_constraints_raw(cx, goal.max_universe, goal.variables, certainty))
|
||||
}
|
||||
|
||||
#[allow(rustc::potential_query_instability)]
|
||||
|
|
|
@ -30,8 +30,8 @@ where
|
|||
self.trait_ref
|
||||
}
|
||||
|
||||
fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> Self {
|
||||
self.with_self_ty(tcx, self_ty)
|
||||
fn with_self_ty(self, cx: I, self_ty: I::Ty) -> Self {
|
||||
self.with_self_ty(cx, self_ty)
|
||||
}
|
||||
|
||||
fn trait_def_id(self, _: I) -> I::DefId {
|
||||
|
@ -43,18 +43,17 @@ where
|
|||
goal: Goal<I, TraitPredicate<I>>,
|
||||
impl_def_id: I::DefId,
|
||||
) -> Result<Candidate<I>, NoSolution> {
|
||||
let tcx = ecx.cx();
|
||||
let cx = ecx.cx();
|
||||
|
||||
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id);
|
||||
if !tcx
|
||||
.args_may_unify_deep(goal.predicate.trait_ref.args, impl_trait_ref.skip_binder().args)
|
||||
let impl_trait_ref = cx.impl_trait_ref(impl_def_id);
|
||||
if !cx.args_may_unify_deep(goal.predicate.trait_ref.args, impl_trait_ref.skip_binder().args)
|
||||
{
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
// An upper bound of the certainty of this goal, used to lower the certainty
|
||||
// of reservation impl to ambiguous during coherence.
|
||||
let impl_polarity = tcx.impl_polarity(impl_def_id);
|
||||
let impl_polarity = cx.impl_polarity(impl_def_id);
|
||||
let maximal_certainty = match (impl_polarity, goal.predicate.polarity) {
|
||||
// In intercrate mode, this is ambiguous. But outside of intercrate,
|
||||
// it's not a real impl.
|
||||
|
@ -77,13 +76,13 @@ where
|
|||
ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
|
||||
let impl_args = ecx.fresh_args_for_item(impl_def_id);
|
||||
ecx.record_impl_args(impl_args);
|
||||
let impl_trait_ref = impl_trait_ref.instantiate(tcx, impl_args);
|
||||
let impl_trait_ref = impl_trait_ref.instantiate(cx, impl_args);
|
||||
|
||||
ecx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?;
|
||||
let where_clause_bounds = tcx
|
||||
let where_clause_bounds = cx
|
||||
.predicates_of(impl_def_id)
|
||||
.iter_instantiated(tcx, impl_args)
|
||||
.map(|pred| goal.with(tcx, pred));
|
||||
.iter_instantiated(cx, impl_args)
|
||||
.map(|pred| goal.with(cx, pred));
|
||||
ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds);
|
||||
|
||||
ecx.evaluate_added_goals_and_make_canonical_response(maximal_certainty)
|
||||
|
@ -181,13 +180,13 @@ where
|
|||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
let tcx = ecx.cx();
|
||||
let cx = ecx.cx();
|
||||
|
||||
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
|
||||
let nested_obligations = tcx
|
||||
let nested_obligations = cx
|
||||
.predicates_of(goal.predicate.def_id())
|
||||
.iter_instantiated(tcx, goal.predicate.trait_ref.args)
|
||||
.map(|p| goal.with(tcx, p));
|
||||
.iter_instantiated(cx, goal.predicate.trait_ref.args)
|
||||
.map(|p| goal.with(cx, p));
|
||||
// FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`?
|
||||
ecx.add_goals(GoalSource::Misc, nested_obligations);
|
||||
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
|
@ -232,13 +231,13 @@ where
|
|||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
let tcx = ecx.cx();
|
||||
let cx = ecx.cx();
|
||||
// But if there are inference variables, we have to wait until it's resolved.
|
||||
if (goal.param_env, goal.predicate.self_ty()).has_non_region_infer() {
|
||||
return ecx.forced_ambiguity(MaybeCause::Ambiguity);
|
||||
}
|
||||
|
||||
if tcx.layout_is_pointer_like(goal.param_env, goal.predicate.self_ty()) {
|
||||
if cx.layout_is_pointer_like(goal.param_env, goal.predicate.self_ty()) {
|
||||
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
|
||||
.enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
|
||||
} else {
|
||||
|
@ -286,10 +285,10 @@ where
|
|||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
let tcx = ecx.cx();
|
||||
let cx = ecx.cx();
|
||||
let tupled_inputs_and_output =
|
||||
match structural_traits::extract_tupled_inputs_and_output_from_callable(
|
||||
tcx,
|
||||
cx,
|
||||
goal.predicate.self_ty(),
|
||||
goal_kind,
|
||||
)? {
|
||||
|
@ -299,14 +298,14 @@ where
|
|||
}
|
||||
};
|
||||
let output_is_sized_pred = tupled_inputs_and_output.map_bound(|(_, output)| {
|
||||
ty::TraitRef::new(tcx, tcx.require_lang_item(TraitSolverLangItem::Sized), [output])
|
||||
ty::TraitRef::new(cx, cx.require_lang_item(TraitSolverLangItem::Sized), [output])
|
||||
});
|
||||
|
||||
let pred = tupled_inputs_and_output
|
||||
.map_bound(|(inputs, _)| {
|
||||
ty::TraitRef::new(tcx, goal.predicate.def_id(), [goal.predicate.self_ty(), inputs])
|
||||
ty::TraitRef::new(cx, goal.predicate.def_id(), [goal.predicate.self_ty(), inputs])
|
||||
})
|
||||
.upcast(tcx);
|
||||
.upcast(cx);
|
||||
// A built-in `Fn` impl only holds if the output is sized.
|
||||
// (FIXME: technically we only need to check this if the type is a fn ptr...)
|
||||
Self::probe_and_consider_implied_clause(
|
||||
|
@ -314,7 +313,7 @@ where
|
|||
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
|
||||
goal,
|
||||
pred,
|
||||
[(GoalSource::ImplWhereBound, goal.with(tcx, output_is_sized_pred))],
|
||||
[(GoalSource::ImplWhereBound, goal.with(cx, output_is_sized_pred))],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -327,20 +326,20 @@ where
|
|||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
let tcx = ecx.cx();
|
||||
let cx = ecx.cx();
|
||||
let (tupled_inputs_and_output_and_coroutine, nested_preds) =
|
||||
structural_traits::extract_tupled_inputs_and_output_from_async_callable(
|
||||
tcx,
|
||||
cx,
|
||||
goal.predicate.self_ty(),
|
||||
goal_kind,
|
||||
// This region doesn't matter because we're throwing away the coroutine type
|
||||
Region::new_static(tcx),
|
||||
Region::new_static(cx),
|
||||
)?;
|
||||
let output_is_sized_pred = tupled_inputs_and_output_and_coroutine.map_bound(
|
||||
|AsyncCallableRelevantTypes { output_coroutine_ty, .. }| {
|
||||
ty::TraitRef::new(
|
||||
tcx,
|
||||
tcx.require_lang_item(TraitSolverLangItem::Sized),
|
||||
cx,
|
||||
cx.require_lang_item(TraitSolverLangItem::Sized),
|
||||
[output_coroutine_ty],
|
||||
)
|
||||
},
|
||||
|
@ -349,12 +348,12 @@ where
|
|||
let pred = tupled_inputs_and_output_and_coroutine
|
||||
.map_bound(|AsyncCallableRelevantTypes { tupled_inputs_ty, .. }| {
|
||||
ty::TraitRef::new(
|
||||
tcx,
|
||||
cx,
|
||||
goal.predicate.def_id(),
|
||||
[goal.predicate.self_ty(), tupled_inputs_ty],
|
||||
)
|
||||
})
|
||||
.upcast(tcx);
|
||||
.upcast(cx);
|
||||
// A built-in `AsyncFn` impl only holds if the output is sized.
|
||||
// (FIXME: technically we only need to check this if the type is a fn ptr...)
|
||||
Self::probe_and_consider_implied_clause(
|
||||
|
@ -362,9 +361,9 @@ where
|
|||
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
|
||||
goal,
|
||||
pred,
|
||||
[goal.with(tcx, output_is_sized_pred)]
|
||||
[goal.with(cx, output_is_sized_pred)]
|
||||
.into_iter()
|
||||
.chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred)))
|
||||
.chain(nested_preds.into_iter().map(|pred| goal.with(cx, pred)))
|
||||
.map(|goal| (GoalSource::ImplWhereBound, goal)),
|
||||
)
|
||||
}
|
||||
|
@ -437,8 +436,8 @@ where
|
|||
};
|
||||
|
||||
// Coroutines are not futures unless they come from `async` desugaring
|
||||
let tcx = ecx.cx();
|
||||
if !tcx.coroutine_is_async(def_id) {
|
||||
let cx = ecx.cx();
|
||||
if !cx.coroutine_is_async(def_id) {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
|
@ -463,8 +462,8 @@ where
|
|||
};
|
||||
|
||||
// Coroutines are not iterators unless they come from `gen` desugaring
|
||||
let tcx = ecx.cx();
|
||||
if !tcx.coroutine_is_gen(def_id) {
|
||||
let cx = ecx.cx();
|
||||
if !cx.coroutine_is_gen(def_id) {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
|
@ -489,8 +488,8 @@ where
|
|||
};
|
||||
|
||||
// Coroutines are not iterators unless they come from `gen` desugaring
|
||||
let tcx = ecx.cx();
|
||||
if !tcx.coroutine_is_gen(def_id) {
|
||||
let cx = ecx.cx();
|
||||
if !cx.coroutine_is_gen(def_id) {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
|
@ -513,8 +512,8 @@ where
|
|||
};
|
||||
|
||||
// Coroutines are not iterators unless they come from `gen` desugaring
|
||||
let tcx = ecx.cx();
|
||||
if !tcx.coroutine_is_async_gen(def_id) {
|
||||
let cx = ecx.cx();
|
||||
if !cx.coroutine_is_async_gen(def_id) {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
|
@ -540,8 +539,8 @@ where
|
|||
};
|
||||
|
||||
// `async`-desugared coroutines do not implement the coroutine trait
|
||||
let tcx = ecx.cx();
|
||||
if !tcx.is_general_coroutine(def_id) {
|
||||
let cx = ecx.cx();
|
||||
if !cx.is_general_coroutine(def_id) {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
|
@ -550,8 +549,8 @@ where
|
|||
ecx,
|
||||
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
|
||||
goal,
|
||||
ty::TraitRef::new(tcx, goal.predicate.def_id(), [self_ty, coroutine.resume_ty()])
|
||||
.upcast(tcx),
|
||||
ty::TraitRef::new(cx, goal.predicate.def_id(), [self_ty, coroutine.resume_ty()])
|
||||
.upcast(cx),
|
||||
// Technically, we need to check that the coroutine types are Sized,
|
||||
// but that's already proven by the coroutine being WF.
|
||||
[],
|
||||
|
@ -727,7 +726,7 @@ where
|
|||
b_data: I::BoundExistentialPredicates,
|
||||
b_region: I::Region,
|
||||
) -> Vec<Candidate<I>> {
|
||||
let tcx = self.cx();
|
||||
let cx = self.cx();
|
||||
let Goal { predicate: (a_ty, _b_ty), .. } = goal;
|
||||
|
||||
let mut responses = vec![];
|
||||
|
@ -745,7 +744,7 @@ where
|
|||
));
|
||||
} else if let Some(a_principal) = a_data.principal() {
|
||||
for new_a_principal in
|
||||
D::elaborate_supertraits(self.cx(), a_principal.with_self_ty(tcx, a_ty)).skip(1)
|
||||
D::elaborate_supertraits(self.cx(), a_principal.with_self_ty(cx, a_ty)).skip(1)
|
||||
{
|
||||
responses.extend(self.consider_builtin_upcast_to_principal(
|
||||
goal,
|
||||
|
@ -755,7 +754,7 @@ where
|
|||
b_data,
|
||||
b_region,
|
||||
Some(new_a_principal.map_bound(|trait_ref| {
|
||||
ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)
|
||||
ty::ExistentialTraitRef::erase_self_ty(cx, trait_ref)
|
||||
})),
|
||||
));
|
||||
}
|
||||
|
@ -770,11 +769,11 @@ where
|
|||
b_data: I::BoundExistentialPredicates,
|
||||
b_region: I::Region,
|
||||
) -> Result<Candidate<I>, NoSolution> {
|
||||
let tcx = self.cx();
|
||||
let cx = self.cx();
|
||||
let Goal { predicate: (a_ty, _), .. } = goal;
|
||||
|
||||
// Can only unsize to an object-safe trait.
|
||||
if b_data.principal_def_id().is_some_and(|def_id| !tcx.trait_is_object_safe(def_id)) {
|
||||
if b_data.principal_def_id().is_some_and(|def_id| !cx.trait_is_object_safe(def_id)) {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
|
@ -783,24 +782,20 @@ where
|
|||
// (i.e. the principal, all of the associated types match, and any auto traits)
|
||||
ecx.add_goals(
|
||||
GoalSource::ImplWhereBound,
|
||||
b_data.iter().map(|pred| goal.with(tcx, pred.with_self_ty(tcx, a_ty))),
|
||||
b_data.iter().map(|pred| goal.with(cx, pred.with_self_ty(cx, a_ty))),
|
||||
);
|
||||
|
||||
// The type must be `Sized` to be unsized.
|
||||
ecx.add_goal(
|
||||
GoalSource::ImplWhereBound,
|
||||
goal.with(
|
||||
tcx,
|
||||
ty::TraitRef::new(
|
||||
tcx,
|
||||
tcx.require_lang_item(TraitSolverLangItem::Sized),
|
||||
[a_ty],
|
||||
),
|
||||
cx,
|
||||
ty::TraitRef::new(cx, cx.require_lang_item(TraitSolverLangItem::Sized), [a_ty]),
|
||||
),
|
||||
);
|
||||
|
||||
// The type must outlive the lifetime of the `dyn` we're unsizing into.
|
||||
ecx.add_goal(GoalSource::Misc, goal.with(tcx, ty::OutlivesPredicate(a_ty, b_region)));
|
||||
ecx.add_goal(GoalSource::Misc, goal.with(cx, ty::OutlivesPredicate(a_ty, b_region)));
|
||||
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
})
|
||||
}
|
||||
|
@ -941,28 +936,28 @@ where
|
|||
a_args: I::GenericArgs,
|
||||
b_args: I::GenericArgs,
|
||||
) -> Result<Candidate<I>, NoSolution> {
|
||||
let tcx = self.cx();
|
||||
let cx = self.cx();
|
||||
let Goal { predicate: (_a_ty, b_ty), .. } = goal;
|
||||
|
||||
let unsizing_params = tcx.unsizing_params_for_adt(def.def_id());
|
||||
let unsizing_params = cx.unsizing_params_for_adt(def.def_id());
|
||||
// We must be unsizing some type parameters. This also implies
|
||||
// that the struct has a tail field.
|
||||
if unsizing_params.is_empty() {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
let tail_field_ty = def.struct_tail_ty(tcx).unwrap();
|
||||
let tail_field_ty = def.struct_tail_ty(cx).unwrap();
|
||||
|
||||
let a_tail_ty = tail_field_ty.instantiate(tcx, a_args);
|
||||
let b_tail_ty = tail_field_ty.instantiate(tcx, b_args);
|
||||
let a_tail_ty = tail_field_ty.instantiate(cx, a_args);
|
||||
let b_tail_ty = tail_field_ty.instantiate(cx, b_args);
|
||||
|
||||
// Instantiate just the unsizing params from B into A. The type after
|
||||
// this instantiation must be equal to B. This is so we don't unsize
|
||||
// unrelated type parameters.
|
||||
let new_a_args = tcx.mk_args_from_iter(a_args.iter().enumerate().map(|(i, a)| {
|
||||
let new_a_args = cx.mk_args_from_iter(a_args.iter().enumerate().map(|(i, a)| {
|
||||
if unsizing_params.contains(i as u32) { b_args.get(i).unwrap() } else { a }
|
||||
}));
|
||||
let unsized_a_ty = Ty::new_adt(tcx, def, new_a_args);
|
||||
let unsized_a_ty = Ty::new_adt(cx, def, new_a_args);
|
||||
|
||||
// Finally, we require that `TailA: Unsize<TailB>` for the tail field
|
||||
// types.
|
||||
|
@ -970,10 +965,10 @@ where
|
|||
self.add_goal(
|
||||
GoalSource::ImplWhereBound,
|
||||
goal.with(
|
||||
tcx,
|
||||
cx,
|
||||
ty::TraitRef::new(
|
||||
tcx,
|
||||
tcx.require_lang_item(TraitSolverLangItem::Unsize),
|
||||
cx,
|
||||
cx.require_lang_item(TraitSolverLangItem::Unsize),
|
||||
[a_tail_ty, b_tail_ty],
|
||||
),
|
||||
),
|
||||
|
@ -998,25 +993,24 @@ where
|
|||
a_tys: I::Tys,
|
||||
b_tys: I::Tys,
|
||||
) -> Result<Candidate<I>, NoSolution> {
|
||||
let tcx = self.cx();
|
||||
let cx = self.cx();
|
||||
let Goal { predicate: (_a_ty, b_ty), .. } = goal;
|
||||
|
||||
let (&a_last_ty, a_rest_tys) = a_tys.split_last().unwrap();
|
||||
let b_last_ty = b_tys.last().unwrap();
|
||||
|
||||
// Instantiate just the tail field of B., and require that they're equal.
|
||||
let unsized_a_ty =
|
||||
Ty::new_tup_from_iter(tcx, a_rest_tys.iter().copied().chain([b_last_ty]));
|
||||
let unsized_a_ty = Ty::new_tup_from_iter(cx, a_rest_tys.iter().copied().chain([b_last_ty]));
|
||||
self.eq(goal.param_env, unsized_a_ty, b_ty)?;
|
||||
|
||||
// Similar to ADTs, require that we can unsize the tail.
|
||||
self.add_goal(
|
||||
GoalSource::ImplWhereBound,
|
||||
goal.with(
|
||||
tcx,
|
||||
cx,
|
||||
ty::TraitRef::new(
|
||||
tcx,
|
||||
tcx.require_lang_item(TraitSolverLangItem::Unsize),
|
||||
cx,
|
||||
cx.require_lang_item(TraitSolverLangItem::Unsize),
|
||||
[a_last_ty, b_last_ty],
|
||||
),
|
||||
),
|
||||
|
|
|
@ -608,7 +608,7 @@ impl<'a> Parser<'a> {
|
|||
self.dcx().emit_err(FnPointerCannotBeAsync { span: whole_span, qualifier: span });
|
||||
}
|
||||
// FIXME(gen_blocks): emit a similar error for `gen fn()`
|
||||
let decl_span = span_start.to(self.token.span);
|
||||
let decl_span = span_start.to(self.prev_token.span);
|
||||
Ok(TyKind::BareFn(P(BareFnTy { ext, safety, generic_params: params, decl, decl_span })))
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
|
|||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::Node;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
use rustc_middle::middle::privacy::{self, Level};
|
||||
use rustc_middle::mir::interpret::{ConstAllocation, ErrorHandled, GlobalAlloc};
|
||||
use rustc_middle::query::Providers;
|
||||
|
@ -178,15 +178,7 @@ impl<'tcx> ReachableContext<'tcx> {
|
|||
if !self.any_library {
|
||||
// If we are building an executable, only explicitly extern
|
||||
// types need to be exported.
|
||||
let codegen_attrs = if self.tcx.def_kind(search_item).has_codegen_attrs() {
|
||||
self.tcx.codegen_fn_attrs(search_item)
|
||||
} else {
|
||||
CodegenFnAttrs::EMPTY
|
||||
};
|
||||
let is_extern = codegen_attrs.contains_extern_indicator();
|
||||
let std_internal =
|
||||
codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);
|
||||
if is_extern || std_internal {
|
||||
if has_custom_linkage(self.tcx, search_item) {
|
||||
self.reachable_symbols.insert(search_item);
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -99,7 +99,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> {
|
|||
// is the maximum value among visibilities of bindings corresponding to that def id.
|
||||
for (binding, eff_vis) in visitor.import_effective_visibilities.iter() {
|
||||
let NameBindingKind::Import { import, .. } = binding.kind else { unreachable!() };
|
||||
if !binding.is_ambiguity() {
|
||||
if !binding.is_ambiguity_recursive() {
|
||||
if let Some(node_id) = import.id() {
|
||||
r.effective_visibilities.update_eff_vis(r.local_def_id(node_id), eff_vis, r.tcx)
|
||||
}
|
||||
|
|
|
@ -325,8 +325,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
}
|
||||
match (old_binding.is_glob_import(), binding.is_glob_import()) {
|
||||
(true, true) => {
|
||||
// FIXME: remove `!binding.is_ambiguity()` after delete the warning ambiguity.
|
||||
if !binding.is_ambiguity()
|
||||
// FIXME: remove `!binding.is_ambiguity_recursive()` after delete the warning ambiguity.
|
||||
if !binding.is_ambiguity_recursive()
|
||||
&& let NameBindingKind::Import { import: old_import, .. } =
|
||||
old_binding.kind
|
||||
&& let NameBindingKind::Import { import, .. } = binding.kind
|
||||
|
@ -337,21 +337,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
// imported from the same glob-import statement.
|
||||
resolution.binding = Some(binding);
|
||||
} else if res != old_binding.res() {
|
||||
let binding = if warn_ambiguity {
|
||||
this.warn_ambiguity(AmbiguityKind::GlobVsGlob, old_binding, binding)
|
||||
} else {
|
||||
this.ambiguity(AmbiguityKind::GlobVsGlob, old_binding, binding)
|
||||
};
|
||||
resolution.binding = Some(binding);
|
||||
resolution.binding = Some(this.new_ambiguity_binding(
|
||||
AmbiguityKind::GlobVsGlob,
|
||||
old_binding,
|
||||
binding,
|
||||
warn_ambiguity,
|
||||
));
|
||||
} else if !old_binding.vis.is_at_least(binding.vis, this.tcx) {
|
||||
// We are glob-importing the same item but with greater visibility.
|
||||
resolution.binding = Some(binding);
|
||||
} else if binding.is_ambiguity() {
|
||||
resolution.binding =
|
||||
Some(self.arenas.alloc_name_binding(NameBindingData {
|
||||
warn_ambiguity: true,
|
||||
..(*binding).clone()
|
||||
}));
|
||||
} else if binding.is_ambiguity_recursive() {
|
||||
resolution.binding = Some(this.new_warn_ambiguity_binding(binding));
|
||||
}
|
||||
}
|
||||
(old_glob @ true, false) | (old_glob @ false, true) => {
|
||||
|
@ -361,24 +357,26 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
&& nonglob_binding.expansion != LocalExpnId::ROOT
|
||||
&& glob_binding.res() != nonglob_binding.res()
|
||||
{
|
||||
resolution.binding = Some(this.ambiguity(
|
||||
resolution.binding = Some(this.new_ambiguity_binding(
|
||||
AmbiguityKind::GlobVsExpanded,
|
||||
nonglob_binding,
|
||||
glob_binding,
|
||||
false,
|
||||
));
|
||||
} else {
|
||||
resolution.binding = Some(nonglob_binding);
|
||||
}
|
||||
|
||||
if let Some(old_binding) = resolution.shadowed_glob {
|
||||
assert!(old_binding.is_glob_import());
|
||||
if glob_binding.res() != old_binding.res() {
|
||||
resolution.shadowed_glob = Some(this.ambiguity(
|
||||
if let Some(old_shadowed_glob) = resolution.shadowed_glob {
|
||||
assert!(old_shadowed_glob.is_glob_import());
|
||||
if glob_binding.res() != old_shadowed_glob.res() {
|
||||
resolution.shadowed_glob = Some(this.new_ambiguity_binding(
|
||||
AmbiguityKind::GlobVsGlob,
|
||||
old_binding,
|
||||
old_shadowed_glob,
|
||||
glob_binding,
|
||||
false,
|
||||
));
|
||||
} else if !old_binding.vis.is_at_least(binding.vis, this.tcx) {
|
||||
} else if !old_shadowed_glob.vis.is_at_least(binding.vis, this.tcx) {
|
||||
resolution.shadowed_glob = Some(glob_binding);
|
||||
}
|
||||
} else {
|
||||
|
@ -397,29 +395,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
fn ambiguity(
|
||||
fn new_ambiguity_binding(
|
||||
&self,
|
||||
kind: AmbiguityKind,
|
||||
ambiguity_kind: AmbiguityKind,
|
||||
primary_binding: NameBinding<'a>,
|
||||
secondary_binding: NameBinding<'a>,
|
||||
warn_ambiguity: bool,
|
||||
) -> NameBinding<'a> {
|
||||
self.arenas.alloc_name_binding(NameBindingData {
|
||||
ambiguity: Some((secondary_binding, kind)),
|
||||
..(*primary_binding).clone()
|
||||
})
|
||||
let ambiguity = Some((secondary_binding, ambiguity_kind));
|
||||
let data = NameBindingData { ambiguity, warn_ambiguity, ..*primary_binding };
|
||||
self.arenas.alloc_name_binding(data)
|
||||
}
|
||||
|
||||
fn warn_ambiguity(
|
||||
&self,
|
||||
kind: AmbiguityKind,
|
||||
primary_binding: NameBinding<'a>,
|
||||
secondary_binding: NameBinding<'a>,
|
||||
) -> NameBinding<'a> {
|
||||
self.arenas.alloc_name_binding(NameBindingData {
|
||||
ambiguity: Some((secondary_binding, kind)),
|
||||
warn_ambiguity: true,
|
||||
..(*primary_binding).clone()
|
||||
})
|
||||
fn new_warn_ambiguity_binding(&self, binding: NameBinding<'a>) -> NameBinding<'a> {
|
||||
assert!(binding.is_ambiguity_recursive());
|
||||
self.arenas.alloc_name_binding(NameBindingData { warn_ambiguity: true, ..*binding })
|
||||
}
|
||||
|
||||
// Use `f` to mutate the resolution of the name in the module.
|
||||
|
@ -1381,8 +1371,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
target_bindings[ns].get(),
|
||||
) {
|
||||
Ok(other_binding) => {
|
||||
is_redundant =
|
||||
binding.res() == other_binding.res() && !other_binding.is_ambiguity();
|
||||
is_redundant = binding.res() == other_binding.res()
|
||||
&& !other_binding.is_ambiguity_recursive();
|
||||
if is_redundant {
|
||||
redundant_span[ns] =
|
||||
Some((other_binding.span, other_binding.is_import()));
|
||||
|
@ -1455,7 +1445,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
.resolution(import.parent_scope.module, key)
|
||||
.borrow()
|
||||
.binding()
|
||||
.is_some_and(|binding| binding.is_warn_ambiguity());
|
||||
.is_some_and(|binding| binding.warn_ambiguity_recursive());
|
||||
let _ = self.try_define(
|
||||
import.parent_scope.module,
|
||||
key,
|
||||
|
@ -1480,7 +1470,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
|
||||
module.for_each_child(self, |this, ident, _, binding| {
|
||||
let res = binding.res().expect_non_local();
|
||||
let error_ambiguity = binding.is_ambiguity() && !binding.warn_ambiguity;
|
||||
let error_ambiguity = binding.is_ambiguity_recursive() && !binding.warn_ambiguity;
|
||||
if res != def::Res::Err && !error_ambiguity {
|
||||
let mut reexport_chain = SmallVec::new();
|
||||
let mut next_binding = binding;
|
||||
|
|
|
@ -3730,7 +3730,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
let ls_binding = self.maybe_resolve_ident_in_lexical_scope(ident, ValueNS)?;
|
||||
let (res, binding) = match ls_binding {
|
||||
LexicalScopeBinding::Item(binding)
|
||||
if is_syntactic_ambiguity && binding.is_ambiguity() =>
|
||||
if is_syntactic_ambiguity && binding.is_ambiguity_recursive() =>
|
||||
{
|
||||
// For ambiguous bindings we don't know all their definitions and cannot check
|
||||
// whether they can be shadowed by fresh bindings or not, so force an error.
|
||||
|
|
|
@ -694,10 +694,12 @@ impl<'a> fmt::Debug for Module<'a> {
|
|||
}
|
||||
|
||||
/// Records a possibly-private value, type, or module definition.
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
struct NameBindingData<'a> {
|
||||
kind: NameBindingKind<'a>,
|
||||
ambiguity: Option<(NameBinding<'a>, AmbiguityKind)>,
|
||||
/// Produce a warning instead of an error when reporting ambiguities inside this binding.
|
||||
/// May apply to indirect ambiguities under imports, so `ambiguity.is_some()` is not required.
|
||||
warn_ambiguity: bool,
|
||||
expansion: LocalExpnId,
|
||||
span: Span,
|
||||
|
@ -718,7 +720,7 @@ impl<'a> ToNameBinding<'a> for NameBinding<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
enum NameBindingKind<'a> {
|
||||
Res(Res),
|
||||
Module(Module<'a>),
|
||||
|
@ -830,18 +832,18 @@ impl<'a> NameBindingData<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_ambiguity(&self) -> bool {
|
||||
fn is_ambiguity_recursive(&self) -> bool {
|
||||
self.ambiguity.is_some()
|
||||
|| match self.kind {
|
||||
NameBindingKind::Import { binding, .. } => binding.is_ambiguity(),
|
||||
NameBindingKind::Import { binding, .. } => binding.is_ambiguity_recursive(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_warn_ambiguity(&self) -> bool {
|
||||
fn warn_ambiguity_recursive(&self) -> bool {
|
||||
self.warn_ambiguity
|
||||
|| match self.kind {
|
||||
NameBindingKind::Import { binding, .. } => binding.is_warn_ambiguity(),
|
||||
NameBindingKind::Import { binding, .. } => binding.warn_ambiguity_recursive(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedF
|
|||
use crate::num::NonZero;
|
||||
use crate::ops::Try;
|
||||
use core::array;
|
||||
use core::mem::{ManuallyDrop, MaybeUninit};
|
||||
use core::mem::MaybeUninit;
|
||||
use core::ops::ControlFlow;
|
||||
|
||||
/// An iterator that filters the elements of `iter` with `predicate`.
|
||||
|
@ -27,6 +27,42 @@ impl<I, P> Filter<I, P> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<I, P> Filter<I, P>
|
||||
where
|
||||
I: Iterator,
|
||||
P: FnMut(&I::Item) -> bool,
|
||||
{
|
||||
#[inline]
|
||||
fn next_chunk_dropless<const N: usize>(
|
||||
&mut self,
|
||||
) -> Result<[I::Item; N], array::IntoIter<I::Item, N>> {
|
||||
let mut array: [MaybeUninit<I::Item>; N] = [const { MaybeUninit::uninit() }; N];
|
||||
let mut initialized = 0;
|
||||
|
||||
let result = self.iter.try_for_each(|element| {
|
||||
let idx = initialized;
|
||||
// branchless index update combined with unconditionally copying the value even when
|
||||
// it is filtered reduces branching and dependencies in the loop.
|
||||
initialized = idx + (self.predicate)(&element) as usize;
|
||||
// SAFETY: Loop conditions ensure the index is in bounds.
|
||||
unsafe { array.get_unchecked_mut(idx) }.write(element);
|
||||
|
||||
if initialized < N { ControlFlow::Continue(()) } else { ControlFlow::Break(()) }
|
||||
});
|
||||
|
||||
match result {
|
||||
ControlFlow::Break(()) => {
|
||||
// SAFETY: The loop above is only explicitly broken when the array has been fully initialized
|
||||
Ok(unsafe { MaybeUninit::array_assume_init(array) })
|
||||
}
|
||||
ControlFlow::Continue(()) => {
|
||||
// SAFETY: The range is in bounds since the loop breaks when reaching N elements.
|
||||
Err(unsafe { array::IntoIter::new_unchecked(array, 0..initialized) })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "core_impl_debug", since = "1.9.0")]
|
||||
impl<I: fmt::Debug, P> fmt::Debug for Filter<I, P> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
@ -64,52 +100,16 @@ where
|
|||
fn next_chunk<const N: usize>(
|
||||
&mut self,
|
||||
) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>> {
|
||||
let mut array: [MaybeUninit<Self::Item>; N] = [const { MaybeUninit::uninit() }; N];
|
||||
|
||||
struct Guard<'a, T> {
|
||||
array: &'a mut [MaybeUninit<T>],
|
||||
initialized: usize,
|
||||
}
|
||||
|
||||
impl<T> Drop for Guard<'_, T> {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
if const { crate::mem::needs_drop::<T>() } {
|
||||
// SAFETY: self.initialized is always <= N, which also is the length of the array.
|
||||
unsafe {
|
||||
core::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(
|
||||
self.array.get_unchecked_mut(..self.initialized),
|
||||
));
|
||||
}
|
||||
}
|
||||
// avoid codegen for the dead branch
|
||||
let fun = const {
|
||||
if crate::mem::needs_drop::<I::Item>() {
|
||||
array::iter_next_chunk::<I::Item, N>
|
||||
} else {
|
||||
Self::next_chunk_dropless::<N>
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let mut guard = Guard { array: &mut array, initialized: 0 };
|
||||
|
||||
let result = self.iter.try_for_each(|element| {
|
||||
let idx = guard.initialized;
|
||||
guard.initialized = idx + (self.predicate)(&element) as usize;
|
||||
|
||||
// SAFETY: Loop conditions ensure the index is in bounds.
|
||||
unsafe { guard.array.get_unchecked_mut(idx) }.write(element);
|
||||
|
||||
if guard.initialized < N { ControlFlow::Continue(()) } else { ControlFlow::Break(()) }
|
||||
});
|
||||
|
||||
let guard = ManuallyDrop::new(guard);
|
||||
|
||||
match result {
|
||||
ControlFlow::Break(()) => {
|
||||
// SAFETY: The loop above is only explicitly broken when the array has been fully initialized
|
||||
Ok(unsafe { MaybeUninit::array_assume_init(array) })
|
||||
}
|
||||
ControlFlow::Continue(()) => {
|
||||
let initialized = guard.initialized;
|
||||
// SAFETY: The range is in bounds since the loop breaks when reaching N elements.
|
||||
Err(unsafe { array::IntoIter::new_unchecked(array, 0..initialized) })
|
||||
}
|
||||
}
|
||||
fun(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use core::iter::*;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[test]
|
||||
fn test_iterator_filter_count() {
|
||||
|
@ -50,3 +51,15 @@ fn test_double_ended_filter() {
|
|||
assert_eq!(it.next().unwrap(), &2);
|
||||
assert_eq!(it.next_back(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_next_chunk_does_not_leak() {
|
||||
let drop_witness: [_; 5] = std::array::from_fn(|_| Rc::new(()));
|
||||
|
||||
let v = (0..5).map(|i| drop_witness[i].clone()).collect::<Vec<_>>();
|
||||
let _ = v.into_iter().filter(|_| false).next_chunk::<1>();
|
||||
|
||||
for ref w in drop_witness {
|
||||
assert_eq!(Rc::strong_count(w), 1);
|
||||
}
|
||||
}
|
||||
|
|
16
src/tools/miri/tests/pass/tls/win_tls_callback.rs
Normal file
16
src/tools/miri/tests/pass/tls/win_tls_callback.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
//! Ensure that we call Windows TLS callbacks in the local crate.
|
||||
//@only-target-windows
|
||||
// Calling eprintln in the callback seems to (re-)initialize some thread-local storage
|
||||
// and then leak the memory allocated for that. Let's just ignore these leaks,
|
||||
// that's not what this test is about.
|
||||
//@compile-flags: -Zmiri-ignore-leaks
|
||||
|
||||
#[link_section = ".CRT$XLB"]
|
||||
#[used] // Miri only considers explicitly `#[used]` statics for `lookup_link_section`
|
||||
pub static CALLBACK: unsafe extern "system" fn(*const (), u32, *const ()) = tls_callback;
|
||||
|
||||
unsafe extern "system" fn tls_callback(_h: *const (), _dw_reason: u32, _pv: *const ()) {
|
||||
eprintln!("in tls_callback");
|
||||
}
|
||||
|
||||
fn main() {}
|
1
src/tools/miri/tests/pass/tls/win_tls_callback.stderr
Normal file
1
src/tools/miri/tests/pass/tls/win_tls_callback.stderr
Normal file
|
@ -0,0 +1 @@
|
|||
in tls_callback
|
|
@ -6,5 +6,5 @@
|
|||
# Note: this generation step should be run with the oldest supported python
|
||||
# version (currently 3.9) to ensure backward compatibility
|
||||
|
||||
black==23.3.0
|
||||
ruff==0.0.272
|
||||
black==24.4.2
|
||||
ruff==0.4.9
|
||||
|
|
|
@ -4,32 +4,29 @@
|
|||
#
|
||||
# pip-compile --generate-hashes --strip-extras src/tools/tidy/config/requirements.in
|
||||
#
|
||||
black==23.3.0 \
|
||||
--hash=sha256:064101748afa12ad2291c2b91c960be28b817c0c7eaa35bec09cc63aa56493c5 \
|
||||
--hash=sha256:0945e13506be58bf7db93ee5853243eb368ace1c08a24c65ce108986eac65915 \
|
||||
--hash=sha256:11c410f71b876f961d1de77b9699ad19f939094c3a677323f43d7a29855fe326 \
|
||||
--hash=sha256:1c7b8d606e728a41ea1ccbd7264677e494e87cf630e399262ced92d4a8dac940 \
|
||||
--hash=sha256:1d06691f1eb8de91cd1b322f21e3bfc9efe0c7ca1f0e1eb1db44ea367dff656b \
|
||||
--hash=sha256:3238f2aacf827d18d26db07524e44741233ae09a584273aa059066d644ca7b30 \
|
||||
--hash=sha256:32daa9783106c28815d05b724238e30718f34155653d4d6e125dc7daec8e260c \
|
||||
--hash=sha256:35d1381d7a22cc5b2be2f72c7dfdae4072a3336060635718cc7e1ede24221d6c \
|
||||
--hash=sha256:3a150542a204124ed00683f0db1f5cf1c2aaaa9cc3495b7a3b5976fb136090ab \
|
||||
--hash=sha256:48f9d345675bb7fbc3dd85821b12487e1b9a75242028adad0333ce36ed2a6d27 \
|
||||
--hash=sha256:50cb33cac881766a5cd9913e10ff75b1e8eb71babf4c7104f2e9c52da1fb7de2 \
|
||||
--hash=sha256:562bd3a70495facf56814293149e51aa1be9931567474993c7942ff7d3533961 \
|
||||
--hash=sha256:67de8d0c209eb5b330cce2469503de11bca4085880d62f1628bd9972cc3366b9 \
|
||||
--hash=sha256:6b39abdfb402002b8a7d030ccc85cf5afff64ee90fa4c5aebc531e3ad0175ddb \
|
||||
--hash=sha256:6f3c333ea1dd6771b2d3777482429864f8e258899f6ff05826c3a4fcc5ce3f70 \
|
||||
--hash=sha256:714290490c18fb0126baa0fca0a54ee795f7502b44177e1ce7624ba1c00f2331 \
|
||||
--hash=sha256:7c3eb7cea23904399866c55826b31c1f55bbcd3890ce22ff70466b907b6775c2 \
|
||||
--hash=sha256:92c543f6854c28a3c7f39f4d9b7694f9a6eb9d3c5e2ece488c327b6e7ea9b266 \
|
||||
--hash=sha256:a6f6886c9869d4daae2d1715ce34a19bbc4b95006d20ed785ca00fa03cba312d \
|
||||
--hash=sha256:a8a968125d0a6a404842fa1bf0b349a568634f856aa08ffaff40ae0dfa52e7c6 \
|
||||
--hash=sha256:c7ab5790333c448903c4b721b59c0d80b11fe5e9803d8703e84dcb8da56fec1b \
|
||||
--hash=sha256:e114420bf26b90d4b9daa597351337762b63039752bdf72bf361364c1aa05925 \
|
||||
--hash=sha256:e198cf27888ad6f4ff331ca1c48ffc038848ea9f031a3b40ba36aced7e22f2c8 \
|
||||
--hash=sha256:ec751418022185b0c1bb7d7736e6933d40bbb14c14a0abcf9123d1b159f98dd4 \
|
||||
--hash=sha256:f0bd2f4a58d6666500542b26354978218a9babcdc972722f4bf90779524515f3
|
||||
black==24.4.2 \
|
||||
--hash=sha256:257d724c2c9b1660f353b36c802ccece186a30accc7742c176d29c146df6e474 \
|
||||
--hash=sha256:37aae07b029fa0174d39daf02748b379399b909652a806e5708199bd93899da1 \
|
||||
--hash=sha256:415e686e87dbbe6f4cd5ef0fbf764af7b89f9057b97c908742b6008cc554b9c0 \
|
||||
--hash=sha256:48a85f2cb5e6799a9ef05347b476cce6c182d6c71ee36925a6c194d074336ef8 \
|
||||
--hash=sha256:7768a0dbf16a39aa5e9a3ded568bb545c8c2727396d063bbaf847df05b08cd96 \
|
||||
--hash=sha256:7e122b1c4fb252fd85df3ca93578732b4749d9be076593076ef4d07a0233c3e1 \
|
||||
--hash=sha256:88c57dc656038f1ab9f92b3eb5335ee9b021412feaa46330d5eba4e51fe49b04 \
|
||||
--hash=sha256:8e537d281831ad0e71007dcdcbe50a71470b978c453fa41ce77186bbe0ed6021 \
|
||||
--hash=sha256:98e123f1d5cfd42f886624d84464f7756f60ff6eab89ae845210631714f6db94 \
|
||||
--hash=sha256:accf49e151c8ed2c0cdc528691838afd217c50412534e876a19270fea1e28e2d \
|
||||
--hash=sha256:b1530ae42e9d6d5b670a34db49a94115a64596bc77710b1d05e9801e62ca0a7c \
|
||||
--hash=sha256:b9176b9832e84308818a99a561e90aa479e73c523b3f77afd07913380ae2eab7 \
|
||||
--hash=sha256:bdde6f877a18f24844e381d45e9947a49e97933573ac9d4345399be37621e26c \
|
||||
--hash=sha256:be8bef99eb46d5021bf053114442914baeb3649a89dc5f3a555c88737e5e98fc \
|
||||
--hash=sha256:bf10f7310db693bb62692609b397e8d67257c55f949abde4c67f9cc574492cc7 \
|
||||
--hash=sha256:c872b53057f000085da66a19c55d68f6f8ddcac2642392ad3a355878406fbd4d \
|
||||
--hash=sha256:d36ed1124bb81b32f8614555b34cc4259c3fbc7eec17870e8ff8ded335b58d8c \
|
||||
--hash=sha256:da33a1a5e49c4122ccdfd56cd021ff1ebc4a1ec4e2d01594fef9b6f267a9e741 \
|
||||
--hash=sha256:dd1b5a14e417189db4c7b64a6540f31730713d173f0b63e55fabd52d61d8fdce \
|
||||
--hash=sha256:e151054aa00bad1f4e1f04919542885f89f5f7d086b8a59e5000e6c616896ffb \
|
||||
--hash=sha256:eaea3008c281f1038edb473c1aa8ed8143a5535ff18f978a318f10302b254063 \
|
||||
--hash=sha256:ef703f83fc32e131e9bcc0a5094cfe85599e7109f896fe8bc96cc402f3eb4b6e
|
||||
# via -r src/tools/tidy/config/requirements.in
|
||||
click==8.1.3 \
|
||||
--hash=sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e \
|
||||
|
@ -47,28 +44,28 @@ pathspec==0.11.1 \
|
|||
--hash=sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687 \
|
||||
--hash=sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293
|
||||
# via black
|
||||
platformdirs==3.6.0 \
|
||||
--hash=sha256:57e28820ca8094678b807ff529196506d7a21e17156cb1cddb3e74cebce54640 \
|
||||
--hash=sha256:ffa199e3fbab8365778c4a10e1fbf1b9cd50707de826eb304b50e57ec0cc8d38
|
||||
platformdirs==4.2.2 \
|
||||
--hash=sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee \
|
||||
--hash=sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3
|
||||
# via black
|
||||
ruff==0.0.272 \
|
||||
--hash=sha256:06b8ee4eb8711ab119db51028dd9f5384b44728c23586424fd6e241a5b9c4a3b \
|
||||
--hash=sha256:1609b864a8d7ee75a8c07578bdea0a7db75a144404e75ef3162e0042bfdc100d \
|
||||
--hash=sha256:19643d448f76b1eb8a764719072e9c885968971bfba872e14e7257e08bc2f2b7 \
|
||||
--hash=sha256:273a01dc8c3c4fd4c2af7ea7a67c8d39bb09bce466e640dd170034da75d14cab \
|
||||
--hash=sha256:27b2ea68d2aa69fff1b20b67636b1e3e22a6a39e476c880da1282c3e4bf6ee5a \
|
||||
--hash=sha256:48eccf225615e106341a641f826b15224b8a4240b84269ead62f0afd6d7e2d95 \
|
||||
--hash=sha256:677284430ac539bb23421a2b431b4ebc588097ef3ef918d0e0a8d8ed31fea216 \
|
||||
--hash=sha256:691d72a00a99707a4e0b2846690961157aef7b17b6b884f6b4420a9f25cd39b5 \
|
||||
--hash=sha256:86bc788245361a8148ff98667da938a01e1606b28a45e50ac977b09d3ad2c538 \
|
||||
--hash=sha256:905ff8f3d6206ad56fcd70674453527b9011c8b0dc73ead27618426feff6908e \
|
||||
--hash=sha256:9c4bfb75456a8e1efe14c52fcefb89cfb8f2a0d31ed8d804b82c6cf2dc29c42c \
|
||||
--hash=sha256:a37ec80e238ead2969b746d7d1b6b0d31aa799498e9ba4281ab505b93e1f4b28 \
|
||||
--hash=sha256:ae9b57546e118660175d45d264b87e9b4c19405c75b587b6e4d21e6a17bf4fdf \
|
||||
--hash=sha256:bd2bbe337a3f84958f796c77820d55ac2db1e6753f39d1d1baed44e07f13f96d \
|
||||
--hash=sha256:d5a208f8ef0e51d4746930589f54f9f92f84bb69a7d15b1de34ce80a7681bc00 \
|
||||
--hash=sha256:dc406e5d756d932da95f3af082814d2467943631a587339ee65e5a4f4fbe83eb \
|
||||
--hash=sha256:ee76b4f05fcfff37bd6ac209d1370520d509ea70b5a637bdf0a04d0c99e13dff
|
||||
ruff==0.4.9 \
|
||||
--hash=sha256:06b60f91bfa5514bb689b500a25ba48e897d18fea14dce14b48a0c40d1635893 \
|
||||
--hash=sha256:0e8e7b95673f22e0efd3571fb5b0cf71a5eaaa3cc8a776584f3b2cc878e46bff \
|
||||
--hash=sha256:2d45ddc6d82e1190ea737341326ecbc9a61447ba331b0a8962869fcada758505 \
|
||||
--hash=sha256:4555056049d46d8a381f746680db1c46e67ac3b00d714606304077682832998e \
|
||||
--hash=sha256:5d5460f789ccf4efd43f265a58538a2c24dbce15dbf560676e430375f20a8198 \
|
||||
--hash=sha256:673bddb893f21ab47a8334c8e0ea7fd6598ecc8e698da75bcd12a7b9d0a3206e \
|
||||
--hash=sha256:732dd550bfa5d85af8c3c6cbc47ba5b67c6aed8a89e2f011b908fc88f87649db \
|
||||
--hash=sha256:784d3ec9bd6493c3b720a0b76f741e6c2d7d44f6b2be87f5eef1ae8cc1d54c84 \
|
||||
--hash=sha256:78de3fdb95c4af084087628132336772b1c5044f6e710739d440fc0bccf4d321 \
|
||||
--hash=sha256:8064590fd1a50dcf4909c268b0e7c2498253273309ad3d97e4a752bb9df4f521 \
|
||||
--hash=sha256:88bffe9c6a454bf8529f9ab9091c99490578a593cc9f9822b7fc065ee0712a06 \
|
||||
--hash=sha256:8c1aff58c31948cc66d0b22951aa19edb5af0a3af40c936340cd32a8b1ab7438 \
|
||||
--hash=sha256:98ec2775fd2d856dc405635e5ee4ff177920f2141b8e2d9eb5bd6efd50e80317 \
|
||||
--hash=sha256:b262ed08d036ebe162123170b35703aaf9daffecb698cd367a8d585157732991 \
|
||||
--hash=sha256:e0a22c4157e53d006530c902107c7f550b9233e9706313ab57b892d7197d8e52 \
|
||||
--hash=sha256:e91175fbe48f8a2174c9aad70438fe9cb0a5732c4159b2a10a3565fea2d94cde \
|
||||
--hash=sha256:f1cb0828ac9533ba0135d148d214e284711ede33640465e706772645483427e3
|
||||
# via -r src/tools/tidy/config/requirements.in
|
||||
tomli==2.0.1 \
|
||||
--hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \
|
||||
|
|
|
@ -1,17 +1,7 @@
|
|||
# Configuration for ruff python linter, run as part of tidy external tools
|
||||
|
||||
# B (bugbear), E (pycodestyle, standard), EXE (executables) F (flakes, standard)
|
||||
# ERM for error messages would be beneficial at some point
|
||||
select = ["B", "E", "EXE", "F"]
|
||||
|
||||
ignore = [
|
||||
"E501", # line-too-long
|
||||
"F403", # undefined-local-with-import-star
|
||||
"F405", # undefined-local-with-import-star-usage
|
||||
]
|
||||
|
||||
# lowest possible for ruff
|
||||
target-version = "py37"
|
||||
target-version = "py39"
|
||||
|
||||
# Ignore all submodules
|
||||
extend-exclude = [
|
||||
|
@ -41,3 +31,14 @@ extend-exclude = [
|
|||
"../library/backtrace/",
|
||||
"../src/tools/rustc-perf/",
|
||||
]
|
||||
|
||||
[lint]
|
||||
# B (bugbear), E (pycodestyle, standard), EXE (executables) F (flakes, standard)
|
||||
# ERM for error messages would be beneficial at some point
|
||||
select = ["B", "E", "EXE", "F"]
|
||||
|
||||
ignore = [
|
||||
"E501", # line-too-long
|
||||
"F403", # undefined-local-with-import-star
|
||||
"F405", # undefined-local-with-import-star-usage
|
||||
]
|
||||
|
|
|
@ -55,13 +55,11 @@ run-make/incr-foreign-head-span/Makefile
|
|||
run-make/interdependent-c-libraries/Makefile
|
||||
run-make/intrinsic-unreachable/Makefile
|
||||
run-make/invalid-library/Makefile
|
||||
run-make/invalid-so/Makefile
|
||||
run-make/issue-107094/Makefile
|
||||
run-make/issue-109934-lto-debuginfo/Makefile
|
||||
run-make/issue-14698/Makefile
|
||||
run-make/issue-15460/Makefile
|
||||
run-make/issue-18943/Makefile
|
||||
run-make/issue-20626/Makefile
|
||||
run-make/issue-22131/Makefile
|
||||
run-make/issue-25581/Makefile
|
||||
run-make/issue-26006/Makefile
|
||||
|
@ -97,7 +95,6 @@ run-make/long-linker-command-lines-cmd-exe/Makefile
|
|||
run-make/long-linker-command-lines/Makefile
|
||||
run-make/longjmp-across-rust/Makefile
|
||||
run-make/lto-dylib-dep/Makefile
|
||||
run-make/lto-empty/Makefile
|
||||
run-make/lto-linkage-used-attr/Makefile
|
||||
run-make/lto-no-link-whole-rlib/Makefile
|
||||
run-make/lto-smoke-c/Makefile
|
||||
|
|
|
@ -110,12 +110,13 @@ fn check_impl(
|
|||
}
|
||||
|
||||
let mut args = merge_args(&cfg_args_ruff, &file_args_ruff);
|
||||
args.insert(0, "check".as_ref());
|
||||
let res = py_runner(py_path.as_ref().unwrap(), "ruff", &args);
|
||||
|
||||
if res.is_err() && show_diff {
|
||||
eprintln!("\npython linting failed! Printing diff suggestions:");
|
||||
|
||||
args.insert(0, "--diff".as_ref());
|
||||
args.insert(1, "--diff".as_ref());
|
||||
let _ = py_runner(py_path.as_ref().unwrap(), "ruff", &args);
|
||||
}
|
||||
// Rethrow error
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
include ../tools.mk
|
||||
|
||||
DYLIB_NAME := $(shell echo | $(RUSTC) --crate-name foo --crate-type dylib --print file-names -)
|
||||
|
||||
all:
|
||||
echo >> $(TMPDIR)/$(DYLIB_NAME)
|
||||
$(RUSTC) --crate-type lib --extern foo=$(TMPDIR)/$(DYLIB_NAME) bar.rs 2>&1 | $(CGREP) 'invalid metadata files for crate `foo`'
|
17
tests/run-make/invalid-so/rmake.rs
Normal file
17
tests/run-make/invalid-so/rmake.rs
Normal file
|
@ -0,0 +1,17 @@
|
|||
// When a fake library was given to the compiler, it would
|
||||
// result in an obscure and unhelpful error message. This test
|
||||
// creates a false "foo" dylib, and checks that the standard error
|
||||
// explains that the file exists, but that its metadata is incorrect.
|
||||
// See https://github.com/rust-lang/rust/pull/88368
|
||||
|
||||
use run_make_support::{dynamic_lib_name, fs_wrapper, rustc};
|
||||
|
||||
fn main() {
|
||||
fs_wrapper::create_file(dynamic_lib_name("foo"));
|
||||
rustc()
|
||||
.crate_type("lib")
|
||||
.extern_("foo", dynamic_lib_name("foo"))
|
||||
.input("bar.rs")
|
||||
.run_fail()
|
||||
.assert_stderr_contains("invalid metadata files for crate `foo`");
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
# ignore-cross-compile
|
||||
include ../tools.mk
|
||||
|
||||
# Test output to be four
|
||||
# The original error only occurred when printing, not when comparing using assert!
|
||||
|
||||
all:
|
||||
$(RUSTC) foo.rs -O
|
||||
[ `$(call RUN,foo)` = "4" ]
|
|
@ -1,13 +0,0 @@
|
|||
# ignore-cross-compile
|
||||
include ../tools.mk
|
||||
|
||||
all: cdylib-fat cdylib-thin
|
||||
|
||||
cdylib-fat:
|
||||
$(RUSTC) lib.rs -C lto=fat -C opt-level=3 -C incremental=$(TMPDIR)/inc-fat
|
||||
$(RUSTC) lib.rs -C lto=fat -C opt-level=3 -C incremental=$(TMPDIR)/inc-fat
|
||||
|
||||
cdylib-thin:
|
||||
$(RUSTC) lib.rs -C lto=thin -C opt-level=3 -C incremental=$(TMPDIR)/inc-thin
|
||||
$(RUSTC) lib.rs -C lto=thin -C opt-level=3 -C incremental=$(TMPDIR)/inc-thin
|
||||
|
17
tests/run-make/lto-empty/rmake.rs
Normal file
17
tests/run-make/lto-empty/rmake.rs
Normal file
|
@ -0,0 +1,17 @@
|
|||
// Compiling Rust code twice in a row with "fat" link-time-optimizations used to cause
|
||||
// an internal compiler error (ICE). This was due to how the compiler would cache some modules
|
||||
// to make subsequent compilations faster, at least one of which was required for LTO to link
|
||||
// into. After this was patched in #63956, this test checks that the bug does not make
|
||||
// a resurgence.
|
||||
// See https://github.com/rust-lang/rust/issues/63349
|
||||
|
||||
//@ ignore-cross-compile
|
||||
|
||||
use run_make_support::rustc;
|
||||
|
||||
fn main() {
|
||||
rustc().input("lib.rs").arg("-Clto=fat").opt_level("3").incremental("inc-fat").run();
|
||||
rustc().input("lib.rs").arg("-Clto=fat").opt_level("3").incremental("inc-fat").run();
|
||||
rustc().input("lib.rs").arg("-Clto=thin").opt_level("3").incremental("inc-thin").run();
|
||||
rustc().input("lib.rs").arg("-Clto=thin").opt_level("3").incremental("inc-thin").run();
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
// Despite the absence of any unsafe Rust code, foo.rs in this test would,
|
||||
// because of the raw function pointer,
|
||||
// cause undefined behavior and fail to print the expected result, "4" -
|
||||
// only when activating optimizations (opt-level 2). This test checks
|
||||
// that this bug does not make a resurgence.
|
||||
// Note that the bug cannot be observed in an assert_eq!, only in the stdout.
|
||||
// See https://github.com/rust-lang/rust/issues/20626
|
||||
|
||||
//@ ignore-cross-compile
|
||||
|
||||
use run_make_support::{run, rustc};
|
||||
|
||||
fn main() {
|
||||
rustc().input("foo.rs").opt().run();
|
||||
run("foo").assert_stdout_equals("4");
|
||||
}
|
|
@ -5,6 +5,11 @@ LL | let k = i + j;
|
|||
| - ^ - Vec<R>
|
||||
| |
|
||||
| Vec<R>
|
||||
|
|
||||
note: the foreign item type `Vec<R>` doesn't implement `Add`
|
||||
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
|
|
||||
= note: not implement `Add`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
@ -5,6 +5,12 @@ LL | let z: isize = a.x + b.y;
|
|||
| --- ^ --- Box<isize>
|
||||
| |
|
||||
| Box<isize>
|
||||
|
|
||||
note: the foreign item type `Box<isize>` doesn't implement `Add`
|
||||
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
::: $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
|
|
||||
= note: not implement `Add`
|
||||
|
||||
error[E0369]: cannot add `Box<isize>` to `Box<isize>`
|
||||
--> $DIR/autoderef-full-lval.rs:21:33
|
||||
|
@ -13,6 +19,12 @@ LL | let answer: isize = forty.a + two.a;
|
|||
| ------- ^ ----- Box<isize>
|
||||
| |
|
||||
| Box<isize>
|
||||
|
|
||||
note: the foreign item type `Box<isize>` doesn't implement `Add`
|
||||
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
::: $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
|
|
||||
= note: not implement `Add`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
16
tests/ui/binop/binary-op-not-allowed-issue-125631.rs
Normal file
16
tests/ui/binop/binary-op-not-allowed-issue-125631.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
use std::io::{Error, ErrorKind};
|
||||
use std::thread;
|
||||
|
||||
struct T1;
|
||||
struct T2;
|
||||
|
||||
fn main() {
|
||||
(Error::new(ErrorKind::Other, "1"), T1, 1) == (Error::new(ErrorKind::Other, "1"), T1, 2);
|
||||
//~^ERROR binary operation `==` cannot be applied to type
|
||||
(Error::new(ErrorKind::Other, "2"), thread::current())
|
||||
== (Error::new(ErrorKind::Other, "2"), thread::current());
|
||||
//~^ERROR binary operation `==` cannot be applied to type
|
||||
(Error::new(ErrorKind::Other, "4"), thread::current(), T1, T2)
|
||||
== (Error::new(ErrorKind::Other, "4"), thread::current(), T1, T2);
|
||||
//~^ERROR binary operation `==` cannot be applied to type
|
||||
}
|
75
tests/ui/binop/binary-op-not-allowed-issue-125631.stderr
Normal file
75
tests/ui/binop/binary-op-not-allowed-issue-125631.stderr
Normal file
|
@ -0,0 +1,75 @@
|
|||
error[E0369]: binary operation `==` cannot be applied to type `(std::io::Error, T1, {integer})`
|
||||
--> $DIR/binary-op-not-allowed-issue-125631.rs:8:48
|
||||
|
|
||||
LL | (Error::new(ErrorKind::Other, "1"), T1, 1) == (Error::new(ErrorKind::Other, "1"), T1, 2);
|
||||
| ------------------------------------------ ^^ ------------------------------------------ (std::io::Error, T1, {integer})
|
||||
| |
|
||||
| (std::io::Error, T1, {integer})
|
||||
|
|
||||
note: an implementation of `PartialEq` might be missing for `T1`
|
||||
--> $DIR/binary-op-not-allowed-issue-125631.rs:4:1
|
||||
|
|
||||
LL | struct T1;
|
||||
| ^^^^^^^^^ must implement `PartialEq`
|
||||
note: the foreign item type `std::io::Error` doesn't implement `PartialEq`
|
||||
--> $SRC_DIR/std/src/io/error.rs:LL:COL
|
||||
|
|
||||
= note: not implement `PartialEq`
|
||||
help: consider annotating `T1` with `#[derive(PartialEq)]`
|
||||
|
|
||||
LL + #[derive(PartialEq)]
|
||||
LL | struct T1;
|
||||
|
|
||||
|
||||
error[E0369]: binary operation `==` cannot be applied to type `(std::io::Error, Thread)`
|
||||
--> $DIR/binary-op-not-allowed-issue-125631.rs:11:9
|
||||
|
|
||||
LL | (Error::new(ErrorKind::Other, "2"), thread::current())
|
||||
| ------------------------------------------------------ (std::io::Error, Thread)
|
||||
LL | == (Error::new(ErrorKind::Other, "2"), thread::current());
|
||||
| ^^ ------------------------------------------------------ (std::io::Error, Thread)
|
||||
|
|
||||
note: the foreign item types don't implement required traits for this operation to be valid
|
||||
--> $SRC_DIR/std/src/io/error.rs:LL:COL
|
||||
|
|
||||
= note: not implement `PartialEq`
|
||||
--> $SRC_DIR/std/src/thread/mod.rs:LL:COL
|
||||
|
|
||||
= note: not implement `PartialEq`
|
||||
|
||||
error[E0369]: binary operation `==` cannot be applied to type `(std::io::Error, Thread, T1, T2)`
|
||||
--> $DIR/binary-op-not-allowed-issue-125631.rs:14:9
|
||||
|
|
||||
LL | (Error::new(ErrorKind::Other, "4"), thread::current(), T1, T2)
|
||||
| -------------------------------------------------------------- (std::io::Error, Thread, T1, T2)
|
||||
LL | == (Error::new(ErrorKind::Other, "4"), thread::current(), T1, T2);
|
||||
| ^^ -------------------------------------------------------------- (std::io::Error, Thread, T1, T2)
|
||||
|
|
||||
note: the following types would have to `impl` their required traits for this operation to be valid
|
||||
--> $DIR/binary-op-not-allowed-issue-125631.rs:4:1
|
||||
|
|
||||
LL | struct T1;
|
||||
| ^^^^^^^^^ must implement `PartialEq`
|
||||
LL | struct T2;
|
||||
| ^^^^^^^^^ must implement `PartialEq`
|
||||
note: the foreign item types don't implement required traits for this operation to be valid
|
||||
--> $SRC_DIR/std/src/io/error.rs:LL:COL
|
||||
|
|
||||
= note: not implement `PartialEq`
|
||||
--> $SRC_DIR/std/src/thread/mod.rs:LL:COL
|
||||
|
|
||||
= note: not implement `PartialEq`
|
||||
help: consider annotating `T1` with `#[derive(PartialEq)]`
|
||||
|
|
||||
LL + #[derive(PartialEq)]
|
||||
LL | struct T1;
|
||||
|
|
||||
help: consider annotating `T2` with `#[derive(PartialEq)]`
|
||||
|
|
||||
LL + #[derive(PartialEq)]
|
||||
LL | struct T2;
|
||||
|
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0369`.
|
|
@ -5,6 +5,11 @@ LL | fn main() { let x = "a".to_string() ^ "b".to_string(); }
|
|||
| --------------- ^ --------------- String
|
||||
| |
|
||||
| String
|
||||
|
|
||||
note: the foreign item type `String` doesn't implement `BitXor`
|
||||
--> $SRC_DIR/alloc/src/string.rs:LL:COL
|
||||
|
|
||||
= note: not implement `BitXor`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
@ -5,6 +5,12 @@ LL | LinkedList::new() += 1;
|
|||
| -----------------^^^^^
|
||||
| |
|
||||
| cannot use `+=` on type `LinkedList<_>`
|
||||
|
|
||||
note: the foreign item type `LinkedList<_>` doesn't implement `AddAssign<{integer}>`
|
||||
--> $SRC_DIR/alloc/src/collections/linked_list.rs:LL:COL
|
||||
::: $SRC_DIR/alloc/src/collections/linked_list.rs:LL:COL
|
||||
|
|
||||
= note: not implement `AddAssign<{integer}>`
|
||||
|
||||
error[E0067]: invalid left-hand side of assignment
|
||||
--> $DIR/E0067.rs:4:23
|
||||
|
|
23
tests/ui/impl-trait/in-trait/refine-resolution-errors.rs
Normal file
23
tests/ui/impl-trait/in-trait/refine-resolution-errors.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
// This is a non-regression test for issue #126670 where RPITIT refinement checking encountered
|
||||
// errors during resolution and ICEd.
|
||||
|
||||
//@ edition: 2018
|
||||
|
||||
pub trait Mirror {
|
||||
type Assoc;
|
||||
}
|
||||
impl<T: ?Sized> Mirror for () {
|
||||
//~^ ERROR the type parameter `T` is not constrained
|
||||
type Assoc = T;
|
||||
}
|
||||
|
||||
pub trait First {
|
||||
async fn first() -> <() as Mirror>::Assoc;
|
||||
//~^ ERROR type annotations needed
|
||||
}
|
||||
|
||||
impl First for () {
|
||||
async fn first() {}
|
||||
}
|
||||
|
||||
fn main() {}
|
16
tests/ui/impl-trait/in-trait/refine-resolution-errors.stderr
Normal file
16
tests/ui/impl-trait/in-trait/refine-resolution-errors.stderr
Normal file
|
@ -0,0 +1,16 @@
|
|||
error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
|
||||
--> $DIR/refine-resolution-errors.rs:9:6
|
||||
|
|
||||
LL | impl<T: ?Sized> Mirror for () {
|
||||
| ^ unconstrained type parameter
|
||||
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/refine-resolution-errors.rs:15:5
|
||||
|
|
||||
LL | async fn first() -> <() as Mirror>::Assoc;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0207, E0282.
|
||||
For more information about an error, try `rustc --explain E0207`.
|
|
@ -5,6 +5,12 @@ LL | println!("{}", x + 1);
|
|||
| - ^ - {integer}
|
||||
| |
|
||||
| Box<isize>
|
||||
|
|
||||
note: the foreign item type `Box<isize>` doesn't implement `Add<{integer}>`
|
||||
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
::: $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
|
|
||||
= note: not implement `Add<{integer}>`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
@ -3,6 +3,11 @@ error[E0600]: cannot apply unary operator `-` to type `String`
|
|||
|
|
||||
LL | fn main() { -"foo".to_string(); }
|
||||
| ^^^^^^^^^^^^^^^^^^ cannot apply unary operator `-`
|
||||
|
|
||||
note: the foreign item type `String` doesn't implement `Neg`
|
||||
--> $SRC_DIR/alloc/src/string.rs:LL:COL
|
||||
|
|
||||
= note: not implement `Neg`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
@ -81,11 +81,13 @@ LL | async fn fe1();
|
|||
error: items in unadorned `extern` blocks cannot have safety qualifiers
|
||||
--> $DIR/fn-header-semantic-fail.rs:47:9
|
||||
|
|
||||
LL | extern "C" {
|
||||
| ---------- help: add unsafe to this `extern` block
|
||||
LL | async fn fe1();
|
||||
LL | unsafe fn fe2();
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: add unsafe to this `extern` block
|
||||
|
|
||||
LL | unsafe extern "C" {
|
||||
| ++++++
|
||||
|
||||
error: functions in `extern` blocks cannot have qualifiers
|
||||
--> $DIR/fn-header-semantic-fail.rs:48:9
|
||||
|
@ -135,11 +137,13 @@ LL | const async unsafe extern "C" fn fe5();
|
|||
error: items in unadorned `extern` blocks cannot have safety qualifiers
|
||||
--> $DIR/fn-header-semantic-fail.rs:50:9
|
||||
|
|
||||
LL | extern "C" {
|
||||
| ---------- help: add unsafe to this `extern` block
|
||||
...
|
||||
LL | const async unsafe extern "C" fn fe5();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: add unsafe to this `extern` block
|
||||
|
|
||||
LL | unsafe extern "C" {
|
||||
| ++++++
|
||||
|
||||
error: functions cannot be both `const` and `async`
|
||||
--> $DIR/fn-header-semantic-fail.rs:50:9
|
||||
|
|
|
@ -18,11 +18,13 @@ LL | const unsafe fn bar();
|
|||
error: items in unadorned `extern` blocks cannot have safety qualifiers
|
||||
--> $DIR/no-const-fn-in-extern-block.rs:4:5
|
||||
|
|
||||
LL | extern "C" {
|
||||
| ---------- help: add unsafe to this `extern` block
|
||||
...
|
||||
LL | const unsafe fn bar();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: add unsafe to this `extern` block
|
||||
|
|
||||
LL | unsafe extern "C" {
|
||||
| ++++++
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
@ -13,11 +13,13 @@ LL | extern "C" unsafe {
|
|||
error: items in unadorned `extern` blocks cannot have safety qualifiers
|
||||
--> $DIR/unsafe-foreign-mod-2.rs:4:5
|
||||
|
|
||||
LL | extern "C" unsafe {
|
||||
| ----------------- help: add unsafe to this `extern` block
|
||||
...
|
||||
LL | unsafe fn foo();
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: add unsafe to this `extern` block
|
||||
|
|
||||
LL | unsafe extern "C" unsafe {
|
||||
| ++++++
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
@ -5,6 +5,11 @@ LL | fn foo(t: Bar) -> isize { match t { Bar::T1(_, Some(x)) => { return x * 3;
|
|||
| - ^ - {integer}
|
||||
| |
|
||||
| Vec<isize>
|
||||
|
|
||||
note: the foreign item type `Vec<isize>` doesn't implement `Mul<{integer}>`
|
||||
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
|
|
||||
= note: not implement `Mul<{integer}>`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ error: function pointers cannot be declared with `safe` safety qualifier
|
|||
--> $DIR/safe-outside-extern.rs:24:14
|
||||
|
|
||||
LL | type FnPtr = safe fn(i32, i32) -> i32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ error: function pointers cannot be declared with `safe` safety qualifier
|
|||
--> $DIR/safe-outside-extern.rs:24:14
|
||||
|
|
||||
LL | type FnPtr = safe fn(i32, i32) -> i32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0658]: `unsafe extern {}` blocks and `safe` keyword are experimental
|
||||
--> $DIR/safe-outside-extern.rs:4:1
|
||||
|
|
|
@ -1,20 +1,24 @@
|
|||
error: items in unadorned `extern` blocks cannot have safety qualifiers
|
||||
--> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5
|
||||
|
|
||||
LL | extern "C" {
|
||||
| ---------- help: add unsafe to this `extern` block
|
||||
LL |
|
||||
LL | safe static TEST1: i32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: add unsafe to this `extern` block
|
||||
|
|
||||
LL | unsafe extern "C" {
|
||||
| ++++++
|
||||
|
||||
error: items in unadorned `extern` blocks cannot have safety qualifiers
|
||||
--> $DIR/safe-unsafe-on-unadorned-extern-block.rs:12:5
|
||||
|
|
||||
LL | extern "C" {
|
||||
| ---------- help: add unsafe to this `extern` block
|
||||
...
|
||||
LL | safe fn test1(i: i32);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: add unsafe to this `extern` block
|
||||
|
|
||||
LL | unsafe extern "C" {
|
||||
| ++++++
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
@ -13,20 +13,24 @@ LL | | }
|
|||
error: items in unadorned `extern` blocks cannot have safety qualifiers
|
||||
--> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5
|
||||
|
|
||||
LL | extern "C" {
|
||||
| ---------- help: add unsafe to this `extern` block
|
||||
LL |
|
||||
LL | safe static TEST1: i32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: add unsafe to this `extern` block
|
||||
|
|
||||
LL | unsafe extern "C" {
|
||||
| ++++++
|
||||
|
||||
error: items in unadorned `extern` blocks cannot have safety qualifiers
|
||||
--> $DIR/safe-unsafe-on-unadorned-extern-block.rs:12:5
|
||||
|
|
||||
LL | extern "C" {
|
||||
| ---------- help: add unsafe to this `extern` block
|
||||
...
|
||||
LL | safe fn test1(i: i32);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: add unsafe to this `extern` block
|
||||
|
|
||||
LL | unsafe extern "C" {
|
||||
| ++++++
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
//@ run-rustfix
|
||||
|
||||
#![feature(unsafe_extern_blocks)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
unsafe extern "C" {
|
||||
unsafe fn foo(); //~ ERROR items in unadorned `extern` blocks cannot have safety qualifiers
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,10 @@
|
|||
//@ run-rustfix
|
||||
|
||||
#![feature(unsafe_extern_blocks)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
extern "C" {
|
||||
unsafe fn foo(); //~ ERROR items in unadorned `extern` blocks cannot have safety qualifiers
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,13 @@
|
|||
error: items in unadorned `extern` blocks cannot have safety qualifiers
|
||||
--> $DIR/unsafe-on-extern-block-issue-126756.rs:7:5
|
||||
|
|
||||
LL | unsafe fn foo();
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: add unsafe to this `extern` block
|
||||
|
|
||||
LL | unsafe extern "C" {
|
||||
| ++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
|
@ -19,6 +19,10 @@ LL | x.lock().unwrap() += 1;
|
|||
| |
|
||||
| cannot use `+=` on type `MutexGuard<'_, usize>`
|
||||
|
|
||||
note: the foreign item type `MutexGuard<'_, usize>` doesn't implement `AddAssign<{integer}>`
|
||||
--> $SRC_DIR/std/src/sync/mutex.rs:LL:COL
|
||||
|
|
||||
= note: not implement `AddAssign<{integer}>`
|
||||
help: `+=` can be used on `usize` if you dereference the left-hand side
|
||||
|
|
||||
LL | *x.lock().unwrap() += 1;
|
||||
|
@ -47,6 +51,10 @@ LL | y += 1;
|
|||
| |
|
||||
| cannot use `+=` on type `MutexGuard<'_, usize>`
|
||||
|
|
||||
note: the foreign item type `MutexGuard<'_, usize>` doesn't implement `AddAssign<{integer}>`
|
||||
--> $SRC_DIR/std/src/sync/mutex.rs:LL:COL
|
||||
|
|
||||
= note: not implement `AddAssign<{integer}>`
|
||||
help: `+=` can be used on `usize` if you dereference the left-hand side
|
||||
|
|
||||
LL | *y += 1;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue