Skip to content

Commit

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

Rollup of 9 pull requests

Successful merges:

 - rust-lang#124840 (resolve: mark it undetermined if single import is not has any bindings)
 - rust-lang#125622 (Winnow private method candidates instead of assuming any candidate of the right name will apply)
 - rust-lang#125648 (Remove unused(?) `~/rustsrc` folder from docker script)
 - rust-lang#125672 (Add more ABI test cases to miri (RFC 3391))
 - rust-lang#125800 (Fix `mut` static task queue in SGX target)
 - rust-lang#125871 (Orphanck[old solver]: Consider opaque types to never cover type parameters)
 - rust-lang#125893 (Handle all GVN binops in a single place.)
 - rust-lang#126008 (Port `tests/run-make-fulldeps/issue-19371` to ui-fulldeps)
 - rust-lang#126032 (Update description of the `IsTerminal` example)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jun 5, 2024
2 parents 7ebd2bd + fa58891 commit 72fdf91
Show file tree
Hide file tree
Showing 37 changed files with 455 additions and 190 deletions.
31 changes: 22 additions & 9 deletions compiler/rustc_const_eval/src/interpret/terminator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,17 +294,30 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {

/// Unwrap types that are guaranteed a null-pointer-optimization
fn unfold_npo(&self, layout: TyAndLayout<'tcx>) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
// Check if this is `Option` wrapping some type.
let inner = match layout.ty.kind() {
ty::Adt(def, args) if self.tcx.is_diagnostic_item(sym::Option, def.did()) => {
args[0].as_type().unwrap()
}
_ => {
// Not an `Option`.
return Ok(layout);
// Check if this is `Option` wrapping some type or if this is `Result` wrapping a 1-ZST and
// another type.
let ty::Adt(def, args) = layout.ty.kind() else {
// Not an ADT, so definitely no NPO.
return Ok(layout);
};
let inner = if self.tcx.is_diagnostic_item(sym::Option, def.did()) {
// The wrapped type is the only arg.
self.layout_of(args[0].as_type().unwrap())?
} else if self.tcx.is_diagnostic_item(sym::Result, def.did()) {
// We want to extract which (if any) of the args is not a 1-ZST.
let lhs = self.layout_of(args[0].as_type().unwrap())?;
let rhs = self.layout_of(args[1].as_type().unwrap())?;
if lhs.is_1zst() {
rhs
} else if rhs.is_1zst() {
lhs
} else {
return Ok(layout); // no NPO
}
} else {
return Ok(layout); // no NPO
};
let inner = self.layout_of(inner)?;

// Check if the inner type is one of the NPO-guaranteed ones.
// For that we first unpeel transparent *structs* (but not unions).
let is_npo = |def: AdtDef<'tcx>| {
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1066,7 +1066,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty::ImplContainer => {
if segments.len() == 1 {
// `<T>::assoc` will end up here, and so
// can `T::assoc`. It this came from an
// can `T::assoc`. If this came from an
// inherent impl, we need to record the
// `T` for posterity (see `UserSelfTy` for
// details).
Expand Down Expand Up @@ -1416,11 +1416,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) {
Ok(ok) => self.register_infer_ok_obligations(ok),
Err(_) => {
self.dcx().span_delayed_bug(
self.dcx().span_bug(
span,
format!(
"instantiate_value_path: (UFCS) {self_ty:?} was a subtype of {impl_ty:?} but now is not?",
),
"instantiate_value_path: (UFCS) {self_ty:?} was a subtype of {impl_ty:?} but now is not?",
),
);
}
}
Expand Down
28 changes: 21 additions & 7 deletions compiler/rustc_hir_typeck/src/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ use rustc_trait_selection::traits::query::method_autoderef::{
use rustc_trait_selection::traits::query::CanonicalTyGoal;
use rustc_trait_selection::traits::ObligationCtxt;
use rustc_trait_selection::traits::{self, ObligationCause};
use std::cell::Cell;
use std::cell::RefCell;
use std::cmp::max;
use std::iter;
Expand Down Expand Up @@ -76,8 +77,12 @@ pub(crate) struct ProbeContext<'a, 'tcx> {
/// requested name (by edit distance)
allow_similar_names: bool,

/// List of potential private candidates. Will be trimmed to ones that
/// actually apply and then the result inserted into `private_candidate`
private_candidates: Vec<Candidate<'tcx>>,

/// Some(candidate) if there is a private candidate
private_candidate: Option<(DefKind, DefId)>,
private_candidate: Cell<Option<(DefKind, DefId)>>,

/// Collects near misses when the candidate functions are missing a `self` keyword and is only
/// used for error reporting
Expand Down Expand Up @@ -581,7 +586,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
orig_steps_var_values,
steps,
allow_similar_names: false,
private_candidate: None,
private_candidates: Vec::new(),
private_candidate: Cell::new(None),
static_candidates: RefCell::new(Vec::new()),
unsatisfied_predicates: RefCell::new(Vec::new()),
scope_expr_id,
Expand All @@ -593,7 +599,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
self.inherent_candidates.clear();
self.extension_candidates.clear();
self.impl_dups.clear();
self.private_candidate = None;
self.private_candidates.clear();
self.private_candidate.set(None);
self.static_candidates.borrow_mut().clear();
self.unsatisfied_predicates.borrow_mut().clear();
}
Expand All @@ -617,9 +624,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
} else {
self.extension_candidates.push(candidate);
}
} else if self.private_candidate.is_none() {
self.private_candidate =
Some((candidate.item.kind.as_def_kind(), candidate.item.def_id));
} else {
self.private_candidates.push(candidate);
}
}

Expand Down Expand Up @@ -1171,7 +1177,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
let mut possibly_unsatisfied_predicates = Vec::new();

for (kind, candidates) in
&[("inherent", &self.inherent_candidates), ("extension", &self.extension_candidates)]
[("inherent", &self.inherent_candidates), ("extension", &self.extension_candidates)]
{
debug!("searching {} candidates", kind);
let res = self.consider_candidates(
Expand All @@ -1185,6 +1191,14 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
}
}

if self.private_candidate.get().is_none() {
if let Some(Ok(pick)) =
self.consider_candidates(self_ty, &self.private_candidates, &mut vec![], None)
{
self.private_candidate.set(Some((pick.item.kind.as_def_kind(), pick.item.def_id)));
}
}

// `pick_method` may be called twice for the same self_ty if no stable methods
// match. Only extend once.
if unstable_candidates.is_some() {
Expand Down
70 changes: 40 additions & 30 deletions compiler/rustc_mir_transform/src/gvn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,6 @@ enum Value<'tcx> {
NullaryOp(NullOp<'tcx>, Ty<'tcx>),
UnaryOp(UnOp, VnIndex),
BinaryOp(BinOp, VnIndex, VnIndex),
CheckedBinaryOp(BinOp, VnIndex, VnIndex), // FIXME get rid of this, work like MIR instead
Cast {
kind: CastKind,
value: VnIndex,
Expand Down Expand Up @@ -508,17 +507,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
let val = self.ecx.binary_op(bin_op, &lhs, &rhs).ok()?;
val.into()
}
CheckedBinaryOp(bin_op, lhs, rhs) => {
let lhs = self.evaluated[lhs].as_ref()?;
let lhs = self.ecx.read_immediate(lhs).ok()?;
let rhs = self.evaluated[rhs].as_ref()?;
let rhs = self.ecx.read_immediate(rhs).ok()?;
let val = self
.ecx
.binary_op(bin_op.wrapping_to_overflowing().unwrap(), &lhs, &rhs)
.ok()?;
val.into()
}
Cast { kind, value, from: _, to } => match kind {
CastKind::IntToInt | CastKind::IntToFloat => {
let value = self.evaluated[value].as_ref()?;
Expand Down Expand Up @@ -829,17 +817,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
let lhs = lhs?;
let rhs = rhs?;

if let Some(op) = op.overflowing_to_wrapping() {
if let Some(value) = self.simplify_binary(op, true, ty, lhs, rhs) {
return Some(value);
}
Value::CheckedBinaryOp(op, lhs, rhs)
} else {
if let Some(value) = self.simplify_binary(op, false, ty, lhs, rhs) {
return Some(value);
}
Value::BinaryOp(op, lhs, rhs)
if let Some(value) = self.simplify_binary(op, ty, lhs, rhs) {
return Some(value);
}
Value::BinaryOp(op, lhs, rhs)
}
Rvalue::UnaryOp(op, ref mut arg) => {
let arg = self.simplify_operand(arg, location)?;
Expand Down Expand Up @@ -970,7 +951,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
fn simplify_binary(
&mut self,
op: BinOp,
checked: bool,
lhs_ty: Ty<'tcx>,
lhs: VnIndex,
rhs: VnIndex,
Expand Down Expand Up @@ -999,22 +979,39 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
use Either::{Left, Right};
let a = as_bits(lhs).map_or(Right(lhs), Left);
let b = as_bits(rhs).map_or(Right(rhs), Left);

let result = match (op, a, b) {
// Neutral elements.
(BinOp::Add | BinOp::BitOr | BinOp::BitXor, Left(0), Right(p))
(
BinOp::Add
| BinOp::AddWithOverflow
| BinOp::AddUnchecked
| BinOp::BitOr
| BinOp::BitXor,
Left(0),
Right(p),
)
| (
BinOp::Add
| BinOp::AddWithOverflow
| BinOp::AddUnchecked
| BinOp::BitOr
| BinOp::BitXor
| BinOp::Sub
| BinOp::SubWithOverflow
| BinOp::SubUnchecked
| BinOp::Offset
| BinOp::Shl
| BinOp::Shr,
Right(p),
Left(0),
)
| (BinOp::Mul, Left(1), Right(p))
| (BinOp::Mul | BinOp::Div, Right(p), Left(1)) => p,
| (BinOp::Mul | BinOp::MulWithOverflow | BinOp::MulUnchecked, Left(1), Right(p))
| (
BinOp::Mul | BinOp::MulWithOverflow | BinOp::MulUnchecked | BinOp::Div,
Right(p),
Left(1),
) => p,
// Attempt to simplify `x & ALL_ONES` to `x`, with `ALL_ONES` depending on type size.
(BinOp::BitAnd, Right(p), Left(ones)) | (BinOp::BitAnd, Left(ones), Right(p))
if ones == layout.size.truncate(u128::MAX)
Expand All @@ -1023,10 +1020,21 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
p
}
// Absorbing elements.
(BinOp::Mul | BinOp::BitAnd, _, Left(0))
(
BinOp::Mul | BinOp::MulWithOverflow | BinOp::MulUnchecked | BinOp::BitAnd,
_,
Left(0),
)
| (BinOp::Rem, _, Left(1))
| (
BinOp::Mul | BinOp::Div | BinOp::Rem | BinOp::BitAnd | BinOp::Shl | BinOp::Shr,
BinOp::Mul
| BinOp::MulWithOverflow
| BinOp::MulUnchecked
| BinOp::Div
| BinOp::Rem
| BinOp::BitAnd
| BinOp::Shl
| BinOp::Shr,
Left(0),
_,
) => self.insert_scalar(Scalar::from_uint(0u128, layout.size), lhs_ty),
Expand All @@ -1038,7 +1046,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
self.insert_scalar(Scalar::from_uint(ones, layout.size), lhs_ty)
}
// Sub/Xor with itself.
(BinOp::Sub | BinOp::BitXor, a, b) if a == b => {
(BinOp::Sub | BinOp::SubWithOverflow | BinOp::SubUnchecked | BinOp::BitXor, a, b)
if a == b =>
{
self.insert_scalar(Scalar::from_uint(0u128, layout.size), lhs_ty)
}
// Comparison:
Expand All @@ -1052,7 +1062,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
_ => return None,
};

if checked {
if op.is_overflowing() {
let false_val = self.insert_bool(false);
Some(self.insert_tuple(vec![result, false_val]))
} else {
Expand Down
29 changes: 27 additions & 2 deletions compiler/rustc_resolve/src/ident.rs
Original file line number Diff line number Diff line change
Expand Up @@ -965,6 +965,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// if it can then our result is not determined and can be invalidated.
for single_import in &resolution.single_imports {
let Some(import_vis) = single_import.vis.get() else {
// This branch handles a cycle in single imports, which occurs
// when we've previously captured the `vis` value during an import
// process.
//
// For example:
// ```
// use a::b;
// use b as a;
// ```
// 1. Steal the `vis` in `use a::b` and attempt to locate `a` in the
// current module.
// 2. Encounter the import `use b as a`, which is a `single_import` for `a`,
// and try to find `b` in the current module.
// 3. Re-encounter the `use a::b` import since it's a `single_import` of `b`.
// This leads to entering this branch.
continue;
};
if !self.is_accessible_from(import_vis, parent_scope.module) {
Expand All @@ -979,15 +994,25 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// named imports.
continue;
}

let Some(module) = single_import.imported_module.get() else {
return Err((Undetermined, Weak::No));
};
let ImportKind::Single { source: ident, .. } = single_import.kind else {
let ImportKind::Single { source: ident, source_bindings, .. } = &single_import.kind
else {
unreachable!();
};
if binding.map_or(false, |binding| binding.module().is_some())
&& source_bindings.iter().all(|binding| matches!(binding.get(), Err(Undetermined)))
{
// This branch allows the binding to be defined or updated later,
// avoiding module inconsistency between the resolve process and the finalize process.
// See more details in #124840
return Err((Undetermined, Weak::No));
}
match self.resolve_ident_in_module(
module,
ident,
*ident,
ns,
&single_import.parent_scope,
None,
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_resolve/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -352,9 +352,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
(old_glob @ true, false) | (old_glob @ false, true) => {
let (glob_binding, nonglob_binding) =
if old_glob { (old_binding, binding) } else { (binding, old_binding) };
if glob_binding.res() != nonglob_binding.res()
&& key.ns == MacroNS
if key.ns == MacroNS
&& nonglob_binding.expansion != LocalExpnId::ROOT
&& glob_binding.res() != nonglob_binding.res()
{
resolution.binding = Some(this.ambiguity(
AmbiguityKind::GlobVsExpanded,
Expand Down
Loading

0 comments on commit 72fdf91

Please sign in to comment.