Skip to content

Commit

Permalink
Auto merge of rust-lang#110311 - matthiaskrgr:rollup-kn2k5bq, r=matth…
Browse files Browse the repository at this point in the history
…iaskrgr

Rollup of 9 pull requests

Successful merges:

 - rust-lang#109225 (Clarify that RUST_MIN_STACK may be internally cached)
 - rust-lang#109800 (Improve safe transmute error reporting)
 - rust-lang#110158 (Remove obsolete test case)
 - rust-lang#110180 (don't uniquify regions when canonicalizing)
 - rust-lang#110207 (Assemble `Unpin` candidates specially for generators in new solver)
 - rust-lang#110276 (Remove all but one of the spans in `BoundRegionKind::BrAnon`)
 - rust-lang#110279 (rustdoc: Correctly handle built-in compiler proc-macros as proc-macro and not macro)
 - rust-lang#110298 (Cover edge cases for {f32, f64}.hypot() docs)
 - rust-lang#110299 (Switch to `EarlyBinder` for `impl_subject` query)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Apr 14, 2023
2 parents edcbb29 + 610bc68 commit 71ef9ec
Show file tree
Hide file tree
Showing 52 changed files with 758 additions and 1,090 deletions.
25 changes: 10 additions & 15 deletions compiler/rustc_hir_typeck/src/generator_interior/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,7 @@ pub fn resolve_interior<'a, 'tcx>(
// typeck had previously found constraints that would cause them to be related.

let mut counter = 0;
let mut mk_bound_region = |span| {
let kind = ty::BrAnon(span);
let mut mk_bound_region = |kind| {
let var = ty::BoundVar::from_u32(counter);
counter += 1;
ty::BoundRegion { var, kind }
Expand All @@ -252,24 +251,23 @@ pub fn resolve_interior<'a, 'tcx>(
let origin = fcx.region_var_origin(vid);
match origin {
RegionVariableOrigin::EarlyBoundRegion(span, _) => {
mk_bound_region(Some(span))
mk_bound_region(ty::BrAnon(Some(span)))
}
_ => mk_bound_region(None),
_ => mk_bound_region(ty::BrAnon(None)),
}
}
// FIXME: these should use `BrNamed`
ty::ReEarlyBound(region) => {
mk_bound_region(Some(fcx.tcx.def_span(region.def_id)))
mk_bound_region(ty::BrNamed(region.def_id, region.name))
}
ty::ReLateBound(_, ty::BoundRegion { kind, .. })
| ty::ReFree(ty::FreeRegion { bound_region: kind, .. }) => match kind {
ty::BoundRegionKind::BrAnon(span) => mk_bound_region(span),
ty::BoundRegionKind::BrNamed(def_id, _) => {
mk_bound_region(Some(fcx.tcx.def_span(def_id)))
ty::BoundRegionKind::BrAnon(span) => mk_bound_region(ty::BrAnon(span)),
ty::BoundRegionKind::BrNamed(def_id, sym) => {
mk_bound_region(ty::BrNamed(def_id, sym))
}
ty::BoundRegionKind::BrEnv => mk_bound_region(None),
ty::BoundRegionKind::BrEnv => mk_bound_region(ty::BrAnon(None)),
},
_ => mk_bound_region(None),
_ => mk_bound_region(ty::BrAnon(None)),
};
let r = fcx.tcx.mk_re_late_bound(current_depth, br);
r
Expand All @@ -293,10 +291,7 @@ pub fn resolve_interior<'a, 'tcx>(
type_causes,
FnMutDelegate {
regions: &mut |br| {
let kind = match br.kind {
ty::BrAnon(span) => ty::BrAnon(span),
_ => br.kind,
};
let kind = br.kind;
let var = ty::BoundVar::from_usize(bound_vars.len());
bound_vars.push(ty::BoundVariableKind::Region(kind));
counter += 1;
Expand Down
12 changes: 6 additions & 6 deletions compiler/rustc_middle/src/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pub mod nested_filter;
pub mod place;

use crate::ty::query::Providers;
use crate::ty::{ImplSubject, TyCtxt};
use crate::ty::{EarlyBinder, ImplSubject, TyCtxt};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
use rustc_hir::def_id::{DefId, LocalDefId};
Expand Down Expand Up @@ -104,11 +104,11 @@ impl<'tcx> TyCtxt<'tcx> {
self.parent_module_from_def_id(id.owner.def_id)
}

pub fn impl_subject(self, def_id: DefId) -> ImplSubject<'tcx> {
self.impl_trait_ref(def_id)
.map(|t| t.subst_identity())
.map(ImplSubject::Trait)
.unwrap_or_else(|| ImplSubject::Inherent(self.type_of(def_id).subst_identity()))
pub fn impl_subject(self, def_id: DefId) -> EarlyBinder<ImplSubject<'tcx>> {
match self.impl_trait_ref(def_id) {
Some(t) => t.map_bound(ImplSubject::Trait),
None => self.type_of(def_id).map_bound(ImplSubject::Inherent),
}
}
}

Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_middle/src/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -708,10 +708,6 @@ impl<'tcx> TyCtxt<'tcx> {
ty::EarlyBinder(self.explicit_item_bounds(def_id))
}

pub fn bound_impl_subject(self, def_id: DefId) -> ty::EarlyBinder<ty::ImplSubject<'tcx>> {
ty::EarlyBinder(self.impl_subject(def_id))
}

/// Returns names of captured upvars for closures and generators.
///
/// Here are some examples:
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_trait_selection/src/solve/assembly/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,14 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
) {
let lang_items = self.tcx().lang_items();
let trait_def_id = goal.predicate.trait_def_id(self.tcx());

// N.B. When assembling built-in candidates for lang items that are also
// `auto` traits, then the auto trait candidate that is assembled in
// `consider_auto_trait_candidate` MUST be disqualified to remain sound.
//
// Instead of adding the logic here, it's a better idea to add it in
// `EvalCtxt::disqualify_auto_trait_candidate_due_to_possible_impl` in
// `solve::trait_goals` instead.
let result = if self.tcx().trait_is_auto(trait_def_id) {
G::consider_auto_trait_candidate(self, goal)
} else if self.tcx().trait_is_alias(trait_def_id) {
Expand Down
25 changes: 11 additions & 14 deletions compiler/rustc_trait_selection/src/solve/canonicalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,9 @@ impl<'a, 'tcx> Canonicalizer<'a, 'tcx> {
// - var_infos: [E0, U1, E1, U1, E1, E6, U6], curr_compressed_uv: 1, next_orig_uv: 6
// - var_infos: [E0, U1, E1, U1, E1, E2, U2], curr_compressed_uv: 2, next_orig_uv: -
//
// This algorithm runs in `O(n²)` where `n` is the number of different universe
// indices in the input. This should be fine as `n` is expected to be small.
// This algorithm runs in `O(nm)` where `n` is the number of different universe
// indices in the input and `m` is the number of canonical variables.
// This should be fine as both `n` and `m` are expected to be small.
let mut curr_compressed_uv = ty::UniverseIndex::ROOT;
let mut existential_in_new_uv = false;
let mut next_orig_uv = Some(ty::UniverseIndex::ROOT);
Expand Down Expand Up @@ -245,18 +246,14 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
ty::ReError(_) => return r,
};

let existing_bound_var = match self.canonicalize_mode {
CanonicalizeMode::Input => None,
CanonicalizeMode::Response { .. } => {
self.variables.iter().position(|&v| v == r.into()).map(ty::BoundVar::from)
}
};
let var = existing_bound_var.unwrap_or_else(|| {
let var = ty::BoundVar::from(self.variables.len());
self.variables.push(r.into());
self.primitive_var_infos.push(CanonicalVarInfo { kind });
var
});
let var = ty::BoundVar::from(
self.variables.iter().position(|&v| v == r.into()).unwrap_or_else(|| {
let var = self.variables.len();
self.variables.push(r.into());
self.primitive_var_infos.push(CanonicalVarInfo { kind });
var
}),
);
let br = ty::BoundRegion { var, kind: BrAnon(None) };
self.interner().mk_re_late_bound(self.binder_index, br)
}
Expand Down
155 changes: 94 additions & 61 deletions compiler/rustc_trait_selection/src/solve/trait_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use super::assembly::{self, structural_traits};
use super::{EvalCtxt, SolverMode};
use rustc_hir::def_id::DefId;
use rustc_hir::LangItem;
use rustc_hir::{LangItem, Movability};
use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::util::supertraits;
use rustc_middle::traits::solve::{CanonicalResponse, Certainty, Goal, QueryResult};
Expand Down Expand Up @@ -147,66 +147,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx> {
let self_ty = goal.predicate.self_ty();
match *self_ty.kind() {
// Stall int and float vars until they are resolved to a concrete
// numerical type. That's because the check for impls below treats
// int vars as matching any impl. Even if we filtered such impls,
// we probably don't want to treat an `impl !AutoTrait for i32` as
// disqualifying the built-in auto impl for `i64: AutoTrait` either.
ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
}

// These types cannot be structurally decomposed into constitutent
// types, and therefore have no builtin impl.
ty::Dynamic(..)
| ty::Param(..)
| ty::Foreign(..)
| ty::Alias(ty::Projection, ..)
| ty::Placeholder(..) => return Err(NoSolution),

ty::Infer(_) | ty::Bound(_, _) => bug!("unexpected type `{self_ty}`"),

// For rigid types, we only register a builtin auto implementation
// if there is no implementation that could ever apply to the self
// type.
//
// This differs from the current stable behavior and fixes #84857.
// Due to breakage found via crater, we currently instead lint
// patterns which can be used to exploit this unsoundness on stable,
// see #93367 for more details.
ty::Bool
| ty::Char
| ty::Int(_)
| ty::Uint(_)
| ty::Float(_)
| ty::Str
| ty::Array(_, _)
| ty::Slice(_)
| ty::RawPtr(_)
| ty::Ref(_, _, _)
| ty::FnDef(_, _)
| ty::FnPtr(_)
| ty::Closure(_, _)
| ty::Generator(_, _, _)
| ty::GeneratorWitness(_)
| ty::GeneratorWitnessMIR(_, _)
| ty::Never
| ty::Tuple(_)
| ty::Error(_)
| ty::Adt(_, _)
| ty::Alias(ty::Opaque, _) => {
if let Some(def_id) = ecx.tcx().find_map_relevant_impl(
goal.predicate.def_id(),
goal.predicate.self_ty(),
TreatProjections::NextSolverLookup,
Some,
) {
debug!(?def_id, ?goal, "disqualified auto-trait implementation");
return Err(NoSolution);
}
}
if let Some(result) = ecx.disqualify_auto_trait_candidate_due_to_possible_impl(goal) {
return result;
}

ecx.probe_and_evaluate_goal_for_constituent_tys(
Expand Down Expand Up @@ -630,6 +572,97 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
}

impl<'tcx> EvalCtxt<'_, 'tcx> {
// Return `Some` if there is an impl (built-in or user provided) that may
// hold for the self type of the goal, which for coherence and soundness
// purposes must disqualify the built-in auto impl assembled by considering
// the type's constituent types.
fn disqualify_auto_trait_candidate_due_to_possible_impl(
&mut self,
goal: Goal<'tcx, TraitPredicate<'tcx>>,
) -> Option<QueryResult<'tcx>> {
let self_ty = goal.predicate.self_ty();
match *self_ty.kind() {
// Stall int and float vars until they are resolved to a concrete
// numerical type. That's because the check for impls below treats
// int vars as matching any impl. Even if we filtered such impls,
// we probably don't want to treat an `impl !AutoTrait for i32` as
// disqualifying the built-in auto impl for `i64: AutoTrait` either.
ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
Some(self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS))
}

// These types cannot be structurally decomposed into constitutent
// types, and therefore have no built-in auto impl.
ty::Dynamic(..)
| ty::Param(..)
| ty::Foreign(..)
| ty::Alias(ty::Projection, ..)
| ty::Placeholder(..) => Some(Err(NoSolution)),

ty::Infer(_) | ty::Bound(_, _) => bug!("unexpected type `{self_ty}`"),

// Generators have one special built-in candidate, `Unpin`, which
// takes precedence over the structural auto trait candidate being
// assembled.
ty::Generator(_, _, movability)
if Some(goal.predicate.def_id()) == self.tcx().lang_items().unpin_trait() =>
{
match movability {
Movability::Static => Some(Err(NoSolution)),
Movability::Movable => {
Some(self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
}
}
}

// For rigid types, any possible implementation that could apply to
// the type (even if after unification and processing nested goals
// it does not hold) will disqualify the built-in auto impl.
//
// This differs from the current stable behavior and fixes #84857.
// Due to breakage found via crater, we currently instead lint
// patterns which can be used to exploit this unsoundness on stable,
// see #93367 for more details.
ty::Bool
| ty::Char
| ty::Int(_)
| ty::Uint(_)
| ty::Float(_)
| ty::Str
| ty::Array(_, _)
| ty::Slice(_)
| ty::RawPtr(_)
| ty::Ref(_, _, _)
| ty::FnDef(_, _)
| ty::FnPtr(_)
| ty::Closure(_, _)
| ty::Generator(_, _, _)
| ty::GeneratorWitness(_)
| ty::GeneratorWitnessMIR(_, _)
| ty::Never
| ty::Tuple(_)
| ty::Adt(_, _)
// FIXME: Handling opaques here is kinda sus. Especially because we
// simplify them to PlaceholderSimplifiedType.
| ty::Alias(ty::Opaque, _) => {
if let Some(def_id) = self.tcx().find_map_relevant_impl(
goal.predicate.def_id(),
goal.predicate.self_ty(),
TreatProjections::NextSolverLookup,
Some,
) {
debug!(?def_id, ?goal, "disqualified auto-trait implementation");
// No need to actually consider the candidate here,
// since we do that in `consider_impl_candidate`.
return Some(Err(NoSolution));
} else {
None
}
}
ty::Error(_) => None,
}
}

/// Convenience function for traits that are structural, i.e. that only
/// have nested subgoals that only change the self type. Unlike other
/// evaluate-like helpers, this does a probe, so it doesn't need to be
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/traits/coherence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ fn negative_impl(tcx: TyCtxt<'_>, impl1_def_id: DefId, impl2_def_id: DefId) -> b
&infcx,
ObligationCause::dummy(),
impl_env,
tcx.impl_subject(impl1_def_id),
tcx.impl_subject(impl1_def_id).subst_identity(),
) {
Ok(s) => s,
Err(err) => {
Expand Down
Loading

0 comments on commit 71ef9ec

Please sign in to comment.