Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 28 additions & 8 deletions compiler/rustc_hir_typeck/src/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -415,10 +415,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
infcx.instantiate_canonical(span, &query_input.canonical);
let query::MethodAutoderefSteps { predefined_opaques_in_body: _, self_ty } = value;
debug!(?self_ty, ?query_input, "probe_op: Mode::Path");
let prev_opaque_entries = self.inner.borrow_mut().opaque_types().num_entries();
MethodAutoderefStepsResult {
steps: infcx.tcx.arena.alloc_from_iter([CandidateStep {
self_ty: self
.make_query_response_ignoring_pending_obligations(var_values, self_ty),
self_ty: self.make_query_response_ignoring_pending_obligations(
var_values,
self_ty,
prev_opaque_entries,
),
self_ty_is_opaque: false,
autoderefs: 0,
from_unsafe_deref: false,
Expand Down Expand Up @@ -607,6 +611,7 @@ pub(crate) fn method_autoderef_steps<'tcx>(
debug!(?key, ?ty, ?prev, "ignore duplicate in `opaque_types_storage`");
}
}
let prev_opaque_entries = infcx.inner.borrow_mut().opaque_types().num_entries();

// We accept not-yet-defined opaque types in the autoderef
// chain to support recursive calls. We do error if the final
Expand Down Expand Up @@ -650,8 +655,11 @@ pub(crate) fn method_autoderef_steps<'tcx>(
.zip(reachable_via_deref)
.map(|((ty, d), reachable_via_deref)| {
let step = CandidateStep {
self_ty: infcx
.make_query_response_ignoring_pending_obligations(inference_vars, ty),
self_ty: infcx.make_query_response_ignoring_pending_obligations(
inference_vars,
ty,
prev_opaque_entries,
),
self_ty_is_opaque: self_ty_is_opaque(ty),
autoderefs: d,
from_unsafe_deref: reached_raw_pointer,
Expand All @@ -671,8 +679,11 @@ pub(crate) fn method_autoderef_steps<'tcx>(
.by_ref()
.map(|(ty, d)| {
let step = CandidateStep {
self_ty: infcx
.make_query_response_ignoring_pending_obligations(inference_vars, ty),
self_ty: infcx.make_query_response_ignoring_pending_obligations(
inference_vars,
ty,
prev_opaque_entries,
),
self_ty_is_opaque: self_ty_is_opaque(ty),
autoderefs: d,
from_unsafe_deref: reached_raw_pointer,
Expand All @@ -692,18 +703,27 @@ pub(crate) fn method_autoderef_steps<'tcx>(
let opt_bad_ty = match final_ty.kind() {
ty::Infer(ty::TyVar(_)) if !self_ty_is_opaque(final_ty) => Some(MethodAutoderefBadTy {
reached_raw_pointer,
ty: infcx.make_query_response_ignoring_pending_obligations(inference_vars, final_ty),
ty: infcx.make_query_response_ignoring_pending_obligations(
inference_vars,
final_ty,
prev_opaque_entries,
),
}),
ty::Error(_) => Some(MethodAutoderefBadTy {
reached_raw_pointer,
ty: infcx.make_query_response_ignoring_pending_obligations(inference_vars, final_ty),
ty: infcx.make_query_response_ignoring_pending_obligations(
inference_vars,
final_ty,
prev_opaque_entries,
),
}),
ty::Array(elem_ty, _) => {
let autoderefs = steps.iter().filter(|s| s.reachable_via_deref).count() - 1;
steps.push(CandidateStep {
self_ty: infcx.make_query_response_ignoring_pending_obligations(
inference_vars,
Ty::new_slice(infcx.tcx, *elem_ty),
prev_opaque_entries,
),
self_ty_is_opaque: false,
autoderefs,
Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_infer/src/infer/canonical/query_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ use crate::infer::canonical::{
};
use crate::infer::region_constraints::RegionConstraintData;
use crate::infer::{
DefineOpaqueTypes, InferCtxt, InferOk, InferResult, SubregionOrigin, TypeOutlivesConstraint,
DefineOpaqueTypes, InferCtxt, InferOk, InferResult, OpaqueTypeStorageEntries, SubregionOrigin,
TypeOutlivesConstraint,
};
use crate::traits::query::NoSolution;
use crate::traits::{ObligationCause, PredicateObligations, ScrubbedTraitError, TraitEngine};
Expand Down Expand Up @@ -81,6 +82,7 @@ impl<'tcx> InferCtxt<'tcx> {
&self,
inference_vars: CanonicalVarValues<'tcx>,
answer: T,
prev_entries: OpaqueTypeStorageEntries,
) -> Canonical<'tcx, QueryResponse<'tcx, T>>
where
T: Debug + TypeFoldable<TyCtxt<'tcx>>,
Expand All @@ -96,7 +98,7 @@ impl<'tcx> InferCtxt<'tcx> {
self.inner
.borrow_mut()
.opaque_type_storage
.iter_opaque_types()
.opaque_types_added_since(prev_entries)
.map(|(k, v)| (k, v.ty))
.collect()
} else {
Expand Down
39 changes: 18 additions & 21 deletions compiler/rustc_query_impl/src/plumbing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ use rustc_span::def_id::LOCAL_CRATE;

use crate::QueryConfigRestored;

/// Implements [`QueryContext`] for use by [`rustc_query_system`], since that
/// crate does not have direct access to [`TyCtxt`].
#[derive(Copy, Clone)]
pub struct QueryCtxt<'tcx> {
pub tcx: TyCtxt<'tcx>,
Expand All @@ -47,15 +49,6 @@ impl<'tcx> QueryCtxt<'tcx> {
}
}

impl<'tcx> std::ops::Deref for QueryCtxt<'tcx> {
type Target = TyCtxt<'tcx>;

#[inline]
fn deref(&self) -> &Self::Target {
&self.tcx
}
}

impl<'tcx> HasDepContext for QueryCtxt<'tcx> {
type Deps = rustc_middle::dep_graph::DepsType;
type DepContext = TyCtxt<'tcx>;
Expand All @@ -69,14 +62,16 @@ impl<'tcx> HasDepContext for QueryCtxt<'tcx> {
impl QueryContext for QueryCtxt<'_> {
#[inline]
fn jobserver_proxy(&self) -> &Proxy {
&*self.jobserver_proxy
&self.tcx.jobserver_proxy
}

#[inline]
fn next_job_id(self) -> QueryJobId {
QueryJobId(
NonZero::new(self.query_system.jobs.fetch_add(1, std::sync::atomic::Ordering::Relaxed))
.unwrap(),
NonZero::new(
self.tcx.query_system.jobs.fetch_add(1, std::sync::atomic::Ordering::Relaxed),
)
.unwrap(),
)
}

Expand Down Expand Up @@ -113,7 +108,8 @@ impl QueryContext for QueryCtxt<'_> {
self,
prev_dep_node_index: SerializedDepNodeIndex,
) -> Option<QuerySideEffect> {
self.query_system
self.tcx
.query_system
.on_disk_cache
.as_ref()
.and_then(|c| c.load_side_effect(self.tcx, prev_dep_node_index))
Expand All @@ -122,7 +118,7 @@ impl QueryContext for QueryCtxt<'_> {
#[inline(never)]
#[cold]
fn store_side_effect(self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect) {
if let Some(c) = self.query_system.on_disk_cache.as_ref() {
if let Some(c) = self.tcx.query_system.on_disk_cache.as_ref() {
c.store_side_effect(dep_node_index, side_effect)
}
}
Expand All @@ -140,7 +136,9 @@ impl QueryContext for QueryCtxt<'_> {
// as `self`, so we use `with_related_context` to relate the 'tcx lifetimes
// when accessing the `ImplicitCtxt`.
tls::with_related_context(self.tcx, move |current_icx| {
if depth_limit && !self.recursion_limit().value_within_limit(current_icx.query_depth) {
if depth_limit
&& !self.tcx.recursion_limit().value_within_limit(current_icx.query_depth)
{
self.depth_limit_error(token);
}

Expand All @@ -161,16 +159,16 @@ impl QueryContext for QueryCtxt<'_> {
let query_map = self.collect_active_jobs(true).expect("failed to collect active queries");
let (info, depth) = job.find_dep_kind_root(query_map);

let suggested_limit = match self.recursion_limit() {
let suggested_limit = match self.tcx.recursion_limit() {
Limit(0) => Limit(2),
limit => limit * 2,
};

self.sess.dcx().emit_fatal(QueryOverflow {
self.tcx.sess.dcx().emit_fatal(QueryOverflow {
span: info.job.span,
note: QueryOverflowNote { desc: info.query.description, depth },
suggested_limit,
crate_name: self.crate_name(LOCAL_CRATE),
crate_name: self.tcx.crate_name(LOCAL_CRATE),
});
}
}
Expand Down Expand Up @@ -367,7 +365,7 @@ pub(crate) fn encode_query_results<'a, 'tcx, Q>(
Q: super::QueryConfigRestored<'tcx>,
Q::RestoredValue: Encodable<CacheEncoder<'a, 'tcx>>,
{
let _timer = qcx.profiler().generic_activity_with_arg("encode_query_results_for", query.name());
let _timer = qcx.tcx.prof.generic_activity_with_arg("encode_query_results_for", query.name());

assert!(query.query_state(qcx).all_inactive());
let cache = query.query_cache(qcx);
Expand All @@ -389,8 +387,7 @@ pub(crate) fn query_key_hash_verify<'tcx>(
query: impl QueryConfig<QueryCtxt<'tcx>>,
qcx: QueryCtxt<'tcx>,
) {
let _timer =
qcx.profiler().generic_activity_with_arg("query_key_hash_verify_for", query.name());
let _timer = qcx.tcx.prof.generic_activity_with_arg("query_key_hash_verify_for", query.name());

let mut map = UnordMap::default();

Expand Down
40 changes: 38 additions & 2 deletions library/core/src/hint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@ pub const fn must_use<T>(value: T) -> T {
/// }
/// }
/// ```
#[unstable(feature = "likely_unlikely", issue = "136873")]
#[unstable(feature = "likely_unlikely", issue = "151619")]
#[inline(always)]
pub const fn likely(b: bool) -> bool {
crate::intrinsics::likely(b)
Expand Down Expand Up @@ -708,7 +708,7 @@ pub const fn likely(b: bool) -> bool {
/// }
/// }
/// ```
#[unstable(feature = "likely_unlikely", issue = "136873")]
#[unstable(feature = "likely_unlikely", issue = "151619")]
#[inline(always)]
pub const fn unlikely(b: bool) -> bool {
crate::intrinsics::unlikely(b)
Expand All @@ -717,6 +717,10 @@ pub const fn unlikely(b: bool) -> bool {
/// Hints to the compiler that given path is cold, i.e., unlikely to be taken. The compiler may
/// choose to optimize paths that are not cold at the expense of paths that are cold.
///
/// Note that like all hints, the exact effect to codegen is not guaranteed. Using `cold_path`
/// can actually *decrease* performance if the branch is called more than expected. It is advisable
/// to perform benchmarks to tell if this function is useful.
///
/// # Examples
///
/// ```
Expand All @@ -741,6 +745,38 @@ pub const fn unlikely(b: bool) -> bool {
/// }
/// }
/// ```
///
/// This can also be used to implement `likely` and `unlikely` helpers to hint the condition rather
/// than the branch:
///
/// ```
/// #![feature(cold_path)]
/// use core::hint::cold_path;
///
/// #[inline(always)]
/// pub const fn likely(b: bool) -> bool {
/// if !b {
/// cold_path();
/// }
/// b
/// }
///
/// #[inline(always)]
/// pub const fn unlikely(b: bool) -> bool {
/// if b {
/// cold_path();
/// }
/// b
/// }
///
/// fn foo(x: i32) {
/// if likely(x > 0) {
/// println!("this branch is likely to be taken");
/// } else {
/// println!("this branch is unlikely to be taken");
/// }
/// }
/// ```
#[unstable(feature = "cold_path", issue = "136873")]
#[inline(always)]
pub const fn cold_path() {
Expand Down
19 changes: 15 additions & 4 deletions src/tools/compiletest/src/directives/auxiliary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ pub struct AuxCrate {
pub path: String,
}

/// The value of a `proc-macro` directive.
#[derive(Clone, Debug, Default)]
pub(crate) struct ProcMacro {
/// With `proc-macro: bar.rs` this will be `bar.rs`.
pub path: String,
}

/// Properties parsed from `aux-*` test directives.
#[derive(Clone, Debug, Default)]
pub(crate) struct AuxProps {
Expand All @@ -37,7 +44,7 @@ pub(crate) struct AuxProps {
/// to build and pass with the `--extern` flag.
pub(crate) crates: Vec<AuxCrate>,
/// Same as `builds`, but for proc-macros.
pub(crate) proc_macros: Vec<String>,
pub(crate) proc_macros: Vec<ProcMacro>,
/// Similar to `builds`, but also uses the resulting dylib as a
/// `-Zcodegen-backend` when compiling the test file.
pub(crate) codegen_backend: Option<String>,
Expand All @@ -53,7 +60,7 @@ impl AuxProps {
.chain(builds.iter().map(String::as_str))
.chain(bins.iter().map(String::as_str))
.chain(crates.iter().map(|c| c.path.as_str()))
.chain(proc_macros.iter().map(String::as_str))
.chain(proc_macros.iter().map(|p| p.path.as_str()))
.chain(codegen_backend.iter().map(String::as_str))
}
}
Expand All @@ -74,8 +81,8 @@ pub(super) fn parse_and_update_aux(
config.push_name_value_directive(ln, AUX_BUILD, &mut aux.builds, |r| r.trim().to_string());
config.push_name_value_directive(ln, AUX_BIN, &mut aux.bins, |r| r.trim().to_string());
config.push_name_value_directive(ln, AUX_CRATE, &mut aux.crates, parse_aux_crate);
config
.push_name_value_directive(ln, PROC_MACRO, &mut aux.proc_macros, |r| r.trim().to_string());
config.push_name_value_directive(ln, PROC_MACRO, &mut aux.proc_macros, parse_proc_macro);

if let Some(r) = config.parse_name_value_directive(ln, AUX_CODEGEN_BACKEND) {
aux.codegen_backend = Some(r.trim().to_owned());
}
Expand All @@ -99,3 +106,7 @@ fn parse_aux_crate(r: String) -> AuxCrate {

AuxCrate { extern_modifiers: modifiers, name, path }
}

fn parse_proc_macro(r: String) -> ProcMacro {
ProcMacro { path: r.trim().to_string() }
}
6 changes: 3 additions & 3 deletions src/tools/compiletest/src/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1298,13 +1298,13 @@ impl<'test> TestCx<'test> {
}

for proc_macro in &self.props.aux.proc_macros {
self.build_auxiliary(proc_macro, &aux_dir, Some(AuxType::ProcMacro));
let crate_name = path_to_crate_name(proc_macro);
self.build_auxiliary(&proc_macro.path, &aux_dir, Some(AuxType::ProcMacro));
let crate_name = path_to_crate_name(&proc_macro.path);
add_extern(
rustc,
None, // `extern_modifiers`
&crate_name,
proc_macro,
&proc_macro.path,
AuxType::ProcMacro,
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//@ compile-flags: -Znext-solver

// Regression test for trait-system-refactor-initiative/issues/263
// Previously `method_auto_deref_steps` would also return opaque
// types which have already been defined in the parent context.
//
// We then handled these opaque types by emitting `AliasRelate` goals
// when instantiating its result, assuming that operation to be infallible.
// By returning opaque type constraints from the parent context and
// constraining the hidden type without reproving the item bounds of
// the opaque, this ended up causing ICE.

use std::ops::Deref;
trait Trait {}
struct Inv<T>(*mut T);
impl Trait for i32 {}
impl Deref for Inv<u32> {
type Target = u32;
fn deref(&self) -> &Self::Target {
todo!()
}
}

fn mk<T>() -> T { todo!() }
fn foo() -> Inv<impl Trait> {
//~^ ERROR: the trait bound `u32: Trait` is not satisfied [E0277]
let mut x: Inv<_> = mk();
if false {
return x;
//~^ ERROR: the trait bound `u32: Trait` is not satisfied [E0277]
}

x.count_ones();
x
//~^ ERROR: mismatched types [E0308]
}

fn main() {}
Loading
Loading