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
|
||||
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 = 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.
|
||||
// For that we first unpeel transparent *structs* (but not unions).
|
||||
let is_npo = |def: AdtDef<'tcx>| {
|
||||
|
|
|
@ -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).
|
||||
|
@ -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?",
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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() {
|
||||
|
|
|
@ -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,
|
||||
|
@ -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()?;
|
||||
|
@ -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)?;
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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),
|
||||
|
@ -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:
|
||||
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -924,11 +924,12 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
ty::Alias(kind @ (ty::Projection | ty::Inherent | ty::Weak), ..) => {
|
||||
if ty.has_type_flags(ty::TypeFlags::HAS_TY_PARAM) {
|
||||
bug!("unexpected ty param in alias ty");
|
||||
}
|
||||
|
||||
// A rigid alias may normalize to anything.
|
||||
// * If it references an infer var, placeholder or bound ty, it may
|
||||
// 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(
|
||||
ty::TypeFlags::HAS_TY_PLACEHOLDER
|
||||
| ty::TypeFlags::HAS_TY_BOUND
|
||||
|
@ -948,7 +949,24 @@ where
|
|||
}
|
||||
}
|
||||
} 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
|
||||
// act as if it were a local type here.
|
||||
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
|
||||
// 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`
|
||||
/// it will print: `Hello foo`.
|
||||
/// - If you instead run the example interactively by running the executable directly, it will
|
||||
/// panic with the message "Expected input to be piped to the process".
|
||||
///
|
||||
/// - If you instead run the example interactively by running `path/to/executable` directly, it will
|
||||
/// prompt for input.
|
||||
///
|
||||
/// [changes]: io#platform-specific-behavior
|
||||
/// [`Stdin`]: crate::io::Stdin
|
||||
|
|
|
@ -15,7 +15,7 @@ pub use self::task_queue::JoinNotifier;
|
|||
|
||||
mod task_queue {
|
||||
use super::wait_notify;
|
||||
use crate::sync::{Mutex, MutexGuard, Once};
|
||||
use crate::sync::{Mutex, MutexGuard};
|
||||
|
||||
pub type JoinHandle = wait_notify::Waiter;
|
||||
|
||||
|
@ -28,12 +28,12 @@ mod task_queue {
|
|||
}
|
||||
|
||||
pub(super) struct Task {
|
||||
p: Box<dyn FnOnce()>,
|
||||
p: Box<dyn FnOnce() + Send>,
|
||||
done: JoinNotifier,
|
||||
}
|
||||
|
||||
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 = JoinNotifier(Some(done));
|
||||
(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")]
|
||||
#[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>> {
|
||||
unsafe {
|
||||
TASK_QUEUE_INIT.call_once(|| TASK_QUEUE = Some(Default::default()));
|
||||
TASK_QUEUE.as_ref().unwrap().lock().unwrap()
|
||||
}
|
||||
TASK_QUEUE.lock().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,7 +95,7 @@ pub mod wait_notify {
|
|||
|
||||
impl Thread {
|
||||
// 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();
|
||||
unsafe { usercalls::launch_thread()? };
|
||||
let (task, handle) = task_queue::Task::new(p);
|
||||
|
|
|
@ -561,7 +561,8 @@ impl Builder {
|
|||
let main = Box::new(main);
|
||||
// SAFETY: dynamic size and alignment of the Box remain the same. See below for why the
|
||||
// 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 {
|
||||
// SAFETY:
|
||||
|
@ -1544,7 +1545,7 @@ struct Packet<'scope, T> {
|
|||
// 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
|
||||
// `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> {
|
||||
fn drop(&mut self) {
|
||||
|
|
|
@ -270,7 +270,6 @@ else
|
|||
args="$args --volume $root_dir:/checkout$SRC_MOUNT_OPTION"
|
||||
args="$args --volume $objdir:/checkout/obj"
|
||||
args="$args --volume $HOME/.cargo:/cargo"
|
||||
args="$args --volume $HOME/rustsrc:$HOME/rustsrc"
|
||||
args="$args --volume /tmp/toolstate:/tmp/toolstate"
|
||||
|
||||
id=$(id -u)
|
||||
|
|
|
@ -61,6 +61,12 @@ envs:
|
|||
|
||||
try:
|
||||
<<: *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
|
||||
|
||||
auto:
|
||||
|
|
|
@ -1268,6 +1268,8 @@ fn expand_variables(mut value: String, config: &Config) -> String {
|
|||
const CWD: &str = "{{cwd}}";
|
||||
const SRC_BASE: &str = "{{src-base}}";
|
||||
const BUILD_BASE: &str = "{{build-base}}";
|
||||
const SYSROOT_BASE: &str = "{{sysroot-base}}";
|
||||
const TARGET_LINKER: &str = "{{target-linker}}";
|
||||
|
||||
if value.contains(CWD) {
|
||||
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());
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
@ -83,12 +83,24 @@ fn main() {
|
|||
test_abi_compat(main as fn(), id::<i32> as fn(i32) -> i32);
|
||||
// - 1-ZST
|
||||
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(main as fn(), Some(main as fn()));
|
||||
test_abi_compat(0u32, Some(num::NonZero::new(1u32).unwrap()));
|
||||
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
|
||||
// with the wrapped field.
|
||||
|
|
|
@ -2445,7 +2445,6 @@ ui/issues/issue-53300.rs
|
|||
ui/issues/issue-53333.rs
|
||||
ui/issues/issue-53348.rs
|
||||
ui/issues/issue-53419.rs
|
||||
ui/issues/issue-53498.rs
|
||||
ui/issues/issue-53568.rs
|
||||
ui/issues/issue-5358-1.rs
|
||||
ui/issues/issue-53728.rs
|
||||
|
|
|
@ -15,7 +15,7 @@ use std::path::{Path, PathBuf};
|
|||
const ENTRY_LIMIT: u32 = 900;
|
||||
// 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] = &[
|
||||
"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)]
|
||||
|
||||
extern crate rustc_driver;
|
||||
|
@ -5,12 +15,12 @@ extern crate rustc_interface;
|
|||
extern crate rustc_session;
|
||||
extern crate rustc_span;
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use rustc_interface::interface;
|
||||
use rustc_session::config::{Input, Options, OutFileName, OutputType, OutputTypes};
|
||||
use rustc_span::FileName;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn main() {
|
||||
let src = r#"
|
||||
fn main() {}
|
||||
|
@ -18,28 +28,28 @@ fn main() {
|
|||
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
|
||||
if args.len() < 4 {
|
||||
panic!("expected rustc path");
|
||||
if args.len() < 2 {
|
||||
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]);
|
||||
sysroot.pop();
|
||||
sysroot.pop();
|
||||
// compiletest sets the current dir to `output_base_dir` when running.
|
||||
let tmpdir = std::env::current_dir().unwrap().join("tmp");
|
||||
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());
|
||||
compile(src.to_string(), tmpdir.join("out"), sysroot.clone(), linker.as_deref());
|
||||
compile(src.to_string(), tmpdir.join("out"), sysroot.clone(), linker.as_deref());
|
||||
}
|
||||
|
||||
fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
|
||||
fn compile(code: String, output: PathBuf, sysroot: PathBuf, linker: Option<&Path>) {
|
||||
let mut opts = Options::default();
|
||||
opts.output_types = OutputTypes::new(&[(OutputType::Exe, None)]);
|
||||
opts.maybe_sysroot = Some(sysroot);
|
||||
|
||||
if let Ok(linker) = std::env::var("RUSTC_LINKER") {
|
||||
opts.cg.linker = Some(linker.into());
|
||||
if let Some(linker) = linker {
|
||||
opts.cg.linker = Some(linker.to_owned());
|
||||
}
|
||||
|
||||
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
|
||||
--> $DIR/issue-53498.rs:16:27
|
||||
--> $DIR/ufc-method-call.rs:27:27
|
||||
|
|
||||
LL | fn foo() {}
|
||||
| -------- private associated function defined here
|
|
@ -1,5 +1,5 @@
|
|||
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<()> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------
|
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
|
||||
//@ revisions: classic next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
extern crate foreign_crate;
|
||||
|
|
Loading…
Add table
Reference in a new issue