Auto merge of #126038 - matthiaskrgr:rollup-h4rm3x2, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #124840 (resolve: mark it undetermined if single import is not has any bindings) - #125622 (Winnow private method candidates instead of assuming any candidate of the right name will apply) - #125648 (Remove unused(?) `~/rustsrc` folder from docker script) - #125672 (Add more ABI test cases to miri (RFC 3391)) - #125800 (Fix `mut` static task queue in SGX target) - #125871 (Orphanck[old solver]: Consider opaque types to never cover type parameters) - #125893 (Handle all GVN binops in a single place.) - #126008 (Port `tests/run-make-fulldeps/issue-19371` to ui-fulldeps) - #126032 (Update description of the `IsTerminal` example) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
72fdf913c5
37 changed files with 456 additions and 191 deletions
|
@ -294,17 +294,30 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||||
|
|
||||||
/// Unwrap types that are guaranteed a null-pointer-optimization
|
/// Unwrap types that are guaranteed a null-pointer-optimization
|
||||||
fn unfold_npo(&self, layout: TyAndLayout<'tcx>) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
|
fn unfold_npo(&self, layout: TyAndLayout<'tcx>) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
|
||||||
// Check if this is `Option` wrapping some type.
|
// Check if this is `Option` wrapping some type or if this is `Result` wrapping a 1-ZST and
|
||||||
let inner = match layout.ty.kind() {
|
// another type.
|
||||||
ty::Adt(def, args) if self.tcx.is_diagnostic_item(sym::Option, def.did()) => {
|
let ty::Adt(def, args) = layout.ty.kind() else {
|
||||||
args[0].as_type().unwrap()
|
// Not an ADT, so definitely no NPO.
|
||||||
}
|
return Ok(layout);
|
||||||
_ => {
|
|
||||||
// Not an `Option`.
|
|
||||||
return Ok(layout);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
let inner = self.layout_of(inner)?;
|
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
|
||||||
|
};
|
||||||
|
|
||||||
// Check if the inner type is one of the NPO-guaranteed ones.
|
// Check if the inner type is one of the NPO-guaranteed ones.
|
||||||
// For that we first unpeel transparent *structs* (but not unions).
|
// For that we first unpeel transparent *structs* (but not unions).
|
||||||
let is_npo = |def: AdtDef<'tcx>| {
|
let is_npo = |def: AdtDef<'tcx>| {
|
||||||
|
|
|
@ -1066,7 +1066,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
ty::ImplContainer => {
|
ty::ImplContainer => {
|
||||||
if segments.len() == 1 {
|
if segments.len() == 1 {
|
||||||
// `<T>::assoc` will end up here, and so
|
// `<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
|
// inherent impl, we need to record the
|
||||||
// `T` for posterity (see `UserSelfTy` for
|
// `T` for posterity (see `UserSelfTy` for
|
||||||
// details).
|
// details).
|
||||||
|
@ -1416,11 +1416,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
) {
|
) {
|
||||||
Ok(ok) => self.register_infer_ok_obligations(ok),
|
Ok(ok) => self.register_infer_ok_obligations(ok),
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
self.dcx().span_delayed_bug(
|
self.dcx().span_bug(
|
||||||
span,
|
span,
|
||||||
format!(
|
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?",
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ use rustc_trait_selection::traits::query::method_autoderef::{
|
||||||
use rustc_trait_selection::traits::query::CanonicalTyGoal;
|
use rustc_trait_selection::traits::query::CanonicalTyGoal;
|
||||||
use rustc_trait_selection::traits::ObligationCtxt;
|
use rustc_trait_selection::traits::ObligationCtxt;
|
||||||
use rustc_trait_selection::traits::{self, ObligationCause};
|
use rustc_trait_selection::traits::{self, ObligationCause};
|
||||||
|
use std::cell::Cell;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
@ -76,8 +77,12 @@ pub(crate) struct ProbeContext<'a, 'tcx> {
|
||||||
/// requested name (by edit distance)
|
/// requested name (by edit distance)
|
||||||
allow_similar_names: bool,
|
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
|
/// 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
|
/// Collects near misses when the candidate functions are missing a `self` keyword and is only
|
||||||
/// used for error reporting
|
/// used for error reporting
|
||||||
|
@ -581,7 +586,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||||
orig_steps_var_values,
|
orig_steps_var_values,
|
||||||
steps,
|
steps,
|
||||||
allow_similar_names: false,
|
allow_similar_names: false,
|
||||||
private_candidate: None,
|
private_candidates: Vec::new(),
|
||||||
|
private_candidate: Cell::new(None),
|
||||||
static_candidates: RefCell::new(Vec::new()),
|
static_candidates: RefCell::new(Vec::new()),
|
||||||
unsatisfied_predicates: RefCell::new(Vec::new()),
|
unsatisfied_predicates: RefCell::new(Vec::new()),
|
||||||
scope_expr_id,
|
scope_expr_id,
|
||||||
|
@ -593,7 +599,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||||
self.inherent_candidates.clear();
|
self.inherent_candidates.clear();
|
||||||
self.extension_candidates.clear();
|
self.extension_candidates.clear();
|
||||||
self.impl_dups.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.static_candidates.borrow_mut().clear();
|
||||||
self.unsatisfied_predicates.borrow_mut().clear();
|
self.unsatisfied_predicates.borrow_mut().clear();
|
||||||
}
|
}
|
||||||
|
@ -617,9 +624,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||||
} else {
|
} else {
|
||||||
self.extension_candidates.push(candidate);
|
self.extension_candidates.push(candidate);
|
||||||
}
|
}
|
||||||
} else if self.private_candidate.is_none() {
|
} else {
|
||||||
self.private_candidate =
|
self.private_candidates.push(candidate);
|
||||||
Some((candidate.item.kind.as_def_kind(), candidate.item.def_id));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1171,7 +1177,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||||
let mut possibly_unsatisfied_predicates = Vec::new();
|
let mut possibly_unsatisfied_predicates = Vec::new();
|
||||||
|
|
||||||
for (kind, candidates) in
|
for (kind, candidates) in
|
||||||
&[("inherent", &self.inherent_candidates), ("extension", &self.extension_candidates)]
|
[("inherent", &self.inherent_candidates), ("extension", &self.extension_candidates)]
|
||||||
{
|
{
|
||||||
debug!("searching {} candidates", kind);
|
debug!("searching {} candidates", kind);
|
||||||
let res = self.consider_candidates(
|
let res = self.consider_candidates(
|
||||||
|
@ -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
|
// `pick_method` may be called twice for the same self_ty if no stable methods
|
||||||
// match. Only extend once.
|
// match. Only extend once.
|
||||||
if unstable_candidates.is_some() {
|
if unstable_candidates.is_some() {
|
||||||
|
|
|
@ -223,7 +223,6 @@ enum Value<'tcx> {
|
||||||
NullaryOp(NullOp<'tcx>, Ty<'tcx>),
|
NullaryOp(NullOp<'tcx>, Ty<'tcx>),
|
||||||
UnaryOp(UnOp, VnIndex),
|
UnaryOp(UnOp, VnIndex),
|
||||||
BinaryOp(BinOp, VnIndex, VnIndex),
|
BinaryOp(BinOp, VnIndex, VnIndex),
|
||||||
CheckedBinaryOp(BinOp, VnIndex, VnIndex), // FIXME get rid of this, work like MIR instead
|
|
||||||
Cast {
|
Cast {
|
||||||
kind: CastKind,
|
kind: CastKind,
|
||||||
value: VnIndex,
|
value: VnIndex,
|
||||||
|
@ -508,17 +507,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||||
let val = self.ecx.binary_op(bin_op, &lhs, &rhs).ok()?;
|
let val = self.ecx.binary_op(bin_op, &lhs, &rhs).ok()?;
|
||||||
val.into()
|
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 {
|
Cast { kind, value, from: _, to } => match kind {
|
||||||
CastKind::IntToInt | CastKind::IntToFloat => {
|
CastKind::IntToInt | CastKind::IntToFloat => {
|
||||||
let value = self.evaluated[value].as_ref()?;
|
let value = self.evaluated[value].as_ref()?;
|
||||||
|
@ -829,17 +817,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||||
let lhs = lhs?;
|
let lhs = lhs?;
|
||||||
let rhs = rhs?;
|
let rhs = rhs?;
|
||||||
|
|
||||||
if let Some(op) = op.overflowing_to_wrapping() {
|
if let Some(value) = self.simplify_binary(op, ty, lhs, rhs) {
|
||||||
if let Some(value) = self.simplify_binary(op, true, ty, lhs, rhs) {
|
return Some(value);
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
Value::BinaryOp(op, lhs, rhs)
|
||||||
}
|
}
|
||||||
Rvalue::UnaryOp(op, ref mut arg) => {
|
Rvalue::UnaryOp(op, ref mut arg) => {
|
||||||
let arg = self.simplify_operand(arg, location)?;
|
let arg = self.simplify_operand(arg, location)?;
|
||||||
|
@ -970,7 +951,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||||
fn simplify_binary(
|
fn simplify_binary(
|
||||||
&mut self,
|
&mut self,
|
||||||
op: BinOp,
|
op: BinOp,
|
||||||
checked: bool,
|
|
||||||
lhs_ty: Ty<'tcx>,
|
lhs_ty: Ty<'tcx>,
|
||||||
lhs: VnIndex,
|
lhs: VnIndex,
|
||||||
rhs: VnIndex,
|
rhs: VnIndex,
|
||||||
|
@ -999,22 +979,39 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||||
use Either::{Left, Right};
|
use Either::{Left, Right};
|
||||||
let a = as_bits(lhs).map_or(Right(lhs), Left);
|
let a = as_bits(lhs).map_or(Right(lhs), Left);
|
||||||
let b = as_bits(rhs).map_or(Right(rhs), Left);
|
let b = as_bits(rhs).map_or(Right(rhs), Left);
|
||||||
|
|
||||||
let result = match (op, a, b) {
|
let result = match (op, a, b) {
|
||||||
// Neutral elements.
|
// 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::Add
|
||||||
|
| BinOp::AddWithOverflow
|
||||||
|
| BinOp::AddUnchecked
|
||||||
| BinOp::BitOr
|
| BinOp::BitOr
|
||||||
| BinOp::BitXor
|
| BinOp::BitXor
|
||||||
| BinOp::Sub
|
| BinOp::Sub
|
||||||
|
| BinOp::SubWithOverflow
|
||||||
|
| BinOp::SubUnchecked
|
||||||
| BinOp::Offset
|
| BinOp::Offset
|
||||||
| BinOp::Shl
|
| BinOp::Shl
|
||||||
| BinOp::Shr,
|
| BinOp::Shr,
|
||||||
Right(p),
|
Right(p),
|
||||||
Left(0),
|
Left(0),
|
||||||
)
|
)
|
||||||
| (BinOp::Mul, Left(1), Right(p))
|
| (BinOp::Mul | BinOp::MulWithOverflow | BinOp::MulUnchecked, Left(1), Right(p))
|
||||||
| (BinOp::Mul | BinOp::Div, Right(p), Left(1)) => 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.
|
// 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))
|
(BinOp::BitAnd, Right(p), Left(ones)) | (BinOp::BitAnd, Left(ones), Right(p))
|
||||||
if ones == layout.size.truncate(u128::MAX)
|
if ones == layout.size.truncate(u128::MAX)
|
||||||
|
@ -1023,10 +1020,21 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||||
p
|
p
|
||||||
}
|
}
|
||||||
// Absorbing elements.
|
// Absorbing elements.
|
||||||
(BinOp::Mul | BinOp::BitAnd, _, Left(0))
|
(
|
||||||
|
BinOp::Mul | BinOp::MulWithOverflow | BinOp::MulUnchecked | BinOp::BitAnd,
|
||||||
|
_,
|
||||||
|
Left(0),
|
||||||
|
)
|
||||||
| (BinOp::Rem, _, Left(1))
|
| (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),
|
Left(0),
|
||||||
_,
|
_,
|
||||||
) => self.insert_scalar(Scalar::from_uint(0u128, layout.size), lhs_ty),
|
) => self.insert_scalar(Scalar::from_uint(0u128, layout.size), lhs_ty),
|
||||||
|
@ -1038,7 +1046,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||||
self.insert_scalar(Scalar::from_uint(ones, layout.size), lhs_ty)
|
self.insert_scalar(Scalar::from_uint(ones, layout.size), lhs_ty)
|
||||||
}
|
}
|
||||||
// Sub/Xor with itself.
|
// 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)
|
self.insert_scalar(Scalar::from_uint(0u128, layout.size), lhs_ty)
|
||||||
}
|
}
|
||||||
// Comparison:
|
// Comparison:
|
||||||
|
@ -1052,7 +1062,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
if checked {
|
if op.is_overflowing() {
|
||||||
let false_val = self.insert_bool(false);
|
let false_val = self.insert_bool(false);
|
||||||
Some(self.insert_tuple(vec![result, false_val]))
|
Some(self.insert_tuple(vec![result, false_val]))
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -965,6 +965,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||||
// if it can then our result is not determined and can be invalidated.
|
// if it can then our result is not determined and can be invalidated.
|
||||||
for single_import in &resolution.single_imports {
|
for single_import in &resolution.single_imports {
|
||||||
let Some(import_vis) = single_import.vis.get() else {
|
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;
|
continue;
|
||||||
};
|
};
|
||||||
if !self.is_accessible_from(import_vis, parent_scope.module) {
|
if !self.is_accessible_from(import_vis, parent_scope.module) {
|
||||||
|
@ -979,15 +994,25 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||||
// named imports.
|
// named imports.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(module) = single_import.imported_module.get() else {
|
let Some(module) = single_import.imported_module.get() else {
|
||||||
return Err((Undetermined, Weak::No));
|
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!();
|
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(
|
match self.resolve_ident_in_module(
|
||||||
module,
|
module,
|
||||||
ident,
|
*ident,
|
||||||
ns,
|
ns,
|
||||||
&single_import.parent_scope,
|
&single_import.parent_scope,
|
||||||
None,
|
None,
|
||||||
|
|
|
@ -352,9 +352,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||||
(old_glob @ true, false) | (old_glob @ false, true) => {
|
(old_glob @ true, false) | (old_glob @ false, true) => {
|
||||||
let (glob_binding, nonglob_binding) =
|
let (glob_binding, nonglob_binding) =
|
||||||
if old_glob { (old_binding, binding) } else { (binding, old_binding) };
|
if old_glob { (old_binding, binding) } else { (binding, old_binding) };
|
||||||
if glob_binding.res() != nonglob_binding.res()
|
if key.ns == MacroNS
|
||||||
&& key.ns == MacroNS
|
|
||||||
&& nonglob_binding.expansion != LocalExpnId::ROOT
|
&& nonglob_binding.expansion != LocalExpnId::ROOT
|
||||||
|
&& glob_binding.res() != nonglob_binding.res()
|
||||||
{
|
{
|
||||||
resolution.binding = Some(this.ambiguity(
|
resolution.binding = Some(this.ambiguity(
|
||||||
AmbiguityKind::GlobVsExpanded,
|
AmbiguityKind::GlobVsExpanded,
|
||||||
|
|
|
@ -924,11 +924,12 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Alias(kind @ (ty::Projection | ty::Inherent | ty::Weak), ..) => {
|
// A rigid alias may normalize to anything.
|
||||||
if ty.has_type_flags(ty::TypeFlags::HAS_TY_PARAM) {
|
// * If it references an infer var, placeholder or bound ty, it may
|
||||||
bug!("unexpected ty param in alias ty");
|
// normalize to that, so we have to treat it as an uncovered ty param.
|
||||||
}
|
// * Otherwise it may normalize to any non-type-generic type
|
||||||
|
// be it local or non-local.
|
||||||
|
ty::Alias(kind, _) => {
|
||||||
if ty.has_type_flags(
|
if ty.has_type_flags(
|
||||||
ty::TypeFlags::HAS_TY_PLACEHOLDER
|
ty::TypeFlags::HAS_TY_PLACEHOLDER
|
||||||
| ty::TypeFlags::HAS_TY_BOUND
|
| ty::TypeFlags::HAS_TY_BOUND
|
||||||
|
@ -948,7 +949,24 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ControlFlow::Continue(())
|
// Regarding *opaque types* specifically, we choose to treat them as non-local,
|
||||||
|
// even those that appear within the same crate. This seems somewhat surprising
|
||||||
|
// at first, but makes sense when you consider that opaque types are supposed
|
||||||
|
// to hide the underlying type *within the same crate*. When an opaque type is
|
||||||
|
// used from outside the module where it is declared, it should be impossible to
|
||||||
|
// observe anything about it other than the traits that it implements.
|
||||||
|
//
|
||||||
|
// The alternative would be to look at the underlying type to determine whether
|
||||||
|
// or not the opaque type itself should be considered local.
|
||||||
|
//
|
||||||
|
// However, this could make it a breaking change to switch the underlying hidden
|
||||||
|
// type from a local type to a remote type. This would violate the rule that
|
||||||
|
// opaque types should be completely opaque apart from the traits that they
|
||||||
|
// implement, so we don't use this behavior.
|
||||||
|
// Addendum: Moreover, revealing the underlying type is likely to cause cycle
|
||||||
|
// errors as we rely on coherence / the specialization graph during typeck.
|
||||||
|
|
||||||
|
self.found_non_local_ty(ty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -990,35 +1008,6 @@ where
|
||||||
// auto trait impl applies. There will never be multiple impls, so we can just
|
// auto trait impl applies. There will never be multiple impls, so we can just
|
||||||
// act as if it were a local type here.
|
// act as if it were a local type here.
|
||||||
ty::CoroutineWitness(..) => ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)),
|
ty::CoroutineWitness(..) => ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)),
|
||||||
ty::Alias(ty::Opaque, ..) => {
|
|
||||||
// This merits some explanation.
|
|
||||||
// Normally, opaque types are not involved when performing
|
|
||||||
// coherence checking, since it is illegal to directly
|
|
||||||
// implement a trait on an opaque type. However, we might
|
|
||||||
// end up looking at an opaque type during coherence checking
|
|
||||||
// if an opaque type gets used within another type (e.g. as
|
|
||||||
// the type of a field) when checking for auto trait or `Sized`
|
|
||||||
// impls. This requires us to decide whether or not an opaque
|
|
||||||
// type should be considered 'local' or not.
|
|
||||||
//
|
|
||||||
// We choose to treat all opaque types as non-local, even
|
|
||||||
// those that appear within the same crate. This seems
|
|
||||||
// somewhat surprising at first, but makes sense when
|
|
||||||
// you consider that opaque types are supposed to hide
|
|
||||||
// the underlying type *within the same crate*. When an
|
|
||||||
// opaque type is used from outside the module
|
|
||||||
// where it is declared, it should be impossible to observe
|
|
||||||
// anything about it other than the traits that it implements.
|
|
||||||
//
|
|
||||||
// The alternative would be to look at the underlying type
|
|
||||||
// to determine whether or not the opaque type itself should
|
|
||||||
// be considered local. However, this could make it a breaking change
|
|
||||||
// to switch the underlying ('defining') type from a local type
|
|
||||||
// to a remote type. This would violate the rule that opaque
|
|
||||||
// types should be completely opaque apart from the traits
|
|
||||||
// that they implement, so we don't use this behavior.
|
|
||||||
self.found_non_local_ty(ty)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
// A bit of a hack, the `OrphanChecker` is only used to visit a `TraitRef`, so
|
// A bit of a hack, the `OrphanChecker` is only used to visit a `TraitRef`, so
|
||||||
// the first type we visit is always the self type.
|
// the first type we visit is always the self type.
|
||||||
|
|
|
@ -1190,9 +1190,8 @@ pub trait IsTerminal: crate::sealed::Sealed {
|
||||||
///
|
///
|
||||||
/// - If you run this example by piping some text to it, e.g. `echo "foo" | path/to/executable`
|
/// - If you run this example by piping some text to it, e.g. `echo "foo" | path/to/executable`
|
||||||
/// it will print: `Hello foo`.
|
/// it will print: `Hello foo`.
|
||||||
/// - If you instead run the example interactively by running the executable directly, it will
|
/// - If you instead run the example interactively by running `path/to/executable` directly, it will
|
||||||
/// panic with the message "Expected input to be piped to the process".
|
/// prompt for input.
|
||||||
///
|
|
||||||
///
|
///
|
||||||
/// [changes]: io#platform-specific-behavior
|
/// [changes]: io#platform-specific-behavior
|
||||||
/// [`Stdin`]: crate::io::Stdin
|
/// [`Stdin`]: crate::io::Stdin
|
||||||
|
|
|
@ -15,7 +15,7 @@ pub use self::task_queue::JoinNotifier;
|
||||||
|
|
||||||
mod task_queue {
|
mod task_queue {
|
||||||
use super::wait_notify;
|
use super::wait_notify;
|
||||||
use crate::sync::{Mutex, MutexGuard, Once};
|
use crate::sync::{Mutex, MutexGuard};
|
||||||
|
|
||||||
pub type JoinHandle = wait_notify::Waiter;
|
pub type JoinHandle = wait_notify::Waiter;
|
||||||
|
|
||||||
|
@ -28,12 +28,12 @@ mod task_queue {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) struct Task {
|
pub(super) struct Task {
|
||||||
p: Box<dyn FnOnce()>,
|
p: Box<dyn FnOnce() + Send>,
|
||||||
done: JoinNotifier,
|
done: JoinNotifier,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Task {
|
impl Task {
|
||||||
pub(super) fn new(p: Box<dyn FnOnce()>) -> (Task, JoinHandle) {
|
pub(super) fn new(p: Box<dyn FnOnce() + Send>) -> (Task, JoinHandle) {
|
||||||
let (done, recv) = wait_notify::new();
|
let (done, recv) = wait_notify::new();
|
||||||
let done = JoinNotifier(Some(done));
|
let done = JoinNotifier(Some(done));
|
||||||
(Task { p, done }, recv)
|
(Task { p, done }, recv)
|
||||||
|
@ -45,18 +45,12 @@ mod task_queue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(test, linkage = "available_externally")]
|
|
||||||
#[export_name = "_ZN16__rust_internals3std3sys3sgx6thread15TASK_QUEUE_INITE"]
|
|
||||||
static TASK_QUEUE_INIT: Once = Once::new();
|
|
||||||
#[cfg_attr(test, linkage = "available_externally")]
|
#[cfg_attr(test, linkage = "available_externally")]
|
||||||
#[export_name = "_ZN16__rust_internals3std3sys3sgx6thread10TASK_QUEUEE"]
|
#[export_name = "_ZN16__rust_internals3std3sys3sgx6thread10TASK_QUEUEE"]
|
||||||
static mut TASK_QUEUE: Option<Mutex<Vec<Task>>> = None;
|
static TASK_QUEUE: Mutex<Vec<Task>> = Mutex::new(Vec::new());
|
||||||
|
|
||||||
pub(super) fn lock() -> MutexGuard<'static, Vec<Task>> {
|
pub(super) fn lock() -> MutexGuard<'static, Vec<Task>> {
|
||||||
unsafe {
|
TASK_QUEUE.lock().unwrap()
|
||||||
TASK_QUEUE_INIT.call_once(|| TASK_QUEUE = Some(Default::default()));
|
|
||||||
TASK_QUEUE.as_ref().unwrap().lock().unwrap()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,7 +95,7 @@ pub mod wait_notify {
|
||||||
|
|
||||||
impl Thread {
|
impl Thread {
|
||||||
// unsafe: see thread::Builder::spawn_unchecked for safety requirements
|
// unsafe: see thread::Builder::spawn_unchecked for safety requirements
|
||||||
pub unsafe fn new(_stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
|
pub unsafe fn new(_stack: usize, p: Box<dyn FnOnce() + Send>) -> io::Result<Thread> {
|
||||||
let mut queue_lock = task_queue::lock();
|
let mut queue_lock = task_queue::lock();
|
||||||
unsafe { usercalls::launch_thread()? };
|
unsafe { usercalls::launch_thread()? };
|
||||||
let (task, handle) = task_queue::Task::new(p);
|
let (task, handle) = task_queue::Task::new(p);
|
||||||
|
|
|
@ -561,7 +561,8 @@ impl Builder {
|
||||||
let main = Box::new(main);
|
let main = Box::new(main);
|
||||||
// SAFETY: dynamic size and alignment of the Box remain the same. See below for why the
|
// SAFETY: dynamic size and alignment of the Box remain the same. See below for why the
|
||||||
// lifetime change is justified.
|
// lifetime change is justified.
|
||||||
let main = unsafe { Box::from_raw(Box::into_raw(main) as *mut (dyn FnOnce() + 'static)) };
|
let main =
|
||||||
|
unsafe { Box::from_raw(Box::into_raw(main) as *mut (dyn FnOnce() + Send + 'static)) };
|
||||||
|
|
||||||
Ok(JoinInner {
|
Ok(JoinInner {
|
||||||
// SAFETY:
|
// SAFETY:
|
||||||
|
@ -1544,7 +1545,7 @@ struct Packet<'scope, T> {
|
||||||
// The type `T` should already always be Send (otherwise the thread could not
|
// The type `T` should already always be Send (otherwise the thread could not
|
||||||
// have been created) and the Packet is Sync because all access to the
|
// have been created) and the Packet is Sync because all access to the
|
||||||
// `UnsafeCell` synchronized (by the `join()` boundary), and `ScopeData` is Sync.
|
// `UnsafeCell` synchronized (by the `join()` boundary), and `ScopeData` is Sync.
|
||||||
unsafe impl<'scope, T: Sync> Sync for Packet<'scope, T> {}
|
unsafe impl<'scope, T: Send> Sync for Packet<'scope, T> {}
|
||||||
|
|
||||||
impl<'scope, T> Drop for Packet<'scope, T> {
|
impl<'scope, T> Drop for Packet<'scope, T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
|
|
|
@ -270,7 +270,6 @@ else
|
||||||
args="$args --volume $root_dir:/checkout$SRC_MOUNT_OPTION"
|
args="$args --volume $root_dir:/checkout$SRC_MOUNT_OPTION"
|
||||||
args="$args --volume $objdir:/checkout/obj"
|
args="$args --volume $objdir:/checkout/obj"
|
||||||
args="$args --volume $HOME/.cargo:/cargo"
|
args="$args --volume $HOME/.cargo:/cargo"
|
||||||
args="$args --volume $HOME/rustsrc:$HOME/rustsrc"
|
|
||||||
args="$args --volume /tmp/toolstate:/tmp/toolstate"
|
args="$args --volume /tmp/toolstate:/tmp/toolstate"
|
||||||
|
|
||||||
id=$(id -u)
|
id=$(id -u)
|
||||||
|
|
|
@ -61,6 +61,12 @@ envs:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
<<: *production
|
<<: *production
|
||||||
|
# The following env var activates faster `try` builds in `opt-dist` by, e.g.
|
||||||
|
# - building only the more commonly useful components (we rarely need e.g. rust-docs in try
|
||||||
|
# builds)
|
||||||
|
# - not running `opt-dist`'s post-optimization smoke tests on the resulting toolchain
|
||||||
|
#
|
||||||
|
# If you *want* these to happen however, temporarily uncomment it before triggering a try build.
|
||||||
DIST_TRY_BUILD: 1
|
DIST_TRY_BUILD: 1
|
||||||
|
|
||||||
auto:
|
auto:
|
||||||
|
|
|
@ -1268,6 +1268,8 @@ fn expand_variables(mut value: String, config: &Config) -> String {
|
||||||
const CWD: &str = "{{cwd}}";
|
const CWD: &str = "{{cwd}}";
|
||||||
const SRC_BASE: &str = "{{src-base}}";
|
const SRC_BASE: &str = "{{src-base}}";
|
||||||
const BUILD_BASE: &str = "{{build-base}}";
|
const BUILD_BASE: &str = "{{build-base}}";
|
||||||
|
const SYSROOT_BASE: &str = "{{sysroot-base}}";
|
||||||
|
const TARGET_LINKER: &str = "{{target-linker}}";
|
||||||
|
|
||||||
if value.contains(CWD) {
|
if value.contains(CWD) {
|
||||||
let cwd = env::current_dir().unwrap();
|
let cwd = env::current_dir().unwrap();
|
||||||
|
@ -1282,6 +1284,14 @@ fn expand_variables(mut value: String, config: &Config) -> String {
|
||||||
value = value.replace(BUILD_BASE, &config.build_base.to_string_lossy());
|
value = value.replace(BUILD_BASE, &config.build_base.to_string_lossy());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if value.contains(SYSROOT_BASE) {
|
||||||
|
value = value.replace(SYSROOT_BASE, &config.sysroot_base.to_string_lossy());
|
||||||
|
}
|
||||||
|
|
||||||
|
if value.contains(TARGET_LINKER) {
|
||||||
|
value = value.replace(TARGET_LINKER, config.target_linker.as_deref().unwrap_or(""));
|
||||||
|
}
|
||||||
|
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,12 +83,24 @@ fn main() {
|
||||||
test_abi_compat(main as fn(), id::<i32> as fn(i32) -> i32);
|
test_abi_compat(main as fn(), id::<i32> as fn(i32) -> i32);
|
||||||
// - 1-ZST
|
// - 1-ZST
|
||||||
test_abi_compat((), [0u8; 0]);
|
test_abi_compat((), [0u8; 0]);
|
||||||
// - Guaranteed null-pointer-optimizations (RFC 3391).
|
// - Guaranteed Option<X> null-pointer-optimizations (RFC 3391).
|
||||||
test_abi_compat(&0u32 as *const u32, Some(&0u32));
|
test_abi_compat(&0u32 as *const u32, Some(&0u32));
|
||||||
test_abi_compat(main as fn(), Some(main as fn()));
|
test_abi_compat(main as fn(), Some(main as fn()));
|
||||||
test_abi_compat(0u32, Some(num::NonZero::new(1u32).unwrap()));
|
test_abi_compat(0u32, Some(num::NonZero::new(1u32).unwrap()));
|
||||||
test_abi_compat(&0u32 as *const u32, Some(Wrapper(&0u32)));
|
test_abi_compat(&0u32 as *const u32, Some(Wrapper(&0u32)));
|
||||||
test_abi_compat(0u32, Some(Wrapper(num::NonZero::new(1u32).unwrap())));
|
test_abi_compat(0u32, Some(Wrapper(num::NonZeroU32::new(1u32).unwrap())));
|
||||||
|
// - Guaranteed Result<X, ZST1> does the same as Option<X> (RFC 3391)
|
||||||
|
test_abi_compat(&0u32 as *const u32, Result::<_, ()>::Ok(&0u32));
|
||||||
|
test_abi_compat(main as fn(), Result::<_, ()>::Ok(main as fn()));
|
||||||
|
test_abi_compat(0u32, Result::<_, ()>::Ok(num::NonZeroU32::new(1).unwrap()));
|
||||||
|
test_abi_compat(&0u32 as *const u32, Result::<_, ()>::Ok(Wrapper(&0u32)));
|
||||||
|
test_abi_compat(0u32, Result::<_, ()>::Ok(Wrapper(num::NonZeroU32::new(1).unwrap())));
|
||||||
|
// - Guaranteed Result<ZST1, X> also does the same as Option<X> (RFC 3391)
|
||||||
|
test_abi_compat(&0u32 as *const u32, Result::<(), _>::Err(&0u32));
|
||||||
|
test_abi_compat(main as fn(), Result::<(), _>::Err(main as fn()));
|
||||||
|
test_abi_compat(0u32, Result::<(), _>::Err(num::NonZeroU32::new(1).unwrap()));
|
||||||
|
test_abi_compat(&0u32 as *const u32, Result::<(), _>::Err(Wrapper(&0u32)));
|
||||||
|
test_abi_compat(0u32, Result::<(), _>::Err(Wrapper(num::NonZeroU32::new(1).unwrap())));
|
||||||
|
|
||||||
// These must work for *any* type, since we guarantee that `repr(transparent)` is ABI-compatible
|
// These must work for *any* type, since we guarantee that `repr(transparent)` is ABI-compatible
|
||||||
// with the wrapped field.
|
// with the wrapped field.
|
||||||
|
|
|
@ -2445,7 +2445,6 @@ ui/issues/issue-53300.rs
|
||||||
ui/issues/issue-53333.rs
|
ui/issues/issue-53333.rs
|
||||||
ui/issues/issue-53348.rs
|
ui/issues/issue-53348.rs
|
||||||
ui/issues/issue-53419.rs
|
ui/issues/issue-53419.rs
|
||||||
ui/issues/issue-53498.rs
|
|
||||||
ui/issues/issue-53568.rs
|
ui/issues/issue-53568.rs
|
||||||
ui/issues/issue-5358-1.rs
|
ui/issues/issue-5358-1.rs
|
||||||
ui/issues/issue-53728.rs
|
ui/issues/issue-53728.rs
|
||||||
|
|
|
@ -15,7 +15,7 @@ use std::path::{Path, PathBuf};
|
||||||
const ENTRY_LIMIT: u32 = 900;
|
const ENTRY_LIMIT: u32 = 900;
|
||||||
// FIXME: The following limits should be reduced eventually.
|
// FIXME: The following limits should be reduced eventually.
|
||||||
|
|
||||||
const ISSUES_ENTRY_LIMIT: u32 = 1674;
|
const ISSUES_ENTRY_LIMIT: u32 = 1672;
|
||||||
|
|
||||||
const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
|
const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
|
||||||
"rs", // test source files
|
"rs", // test source files
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
//@ known-bug: rust-lang/rust#124490
|
|
||||||
use io::{self as std};
|
|
||||||
use std::collections::{self as io};
|
|
||||||
|
|
||||||
mod a {
|
|
||||||
pub mod b {
|
|
||||||
pub mod c {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
use a::*;
|
|
||||||
|
|
||||||
use b::c;
|
|
||||||
use c as b;
|
|
||||||
|
|
||||||
fn main() {}
|
|
|
@ -1,5 +0,0 @@
|
||||||
//@ known-bug: rust-lang/rust#125013
|
|
||||||
//@ edition:2021
|
|
||||||
use io::{self as std};
|
|
||||||
use std::ops::Deref::{self as io};
|
|
||||||
pub fn main() {}
|
|
|
@ -1,16 +0,0 @@
|
||||||
//@ known-bug: rust-lang/rust#125013
|
|
||||||
//@ edition:2021
|
|
||||||
mod a {
|
|
||||||
pub mod b {
|
|
||||||
pub mod c {
|
|
||||||
pub trait D {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
use a::*;
|
|
||||||
|
|
||||||
use e as b;
|
|
||||||
use b::c::D as e;
|
|
||||||
|
|
||||||
fn main() { }
|
|
|
@ -1,9 +0,0 @@
|
||||||
include ../../run-make/tools.mk
|
|
||||||
|
|
||||||
# This test ensures that rustc compile_input can be called twice in one task
|
|
||||||
# without causing a panic.
|
|
||||||
# The program needs the path to rustc to get sysroot.
|
|
||||||
|
|
||||||
all:
|
|
||||||
$(RUSTC) foo.rs
|
|
||||||
$(call RUN,foo $(TMPDIR) $(RUSTC))
|
|
|
@ -1,3 +1,13 @@
|
||||||
|
//@ edition: 2021
|
||||||
|
//@ run-pass
|
||||||
|
//@ run-flags: {{sysroot-base}} {{target-linker}}
|
||||||
|
//@ ignore-stage1 (requires matching sysroot built with in-tree compiler)
|
||||||
|
|
||||||
|
// Regression test for <https://github.com/rust-lang/rust/issues/19371>.
|
||||||
|
//
|
||||||
|
// This test ensures that `compile_input` can be called twice in one task
|
||||||
|
// without causing a panic.
|
||||||
|
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
|
|
||||||
extern crate rustc_driver;
|
extern crate rustc_driver;
|
||||||
|
@ -5,12 +15,12 @@ extern crate rustc_interface;
|
||||||
extern crate rustc_session;
|
extern crate rustc_session;
|
||||||
extern crate rustc_span;
|
extern crate rustc_span;
|
||||||
|
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use rustc_interface::interface;
|
use rustc_interface::interface;
|
||||||
use rustc_session::config::{Input, Options, OutFileName, OutputType, OutputTypes};
|
use rustc_session::config::{Input, Options, OutFileName, OutputType, OutputTypes};
|
||||||
use rustc_span::FileName;
|
use rustc_span::FileName;
|
||||||
|
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let src = r#"
|
let src = r#"
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -18,28 +28,28 @@ fn main() {
|
||||||
|
|
||||||
let args: Vec<String> = std::env::args().collect();
|
let args: Vec<String> = std::env::args().collect();
|
||||||
|
|
||||||
if args.len() < 4 {
|
if args.len() < 2 {
|
||||||
panic!("expected rustc path");
|
panic!("expected sysroot (and optional linker)");
|
||||||
}
|
}
|
||||||
|
|
||||||
let tmpdir = PathBuf::from(&args[1]);
|
let sysroot = PathBuf::from(&args[1]);
|
||||||
|
let linker = args.get(2).map(PathBuf::from);
|
||||||
|
|
||||||
let mut sysroot = PathBuf::from(&args[3]);
|
// compiletest sets the current dir to `output_base_dir` when running.
|
||||||
sysroot.pop();
|
let tmpdir = std::env::current_dir().unwrap().join("tmp");
|
||||||
sysroot.pop();
|
std::fs::create_dir_all(&tmpdir).unwrap();
|
||||||
|
|
||||||
compile(src.to_string(), tmpdir.join("out"), sysroot.clone());
|
compile(src.to_string(), tmpdir.join("out"), sysroot.clone(), linker.as_deref());
|
||||||
|
compile(src.to_string(), tmpdir.join("out"), sysroot.clone(), linker.as_deref());
|
||||||
compile(src.to_string(), tmpdir.join("out"), sysroot.clone());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
|
fn compile(code: String, output: PathBuf, sysroot: PathBuf, linker: Option<&Path>) {
|
||||||
let mut opts = Options::default();
|
let mut opts = Options::default();
|
||||||
opts.output_types = OutputTypes::new(&[(OutputType::Exe, None)]);
|
opts.output_types = OutputTypes::new(&[(OutputType::Exe, None)]);
|
||||||
opts.maybe_sysroot = Some(sysroot);
|
opts.maybe_sysroot = Some(sysroot);
|
||||||
|
|
||||||
if let Ok(linker) = std::env::var("RUSTC_LINKER") {
|
if let Some(linker) = linker {
|
||||||
opts.cg.linker = Some(linker.into());
|
opts.cg.linker = Some(linker.to_owned());
|
||||||
}
|
}
|
||||||
|
|
||||||
let name = FileName::anon_source_code(&code);
|
let name = FileName::anon_source_code(&code);
|
|
@ -0,0 +1,21 @@
|
||||||
|
error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
|
||||||
|
--> $DIR/orphan-check-opaque-types-not-covering.rs:17:6
|
||||||
|
|
|
||||||
|
LL | impl<T> foreign::Trait0<Local, T, ()> for Identity<T> {}
|
||||||
|
| ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
|
||||||
|
|
|
||||||
|
= note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type
|
||||||
|
= note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
|
||||||
|
|
||||||
|
error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
|
||||||
|
--> $DIR/orphan-check-opaque-types-not-covering.rs:26:6
|
||||||
|
|
|
||||||
|
LL | impl<T> foreign::Trait1<Local, T> for Opaque<T> {}
|
||||||
|
| ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
|
||||||
|
|
|
||||||
|
= note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type
|
||||||
|
= note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0210`.
|
|
@ -0,0 +1,21 @@
|
||||||
|
error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
|
||||||
|
--> $DIR/orphan-check-opaque-types-not-covering.rs:17:6
|
||||||
|
|
|
||||||
|
LL | impl<T> foreign::Trait0<Local, T, ()> for Identity<T> {}
|
||||||
|
| ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
|
||||||
|
|
|
||||||
|
= note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type
|
||||||
|
= note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
|
||||||
|
|
||||||
|
error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
|
||||||
|
--> $DIR/orphan-check-opaque-types-not-covering.rs:26:6
|
||||||
|
|
|
||||||
|
LL | impl<T> foreign::Trait1<Local, T> for Opaque<T> {}
|
||||||
|
| ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
|
||||||
|
|
|
||||||
|
= note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type
|
||||||
|
= note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0210`.
|
31
tests/ui/coherence/orphan-check-opaque-types-not-covering.rs
Normal file
31
tests/ui/coherence/orphan-check-opaque-types-not-covering.rs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// Opaque types never cover type parameters.
|
||||||
|
|
||||||
|
//@ revisions: classic next
|
||||||
|
//@[next] compile-flags: -Znext-solver
|
||||||
|
|
||||||
|
//@ aux-crate:foreign=parametrized-trait.rs
|
||||||
|
//@ edition:2021
|
||||||
|
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
type Identity<T> = impl Sized;
|
||||||
|
|
||||||
|
fn define_identity<T>(x: T) -> Identity<T> {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> foreign::Trait0<Local, T, ()> for Identity<T> {}
|
||||||
|
//~^ ERROR type parameter `T` must be covered by another type
|
||||||
|
|
||||||
|
type Opaque<T> = impl Sized;
|
||||||
|
|
||||||
|
fn define_local<T>() -> Opaque<T> {
|
||||||
|
Local
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> foreign::Trait1<Local, T> for Opaque<T> {}
|
||||||
|
//~^ ERROR type parameter `T` must be covered by another type
|
||||||
|
|
||||||
|
struct Local;
|
||||||
|
|
||||||
|
fn main() {}
|
14
tests/ui/imports/cycle-import-in-diff-module-0.rs
Normal file
14
tests/ui/imports/cycle-import-in-diff-module-0.rs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
//@ check-pass
|
||||||
|
|
||||||
|
// https://github.com/rust-lang/rust/pull/124840#issuecomment-2098148587
|
||||||
|
|
||||||
|
mod a {
|
||||||
|
pub(crate) use crate::S;
|
||||||
|
}
|
||||||
|
mod b {
|
||||||
|
pub struct S;
|
||||||
|
}
|
||||||
|
use self::a::S;
|
||||||
|
use self::b::*;
|
||||||
|
|
||||||
|
fn main() {}
|
14
tests/ui/imports/cycle-import-in-diff-module-1.rs
Normal file
14
tests/ui/imports/cycle-import-in-diff-module-1.rs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
//@ check-pass
|
||||||
|
|
||||||
|
// similar `cycle-import-in-diff-module-0.rs`
|
||||||
|
|
||||||
|
mod a {
|
||||||
|
pub(crate) use crate::s;
|
||||||
|
}
|
||||||
|
mod b {
|
||||||
|
pub mod s {}
|
||||||
|
}
|
||||||
|
use self::b::*;
|
||||||
|
use self::a::s;
|
||||||
|
|
||||||
|
fn main() {}
|
17
tests/ui/imports/shadow-glob-module-resolution-1.rs
Normal file
17
tests/ui/imports/shadow-glob-module-resolution-1.rs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// https://github.com/rust-lang/rust/issues/124490
|
||||||
|
|
||||||
|
mod a {
|
||||||
|
pub mod b {
|
||||||
|
pub mod c {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
use a::*;
|
||||||
|
|
||||||
|
use b::c;
|
||||||
|
//~^ ERROR: cannot determine resolution for the import
|
||||||
|
//~| ERROR: cannot determine resolution for the import
|
||||||
|
//~| ERROR: unresolved import `b::c`
|
||||||
|
use c as b;
|
||||||
|
|
||||||
|
fn main() {}
|
23
tests/ui/imports/shadow-glob-module-resolution-1.stderr
Normal file
23
tests/ui/imports/shadow-glob-module-resolution-1.stderr
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
error: cannot determine resolution for the import
|
||||||
|
--> $DIR/shadow-glob-module-resolution-1.rs:11:5
|
||||||
|
|
|
||||||
|
LL | use b::c;
|
||||||
|
| ^^^^
|
||||||
|
|
||||||
|
error: cannot determine resolution for the import
|
||||||
|
--> $DIR/shadow-glob-module-resolution-1.rs:11:5
|
||||||
|
|
|
||||||
|
LL | use b::c;
|
||||||
|
| ^^^^
|
||||||
|
|
|
||||||
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||||
|
|
||||||
|
error[E0432]: unresolved import `b::c`
|
||||||
|
--> $DIR/shadow-glob-module-resolution-1.rs:11:5
|
||||||
|
|
|
||||||
|
LL | use b::c;
|
||||||
|
| ^^^^
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0432`.
|
19
tests/ui/imports/shadow-glob-module-resolution-2.rs
Normal file
19
tests/ui/imports/shadow-glob-module-resolution-2.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
// https://github.com/rust-lang/rust/issues/125013
|
||||||
|
|
||||||
|
mod a {
|
||||||
|
pub mod b {
|
||||||
|
pub mod c {
|
||||||
|
pub trait D {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
use a::*;
|
||||||
|
|
||||||
|
use e as b;
|
||||||
|
//~^ ERROR: unresolved import `e`
|
||||||
|
use b::c::D as e;
|
||||||
|
//~^ ERROR: cannot determine resolution for the import
|
||||||
|
//~| ERROR: cannot determine resolution for the import
|
||||||
|
|
||||||
|
fn main() { }
|
26
tests/ui/imports/shadow-glob-module-resolution-2.stderr
Normal file
26
tests/ui/imports/shadow-glob-module-resolution-2.stderr
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
error: cannot determine resolution for the import
|
||||||
|
--> $DIR/shadow-glob-module-resolution-2.rs:15:5
|
||||||
|
|
|
||||||
|
LL | use b::c::D as e;
|
||||||
|
| ^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: cannot determine resolution for the import
|
||||||
|
--> $DIR/shadow-glob-module-resolution-2.rs:15:5
|
||||||
|
|
|
||||||
|
LL | use b::c::D as e;
|
||||||
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||||
|
|
||||||
|
error[E0432]: unresolved import `e`
|
||||||
|
--> $DIR/shadow-glob-module-resolution-2.rs:13:5
|
||||||
|
|
|
||||||
|
LL | use e as b;
|
||||||
|
| -^^^^^
|
||||||
|
| |
|
||||||
|
| no `e` in the root
|
||||||
|
| help: a similar name exists in the module: `a`
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0432`.
|
|
@ -1,17 +0,0 @@
|
||||||
pub mod test {
|
|
||||||
pub struct A;
|
|
||||||
pub struct B;
|
|
||||||
pub struct Foo<T>(T);
|
|
||||||
|
|
||||||
impl Foo<A> {
|
|
||||||
fn foo() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Foo<B> {
|
|
||||||
fn foo() {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
test::Foo::<test::B>::foo(); //~ ERROR associated function `foo` is private
|
|
||||||
}
|
|
15
tests/ui/privacy/ufc-method-call.different_name.stderr
Normal file
15
tests/ui/privacy/ufc-method-call.different_name.stderr
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
error[E0599]: no function or associated item named `foo` found for struct `Foo<B>` in the current scope
|
||||||
|
--> $DIR/ufc-method-call.rs:27:27
|
||||||
|
|
|
||||||
|
LL | pub struct Foo<T>(T);
|
||||||
|
| ----------------- function or associated item `foo` not found for this struct
|
||||||
|
...
|
||||||
|
LL | test::Foo::<test::B>::foo();
|
||||||
|
| ^^^ function or associated item not found in `Foo<B>`
|
||||||
|
|
|
||||||
|
= note: the function or associated item was found for
|
||||||
|
- `Foo<A>`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0599`.
|
30
tests/ui/privacy/ufc-method-call.rs
Normal file
30
tests/ui/privacy/ufc-method-call.rs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
//! This test used to report that the method call cannot
|
||||||
|
//! call the private method `Foo<A>::foo`, even though the user
|
||||||
|
//! explicitly selected `Foo<B>::foo`. This is because we only
|
||||||
|
//! looked for methods of the right name, without properly checking
|
||||||
|
//! the `Self` type
|
||||||
|
|
||||||
|
//@ revisions: same_name different_name
|
||||||
|
|
||||||
|
pub mod test {
|
||||||
|
pub struct A;
|
||||||
|
pub struct B;
|
||||||
|
pub struct Foo<T>(T);
|
||||||
|
|
||||||
|
impl Foo<A> {
|
||||||
|
fn foo() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Foo<B> {
|
||||||
|
#[cfg(same_name)]
|
||||||
|
fn foo() {}
|
||||||
|
#[cfg(different_name)]
|
||||||
|
fn bar() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
test::Foo::<test::B>::foo();
|
||||||
|
//[same_name]~^ ERROR associated function `foo` is private
|
||||||
|
//[different_name]~^^ ERROR no function or associated item named `foo` found for struct `Foo<B>`
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0624]: associated function `foo` is private
|
error[E0624]: associated function `foo` is private
|
||||||
--> $DIR/issue-53498.rs:16:27
|
--> $DIR/ufc-method-call.rs:27:27
|
||||||
|
|
|
|
||||||
LL | fn foo() {}
|
LL | fn foo() {}
|
||||||
| -------- private associated function defined here
|
| -------- private associated function defined here
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
|
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
|
||||||
--> $DIR/coherence.rs:14:1
|
--> $DIR/coherence.rs:16:1
|
||||||
|
|
|
|
||||||
LL | impl foreign_crate::ForeignTrait for AliasOfForeignType<()> {}
|
LL | impl foreign_crate::ForeignTrait for AliasOfForeignType<()> {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------
|
14
tests/ui/type-alias-impl-trait/coherence.next.stderr
Normal file
14
tests/ui/type-alias-impl-trait/coherence.next.stderr
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
|
||||||
|
--> $DIR/coherence.rs:16:1
|
||||||
|
|
|
||||||
|
LL | impl foreign_crate::ForeignTrait for AliasOfForeignType<()> {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------
|
||||||
|
| | |
|
||||||
|
| | `AliasOfForeignType<()>` is not defined in the current crate
|
||||||
|
| impl doesn't use only types from inside the current crate
|
||||||
|
|
|
||||||
|
= note: define and implement a trait or new type instead
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0117`.
|
|
@ -1,4 +1,6 @@
|
||||||
//@ aux-build:foreign-crate.rs
|
//@ aux-build:foreign-crate.rs
|
||||||
|
//@ revisions: classic next
|
||||||
|
//@[next] compile-flags: -Znext-solver
|
||||||
#![feature(type_alias_impl_trait)]
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
extern crate foreign_crate;
|
extern crate foreign_crate;
|
||||||
|
|
Loading…
Add table
Reference in a new issue