mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-30 20:17:50 +00:00
Auto merge of #132361 - jieyouxu:rollup-zburkwr, r=jieyouxu
Rollup of 6 pull requests Successful merges: - #130098 (Reject generic self types.) - #131096 (rustdoc: Remove usage of `allow(unused)` attribute on `no_run` merged doctests) - #132315 (compiletest: improve robustness of LLVM version handling) - #132346 (Some graphviz tweaks) - #132359 (Fix AIX libc call char type from i8 to u8) - #132360 (Un-vacation myself) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
759e07f063
@ -720,6 +720,7 @@ dependencies = [
|
||||
"miropt-test-tools",
|
||||
"regex",
|
||||
"rustfix",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tracing",
|
||||
|
51
compiler/rustc_error_codes/src/error_codes/E0801.md
Normal file
51
compiler/rustc_error_codes/src/error_codes/E0801.md
Normal file
@ -0,0 +1,51 @@
|
||||
The `self` parameter in a method has an invalid generic "receiver type".
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0801
|
||||
struct Foo;
|
||||
|
||||
impl Foo {
|
||||
fn foo<R: std::ops::Deref<Target=Self>>(self: R) {}
|
||||
}
|
||||
```
|
||||
|
||||
or alternatively,
|
||||
|
||||
```compile_fail,E0801
|
||||
struct Foo;
|
||||
|
||||
impl Foo {
|
||||
fn foo(self: impl std::ops::Deref<Target=Self>) {}
|
||||
}
|
||||
```
|
||||
|
||||
Methods take a special first parameter, termed `self`. It's normal to
|
||||
use `self`, `&self` or `&mut self`, which are syntactic sugar for
|
||||
`self: Self`, `self: &Self`, and `self: &mut Self` respectively.
|
||||
But it's also possible to use more sophisticated types of `self`
|
||||
parameter, for instance `std::rc::Rc<Self>`. The set of allowable
|
||||
`Self` types is extensible using the nightly feature
|
||||
[Arbitrary self types][AST].
|
||||
This will extend the valid set of `Self` types to anything which implements
|
||||
`std::ops::Deref<Target=Self>`, for example `Rc<Self>`, `Box<Self>`, or
|
||||
your own smart pointers that do the same.
|
||||
|
||||
However, even with that feature, the `self` type must be concrete.
|
||||
Generic `self` types are not permitted. Specifically, a `self` type will
|
||||
be rejected if it is a type parameter defined on the method.
|
||||
|
||||
These are OK:
|
||||
|
||||
```
|
||||
struct Foo;
|
||||
|
||||
impl Foo {
|
||||
fn foo(self) {}
|
||||
fn foo2(self: std::rc::Rc<Self>) {} // or some other similar
|
||||
// smart pointer if you enable arbitrary self types and
|
||||
// the pointer implements Deref<Target=Self>
|
||||
}
|
||||
```
|
||||
|
||||
[AST]: https://doc.rust-lang.org/unstable-book/language-features/arbitrary-self-types.html
|
@ -540,6 +540,7 @@ E0797: 0797,
|
||||
E0798: 0798,
|
||||
E0799: 0799,
|
||||
E0800: 0800,
|
||||
E0801: 0801,
|
||||
);
|
||||
)
|
||||
}
|
||||
|
@ -234,6 +234,12 @@ hir_analysis_inherent_ty_outside_relevant = cannot define inherent `impl` for a
|
||||
.help = consider moving this inherent impl into the crate defining the type if possible
|
||||
.span_help = alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items
|
||||
|
||||
hir_analysis_invalid_generic_receiver_ty = invalid generic `self` parameter type: `{$receiver_ty}`
|
||||
.note = type of `self` must not be a method generic parameter type
|
||||
|
||||
hir_analysis_invalid_generic_receiver_ty_help =
|
||||
use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
|
||||
|
||||
hir_analysis_invalid_receiver_ty = invalid `self` parameter type: `{$receiver_ty}`
|
||||
.note = type of `self` must be `Self` or a type that dereferences to it
|
||||
|
||||
|
@ -904,7 +904,6 @@ fn check_impl_item<'tcx>(
|
||||
hir::ImplItemKind::Type(ty) if ty.span != DUMMY_SP => (None, ty.span),
|
||||
_ => (None, impl_item.span),
|
||||
};
|
||||
|
||||
check_associated_item(tcx, impl_item.owner_id.def_id, span, method_sig)
|
||||
}
|
||||
|
||||
@ -1725,8 +1724,11 @@ fn check_method_receiver<'tcx>(
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let generics = tcx.generics_of(method.def_id);
|
||||
|
||||
if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, arbitrary_self_types_level) {
|
||||
let receiver_validity =
|
||||
receiver_is_valid(wfcx, span, receiver_ty, self_ty, arbitrary_self_types_level, generics);
|
||||
if let Err(receiver_validity_err) = receiver_validity {
|
||||
return Err(match arbitrary_self_types_level {
|
||||
// Wherever possible, emit a message advising folks that the features
|
||||
// `arbitrary_self_types` or `arbitrary_self_types_pointers` might
|
||||
@ -1737,7 +1739,9 @@ fn check_method_receiver<'tcx>(
|
||||
receiver_ty,
|
||||
self_ty,
|
||||
Some(ArbitrarySelfTypesLevel::Basic),
|
||||
) =>
|
||||
generics,
|
||||
)
|
||||
.is_ok() =>
|
||||
{
|
||||
// Report error; would have worked with `arbitrary_self_types`.
|
||||
feature_err(
|
||||
@ -1759,7 +1763,9 @@ fn check_method_receiver<'tcx>(
|
||||
receiver_ty,
|
||||
self_ty,
|
||||
Some(ArbitrarySelfTypesLevel::WithPointers),
|
||||
) =>
|
||||
generics,
|
||||
)
|
||||
.is_ok() =>
|
||||
{
|
||||
// Report error; would have worked with `arbitrary_self_types_pointers`.
|
||||
feature_err(
|
||||
@ -1777,13 +1783,45 @@ fn check_method_receiver<'tcx>(
|
||||
_ =>
|
||||
// Report error; would not have worked with `arbitrary_self_types[_pointers]`.
|
||||
{
|
||||
tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty })
|
||||
match receiver_validity_err {
|
||||
ReceiverValidityError::DoesNotDeref => {
|
||||
tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty })
|
||||
}
|
||||
ReceiverValidityError::MethodGenericParamUsed => {
|
||||
tcx.dcx().emit_err(errors::InvalidGenericReceiverTy { span, receiver_ty })
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Error cases which may be returned from `receiver_is_valid`. These error
|
||||
/// cases are generated in this function as they may be unearthed as we explore
|
||||
/// the `autoderef` chain, but they're converted to diagnostics in the caller.
|
||||
enum ReceiverValidityError {
|
||||
/// The self type does not get to the receiver type by following the
|
||||
/// autoderef chain.
|
||||
DoesNotDeref,
|
||||
/// A type was found which is a method type parameter, and that's not allowed.
|
||||
MethodGenericParamUsed,
|
||||
}
|
||||
|
||||
/// Confirms that a type is not a type parameter referring to one of the
|
||||
/// method's type params.
|
||||
fn confirm_type_is_not_a_method_generic_param(
|
||||
ty: Ty<'_>,
|
||||
method_generics: &ty::Generics,
|
||||
) -> Result<(), ReceiverValidityError> {
|
||||
if let ty::Param(param) = ty.kind() {
|
||||
if (param.index as usize) >= method_generics.parent_count {
|
||||
return Err(ReceiverValidityError::MethodGenericParamUsed);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns whether `receiver_ty` would be considered a valid receiver type for `self_ty`. If
|
||||
/// `arbitrary_self_types` is enabled, `receiver_ty` must transitively deref to `self_ty`, possibly
|
||||
/// through a `*const/mut T` raw pointer if `arbitrary_self_types_pointers` is also enabled.
|
||||
@ -1799,7 +1837,8 @@ fn receiver_is_valid<'tcx>(
|
||||
receiver_ty: Ty<'tcx>,
|
||||
self_ty: Ty<'tcx>,
|
||||
arbitrary_self_types_enabled: Option<ArbitrarySelfTypesLevel>,
|
||||
) -> bool {
|
||||
method_generics: &ty::Generics,
|
||||
) -> Result<(), ReceiverValidityError> {
|
||||
let infcx = wfcx.infcx;
|
||||
let tcx = wfcx.tcx();
|
||||
let cause =
|
||||
@ -1811,9 +1850,11 @@ fn receiver_is_valid<'tcx>(
|
||||
ocx.eq(&cause, wfcx.param_env, self_ty, receiver_ty)?;
|
||||
if ocx.select_all_or_error().is_empty() { Ok(()) } else { Err(NoSolution) }
|
||||
}) {
|
||||
return true;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
confirm_type_is_not_a_method_generic_param(receiver_ty, method_generics)?;
|
||||
|
||||
let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_def_id, span, receiver_ty);
|
||||
|
||||
// The `arbitrary_self_types_pointers` feature allows raw pointer receivers like `self: *const Self`.
|
||||
@ -1830,6 +1871,8 @@ fn receiver_is_valid<'tcx>(
|
||||
potential_self_ty, self_ty
|
||||
);
|
||||
|
||||
confirm_type_is_not_a_method_generic_param(potential_self_ty, method_generics)?;
|
||||
|
||||
// Check if the self type unifies. If it does, then commit the result
|
||||
// since it may have region side-effects.
|
||||
if let Ok(()) = wfcx.infcx.commit_if_ok(|_| {
|
||||
@ -1838,7 +1881,7 @@ fn receiver_is_valid<'tcx>(
|
||||
if ocx.select_all_or_error().is_empty() { Ok(()) } else { Err(NoSolution) }
|
||||
}) {
|
||||
wfcx.register_obligations(autoderef.into_obligations());
|
||||
return true;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Without `feature(arbitrary_self_types)`, we require that each step in the
|
||||
@ -1865,7 +1908,7 @@ fn receiver_is_valid<'tcx>(
|
||||
}
|
||||
|
||||
debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`", receiver_ty, self_ty);
|
||||
false
|
||||
Err(ReceiverValidityError::DoesNotDeref)
|
||||
}
|
||||
|
||||
fn receiver_is_implemented<'tcx>(
|
||||
|
@ -1623,6 +1623,16 @@ pub(crate) struct InvalidReceiverTy<'tcx> {
|
||||
pub receiver_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_invalid_generic_receiver_ty, code = E0801)]
|
||||
#[note]
|
||||
#[help(hir_analysis_invalid_generic_receiver_ty_help)]
|
||||
pub(crate) struct InvalidGenericReceiverTy<'tcx> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub receiver_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_cmse_inputs_stack_spill, code = E0798)]
|
||||
#[note]
|
||||
|
@ -533,9 +533,6 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||
self.register_predicates(obligations);
|
||||
}
|
||||
Err(terr) => {
|
||||
// FIXME(arbitrary_self_types): We probably should limit the
|
||||
// situations where this can occur by adding additional restrictions
|
||||
// to the feature, like the self type can't reference method args.
|
||||
if self.tcx.features().arbitrary_self_types() {
|
||||
self.err_ctxt()
|
||||
.report_mismatched_types(
|
||||
|
@ -32,8 +32,11 @@ pub(crate) struct Formatter<'mir, 'tcx, A>
|
||||
where
|
||||
A: Analysis<'tcx>,
|
||||
{
|
||||
body: &'mir Body<'tcx>,
|
||||
results: RefCell<Option<Results<'tcx, A>>>,
|
||||
// The `RefCell` is used because `<Formatter as Labeller>::node_label`
|
||||
// takes `&self`, but it needs to modify the cursor. This is also the
|
||||
// reason for the `Formatter`/`BlockFormatter` split; `BlockFormatter` has
|
||||
// the operations that involve the mutation, i.e. within the `borrow_mut`.
|
||||
cursor: RefCell<ResultsCursor<'mir, 'tcx, A>>,
|
||||
style: OutputStyle,
|
||||
reachable: BitSet<BasicBlock>,
|
||||
}
|
||||
@ -48,11 +51,15 @@ where
|
||||
style: OutputStyle,
|
||||
) -> Self {
|
||||
let reachable = mir::traversal::reachable_as_bitset(body);
|
||||
Formatter { body, results: Some(results).into(), style, reachable }
|
||||
Formatter { cursor: results.into_results_cursor(body).into(), style, reachable }
|
||||
}
|
||||
|
||||
fn body(&self) -> &'mir Body<'tcx> {
|
||||
self.cursor.borrow().body()
|
||||
}
|
||||
|
||||
pub(crate) fn into_results(self) -> Results<'tcx, A> {
|
||||
self.results.into_inner().unwrap()
|
||||
self.cursor.into_inner().into_results()
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,7 +88,7 @@ where
|
||||
type Edge = CfgEdge;
|
||||
|
||||
fn graph_id(&self) -> dot::Id<'_> {
|
||||
let name = graphviz_safe_def_name(self.body.source.def_id());
|
||||
let name = graphviz_safe_def_name(self.body().source.def_id());
|
||||
dot::Id::new(format!("graph_for_def_id_{name}")).unwrap()
|
||||
}
|
||||
|
||||
@ -90,20 +97,11 @@ where
|
||||
}
|
||||
|
||||
fn node_label(&self, block: &Self::Node) -> dot::LabelText<'_> {
|
||||
let mut label = Vec::new();
|
||||
self.results.replace_with(|results| {
|
||||
// `Formatter::result` is a `RefCell<Option<_>>` so we can replace
|
||||
// the value with `None`, move it into the results cursor, move it
|
||||
// back out, and return it to the refcell wrapped in `Some`.
|
||||
let mut fmt = BlockFormatter {
|
||||
results: results.take().unwrap().into_results_cursor(self.body),
|
||||
style: self.style,
|
||||
bg: Background::Light,
|
||||
};
|
||||
let mut cursor = self.cursor.borrow_mut();
|
||||
let mut fmt =
|
||||
BlockFormatter { cursor: &mut cursor, style: self.style, bg: Background::Light };
|
||||
let label = fmt.write_node_label(*block).unwrap();
|
||||
|
||||
fmt.write_node_label(&mut label, *block).unwrap();
|
||||
Some(fmt.results.into_results())
|
||||
});
|
||||
dot::LabelText::html(String::from_utf8(label).unwrap())
|
||||
}
|
||||
|
||||
@ -112,12 +110,12 @@ where
|
||||
}
|
||||
|
||||
fn edge_label(&self, e: &Self::Edge) -> dot::LabelText<'_> {
|
||||
let label = &self.body[e.source].terminator().kind.fmt_successor_labels()[e.index];
|
||||
let label = &self.body()[e.source].terminator().kind.fmt_successor_labels()[e.index];
|
||||
dot::LabelText::label(label.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx, A> dot::GraphWalk<'mir> for Formatter<'mir, 'tcx, A>
|
||||
impl<'tcx, A> dot::GraphWalk<'_> for Formatter<'_, 'tcx, A>
|
||||
where
|
||||
A: Analysis<'tcx>,
|
||||
{
|
||||
@ -125,7 +123,7 @@ where
|
||||
type Edge = CfgEdge;
|
||||
|
||||
fn nodes(&self) -> dot::Nodes<'_, Self::Node> {
|
||||
self.body
|
||||
self.body()
|
||||
.basic_blocks
|
||||
.indices()
|
||||
.filter(|&idx| self.reachable.contains(idx))
|
||||
@ -134,10 +132,10 @@ where
|
||||
}
|
||||
|
||||
fn edges(&self) -> dot::Edges<'_, Self::Edge> {
|
||||
self.body
|
||||
.basic_blocks
|
||||
let body = self.body();
|
||||
body.basic_blocks
|
||||
.indices()
|
||||
.flat_map(|bb| dataflow_successors(self.body, bb))
|
||||
.flat_map(|bb| dataflow_successors(body, bb))
|
||||
.collect::<Vec<_>>()
|
||||
.into()
|
||||
}
|
||||
@ -147,20 +145,20 @@ where
|
||||
}
|
||||
|
||||
fn target(&self, edge: &Self::Edge) -> Self::Node {
|
||||
self.body[edge.source].terminator().successors().nth(edge.index).unwrap()
|
||||
self.body()[edge.source].terminator().successors().nth(edge.index).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
struct BlockFormatter<'mir, 'tcx, A>
|
||||
struct BlockFormatter<'a, 'mir, 'tcx, A>
|
||||
where
|
||||
A: Analysis<'tcx>,
|
||||
{
|
||||
results: ResultsCursor<'mir, 'tcx, A>,
|
||||
cursor: &'a mut ResultsCursor<'mir, 'tcx, A>,
|
||||
bg: Background,
|
||||
style: OutputStyle,
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx, A> BlockFormatter<'mir, 'tcx, A>
|
||||
impl<'tcx, A> BlockFormatter<'_, '_, 'tcx, A>
|
||||
where
|
||||
A: Analysis<'tcx>,
|
||||
A::Domain: DebugWithContext<A>,
|
||||
@ -173,7 +171,9 @@ where
|
||||
bg
|
||||
}
|
||||
|
||||
fn write_node_label(&mut self, w: &mut impl io::Write, block: BasicBlock) -> io::Result<()> {
|
||||
fn write_node_label(&mut self, block: BasicBlock) -> io::Result<Vec<u8>> {
|
||||
use std::io::Write;
|
||||
|
||||
// Sample output:
|
||||
// +-+-----------------------------------------------+
|
||||
// A | bb4 |
|
||||
@ -200,6 +200,9 @@ where
|
||||
// attributes. Make sure to test the output before trying to remove the redundancy.
|
||||
// Notably, `align` was found to have no effect when applied only to <table>.
|
||||
|
||||
let mut v = vec![];
|
||||
let w = &mut v;
|
||||
|
||||
let table_fmt = concat!(
|
||||
" border=\"1\"",
|
||||
" cellborder=\"1\"",
|
||||
@ -219,8 +222,8 @@ where
|
||||
|
||||
// C: State at start of block
|
||||
self.bg = Background::Light;
|
||||
self.results.seek_to_block_start(block);
|
||||
let block_start_state = self.results.get().clone();
|
||||
self.cursor.seek_to_block_start(block);
|
||||
let block_start_state = self.cursor.get().clone();
|
||||
self.write_row_with_full_state(w, "", "(on start)")?;
|
||||
|
||||
// D + E: Statement and terminator transfer functions
|
||||
@ -228,12 +231,12 @@ where
|
||||
|
||||
// F: State at end of block
|
||||
|
||||
let terminator = self.results.body()[block].terminator();
|
||||
let terminator = self.cursor.body()[block].terminator();
|
||||
|
||||
// Write the full dataflow state immediately after the terminator if it differs from the
|
||||
// state at block entry.
|
||||
self.results.seek_to_block_end(block);
|
||||
if self.results.get() != &block_start_state || A::Direction::IS_BACKWARD {
|
||||
self.cursor.seek_to_block_end(block);
|
||||
if self.cursor.get() != &block_start_state || A::Direction::IS_BACKWARD {
|
||||
let after_terminator_name = match terminator.kind {
|
||||
mir::TerminatorKind::Call { target: Some(_), .. } => "(on unwind)",
|
||||
_ => "(on end)",
|
||||
@ -250,8 +253,8 @@ where
|
||||
match terminator.kind {
|
||||
mir::TerminatorKind::Call { destination, .. } => {
|
||||
self.write_row(w, "", "(on successful return)", |this, w, fmt| {
|
||||
let state_on_unwind = this.results.get().clone();
|
||||
this.results.apply_custom_effect(|analysis, state| {
|
||||
let state_on_unwind = this.cursor.get().clone();
|
||||
this.cursor.apply_custom_effect(|analysis, state| {
|
||||
analysis.apply_call_return_effect(
|
||||
state,
|
||||
block,
|
||||
@ -265,9 +268,9 @@ where
|
||||
colspan = this.style.num_state_columns(),
|
||||
fmt = fmt,
|
||||
diff = diff_pretty(
|
||||
this.results.get(),
|
||||
this.cursor.get(),
|
||||
&state_on_unwind,
|
||||
this.results.analysis()
|
||||
this.cursor.analysis()
|
||||
),
|
||||
)
|
||||
})?;
|
||||
@ -275,8 +278,8 @@ where
|
||||
|
||||
mir::TerminatorKind::Yield { resume, resume_arg, .. } => {
|
||||
self.write_row(w, "", "(on yield resume)", |this, w, fmt| {
|
||||
let state_on_coroutine_drop = this.results.get().clone();
|
||||
this.results.apply_custom_effect(|analysis, state| {
|
||||
let state_on_coroutine_drop = this.cursor.get().clone();
|
||||
this.cursor.apply_custom_effect(|analysis, state| {
|
||||
analysis.apply_call_return_effect(
|
||||
state,
|
||||
resume,
|
||||
@ -290,9 +293,9 @@ where
|
||||
colspan = this.style.num_state_columns(),
|
||||
fmt = fmt,
|
||||
diff = diff_pretty(
|
||||
this.results.get(),
|
||||
this.cursor.get(),
|
||||
&state_on_coroutine_drop,
|
||||
this.results.analysis()
|
||||
this.cursor.analysis()
|
||||
),
|
||||
)
|
||||
})?;
|
||||
@ -302,8 +305,8 @@ where
|
||||
if !targets.is_empty() =>
|
||||
{
|
||||
self.write_row(w, "", "(on successful return)", |this, w, fmt| {
|
||||
let state_on_unwind = this.results.get().clone();
|
||||
this.results.apply_custom_effect(|analysis, state| {
|
||||
let state_on_unwind = this.cursor.get().clone();
|
||||
this.cursor.apply_custom_effect(|analysis, state| {
|
||||
analysis.apply_call_return_effect(
|
||||
state,
|
||||
block,
|
||||
@ -317,9 +320,9 @@ where
|
||||
colspan = this.style.num_state_columns(),
|
||||
fmt = fmt,
|
||||
diff = diff_pretty(
|
||||
this.results.get(),
|
||||
this.cursor.get(),
|
||||
&state_on_unwind,
|
||||
this.results.analysis()
|
||||
this.cursor.analysis()
|
||||
),
|
||||
)
|
||||
})?;
|
||||
@ -328,7 +331,9 @@ where
|
||||
_ => {}
|
||||
};
|
||||
|
||||
write!(w, "</table>")
|
||||
write!(w, "</table>")?;
|
||||
|
||||
Ok(v)
|
||||
}
|
||||
|
||||
fn write_block_header_simple(
|
||||
@ -407,9 +412,9 @@ where
|
||||
block: BasicBlock,
|
||||
) -> io::Result<()> {
|
||||
let diffs = StateDiffCollector::run(
|
||||
self.results.body(),
|
||||
self.cursor.body(),
|
||||
block,
|
||||
self.results.mut_results(),
|
||||
self.cursor.mut_results(),
|
||||
self.style,
|
||||
);
|
||||
|
||||
@ -420,7 +425,7 @@ where
|
||||
if A::Direction::IS_FORWARD { it.next().unwrap() } else { it.next_back().unwrap() }
|
||||
};
|
||||
|
||||
for (i, statement) in self.results.body()[block].statements.iter().enumerate() {
|
||||
for (i, statement) in self.cursor.body()[block].statements.iter().enumerate() {
|
||||
let statement_str = format!("{statement:?}");
|
||||
let index_str = format!("{i}");
|
||||
|
||||
@ -442,7 +447,7 @@ where
|
||||
assert!(diffs_after.is_empty());
|
||||
assert!(diffs_before.as_ref().map_or(true, ExactSizeIterator::is_empty));
|
||||
|
||||
let terminator = self.results.body()[block].terminator();
|
||||
let terminator = self.cursor.body()[block].terminator();
|
||||
let mut terminator_str = String::new();
|
||||
terminator.kind.fmt_head(&mut terminator_str).unwrap();
|
||||
|
||||
@ -492,8 +497,8 @@ where
|
||||
mir: &str,
|
||||
) -> io::Result<()> {
|
||||
self.write_row(w, i, mir, |this, w, fmt| {
|
||||
let state = this.results.get();
|
||||
let analysis = this.results.analysis();
|
||||
let state = this.cursor.get();
|
||||
let analysis = this.cursor.analysis();
|
||||
|
||||
// FIXME: The full state vector can be quite long. It would be nice to split on commas
|
||||
// and use some text wrapping algorithm.
|
||||
|
@ -84,7 +84,7 @@ fn current_dll_path() -> Result<PathBuf, String> {
|
||||
loop {
|
||||
if libc::loadquery(
|
||||
libc::L_GETINFO,
|
||||
buffer.as_mut_ptr() as *mut i8,
|
||||
buffer.as_mut_ptr() as *mut u8,
|
||||
(std::mem::size_of::<libc::ld_info>() * buffer.len()) as u32,
|
||||
) >= 0
|
||||
{
|
||||
|
@ -198,10 +198,6 @@ fn generate_mergeable_doctest(
|
||||
} else {
|
||||
writeln!(output, "mod {test_id} {{\n{}{}", doctest.crates, doctest.maybe_crate_attrs)
|
||||
.unwrap();
|
||||
if scraped_test.langstr.no_run {
|
||||
// To prevent having warnings about unused items since they're not called.
|
||||
writeln!(output, "#![allow(unused)]").unwrap();
|
||||
}
|
||||
if doctest.has_main_fn {
|
||||
output.push_str(&doctest.everything_else);
|
||||
} else {
|
||||
|
@ -18,6 +18,7 @@ build_helper = { path = "../build_helper" }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }
|
||||
regex = "1.0"
|
||||
semver = { version = "1.0.23", features = ["serde"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
rustfix = "0.8.1"
|
||||
|
@ -7,6 +7,7 @@ use std::sync::OnceLock;
|
||||
use std::{fmt, iter};
|
||||
|
||||
use build_helper::git::GitConfig;
|
||||
use semver::Version;
|
||||
use serde::de::{Deserialize, Deserializer, Error as _};
|
||||
use test::{ColorConfig, OutputFormat};
|
||||
|
||||
@ -298,7 +299,7 @@ pub struct Config {
|
||||
pub lldb_version: Option<u32>,
|
||||
|
||||
/// Version of LLVM
|
||||
pub llvm_version: Option<u32>,
|
||||
pub llvm_version: Option<Version>,
|
||||
|
||||
/// Is LLVM a system LLVM
|
||||
pub system_llvm: bool,
|
||||
|
@ -6,6 +6,7 @@ use std::io::prelude::*;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
|
||||
use semver::Version;
|
||||
use tracing::*;
|
||||
|
||||
use crate::common::{Config, Debugger, FailMode, Mode, PassMode};
|
||||
@ -1113,26 +1114,39 @@ fn parse_normalize_rule(header: &str) -> Option<(String, String)> {
|
||||
Some((regex, replacement))
|
||||
}
|
||||
|
||||
pub fn extract_llvm_version(version: &str) -> Option<u32> {
|
||||
let pat = |c: char| !c.is_ascii_digit() && c != '.';
|
||||
let version_without_suffix = match version.find(pat) {
|
||||
Some(pos) => &version[..pos],
|
||||
/// Given an llvm version string that looks like `1.2.3-rc1`, extract as semver. Note that this
|
||||
/// accepts more than just strict `semver` syntax (as in `major.minor.patch`); this permits omitting
|
||||
/// minor and patch version components so users can write e.g. `//@ min-llvm-version: 19` instead of
|
||||
/// having to write `//@ min-llvm-version: 19.0.0`.
|
||||
///
|
||||
/// Currently panics if the input string is malformed, though we really should not use panic as an
|
||||
/// error handling strategy.
|
||||
///
|
||||
/// FIXME(jieyouxu): improve error handling
|
||||
pub fn extract_llvm_version(version: &str) -> Version {
|
||||
// The version substring we're interested in usually looks like the `1.2.3`, without any of the
|
||||
// fancy suffix like `-rc1` or `meow`.
|
||||
let version = version.trim();
|
||||
let uninterested = |c: char| !c.is_ascii_digit() && c != '.';
|
||||
let version_without_suffix = match version.split_once(uninterested) {
|
||||
Some((prefix, _suffix)) => prefix,
|
||||
None => version,
|
||||
};
|
||||
let components: Vec<u32> = version_without_suffix
|
||||
|
||||
let components: Vec<u64> = version_without_suffix
|
||||
.split('.')
|
||||
.map(|s| s.parse().expect("Malformed version component"))
|
||||
.map(|s| s.parse().expect("llvm version component should consist of only digits"))
|
||||
.collect();
|
||||
let version = match *components {
|
||||
[a] => a * 10_000,
|
||||
[a, b] => a * 10_000 + b * 100,
|
||||
[a, b, c] => a * 10_000 + b * 100 + c,
|
||||
_ => panic!("Malformed version"),
|
||||
};
|
||||
Some(version)
|
||||
|
||||
match &components[..] {
|
||||
[major] => Version::new(*major, 0, 0),
|
||||
[major, minor] => Version::new(*major, *minor, 0),
|
||||
[major, minor, patch] => Version::new(*major, *minor, *patch),
|
||||
_ => panic!("malformed llvm version string, expected only 1-3 components: {version}"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extract_llvm_version_from_binary(binary_path: &str) -> Option<u32> {
|
||||
pub fn extract_llvm_version_from_binary(binary_path: &str) -> Option<Version> {
|
||||
let output = Command::new(binary_path).arg("--version").output().ok()?;
|
||||
if !output.status.success() {
|
||||
return None;
|
||||
@ -1140,7 +1154,7 @@ pub fn extract_llvm_version_from_binary(binary_path: &str) -> Option<u32> {
|
||||
let version = String::from_utf8(output.stdout).ok()?;
|
||||
for line in version.lines() {
|
||||
if let Some(version) = line.split("LLVM version ").nth(1) {
|
||||
return extract_llvm_version(version);
|
||||
return Some(extract_llvm_version(version));
|
||||
}
|
||||
}
|
||||
None
|
||||
@ -1247,15 +1261,17 @@ pub fn llvm_has_libzstd(config: &Config) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
/// Takes a directive of the form `"<version1> [- <version2>]"`,
|
||||
/// returns the numeric representation of `<version1>` and `<version2>` as
|
||||
/// tuple: `(<version1> as u32, <version2> as u32)`.
|
||||
/// Takes a directive of the form `"<version1> [- <version2>]"`, returns the numeric representation
|
||||
/// of `<version1>` and `<version2>` as tuple: `(<version1>, <version2>)`.
|
||||
///
|
||||
/// If the `<version2>` part is omitted, the second component of the tuple
|
||||
/// is the same as `<version1>`.
|
||||
fn extract_version_range<F>(line: &str, parse: F) -> Option<(u32, u32)>
|
||||
/// If the `<version2>` part is omitted, the second component of the tuple is the same as
|
||||
/// `<version1>`.
|
||||
fn extract_version_range<'a, F, VersionTy: Clone>(
|
||||
line: &'a str,
|
||||
parse: F,
|
||||
) -> Option<(VersionTy, VersionTy)>
|
||||
where
|
||||
F: Fn(&str) -> Option<u32>,
|
||||
F: Fn(&'a str) -> Option<VersionTy>,
|
||||
{
|
||||
let mut splits = line.splitn(2, "- ").map(str::trim);
|
||||
let min = splits.next().unwrap();
|
||||
@ -1273,7 +1289,7 @@ where
|
||||
let max = match max {
|
||||
Some("") => return None,
|
||||
Some(max) => parse(max)?,
|
||||
_ => min,
|
||||
_ => min.clone(),
|
||||
};
|
||||
|
||||
Some((min, max))
|
||||
@ -1489,43 +1505,55 @@ fn ignore_llvm(config: &Config, line: &str) -> IgnoreDecision {
|
||||
};
|
||||
}
|
||||
}
|
||||
if let Some(actual_version) = config.llvm_version {
|
||||
if let Some(rest) = line.strip_prefix("min-llvm-version:").map(str::trim) {
|
||||
let min_version = extract_llvm_version(rest).unwrap();
|
||||
// Ignore if actual version is smaller the minimum required
|
||||
// version
|
||||
if actual_version < min_version {
|
||||
if let Some(actual_version) = &config.llvm_version {
|
||||
// Note that these `min` versions will check for not just major versions.
|
||||
|
||||
if let Some(version_string) = config.parse_name_value_directive(line, "min-llvm-version") {
|
||||
let min_version = extract_llvm_version(&version_string);
|
||||
// Ignore if actual version is smaller than the minimum required version.
|
||||
if *actual_version < min_version {
|
||||
return IgnoreDecision::Ignore {
|
||||
reason: format!("ignored when the LLVM version is older than {rest}"),
|
||||
reason: format!(
|
||||
"ignored when the LLVM version {actual_version} is older than {min_version}"
|
||||
),
|
||||
};
|
||||
}
|
||||
} else if let Some(rest) = line.strip_prefix("min-system-llvm-version:").map(str::trim) {
|
||||
let min_version = extract_llvm_version(rest).unwrap();
|
||||
} else if let Some(version_string) =
|
||||
config.parse_name_value_directive(line, "min-system-llvm-version")
|
||||
{
|
||||
let min_version = extract_llvm_version(&version_string);
|
||||
// Ignore if using system LLVM and actual version
|
||||
// is smaller the minimum required version
|
||||
if config.system_llvm && actual_version < min_version {
|
||||
if config.system_llvm && *actual_version < min_version {
|
||||
return IgnoreDecision::Ignore {
|
||||
reason: format!("ignored when the system LLVM version is older than {rest}"),
|
||||
reason: format!(
|
||||
"ignored when the system LLVM version {actual_version} is older than {min_version}"
|
||||
),
|
||||
};
|
||||
}
|
||||
} else if let Some(rest) = line.strip_prefix("ignore-llvm-version:").map(str::trim) {
|
||||
} else if let Some(version_range) =
|
||||
config.parse_name_value_directive(line, "ignore-llvm-version")
|
||||
{
|
||||
// Syntax is: "ignore-llvm-version: <version1> [- <version2>]"
|
||||
let (v_min, v_max) =
|
||||
extract_version_range(rest, extract_llvm_version).unwrap_or_else(|| {
|
||||
panic!("couldn't parse version range: {:?}", rest);
|
||||
});
|
||||
extract_version_range(&version_range, |s| Some(extract_llvm_version(s)))
|
||||
.unwrap_or_else(|| {
|
||||
panic!("couldn't parse version range: \"{version_range}\"");
|
||||
});
|
||||
if v_max < v_min {
|
||||
panic!("Malformed LLVM version range: max < min")
|
||||
panic!("malformed LLVM version range where {v_max} < {v_min}")
|
||||
}
|
||||
// Ignore if version lies inside of range.
|
||||
if actual_version >= v_min && actual_version <= v_max {
|
||||
if *actual_version >= v_min && *actual_version <= v_max {
|
||||
if v_min == v_max {
|
||||
return IgnoreDecision::Ignore {
|
||||
reason: format!("ignored when the LLVM version is {rest}"),
|
||||
reason: format!("ignored when the LLVM version is {actual_version}"),
|
||||
};
|
||||
} else {
|
||||
return IgnoreDecision::Ignore {
|
||||
reason: format!("ignored when the LLVM version is between {rest}"),
|
||||
reason: format!(
|
||||
"ignored when the LLVM version is between {v_min} and {v_max}"
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,13 @@
|
||||
use std::io::Read;
|
||||
use std::path::Path;
|
||||
|
||||
use super::iter_header;
|
||||
use semver::Version;
|
||||
|
||||
use super::{
|
||||
EarlyProps, HeadersCache, extract_llvm_version, extract_version_range, iter_header,
|
||||
parse_normalize_rule,
|
||||
};
|
||||
use crate::common::{Config, Debugger, Mode};
|
||||
use crate::header::{EarlyProps, HeadersCache, parse_normalize_rule};
|
||||
|
||||
fn make_test_description<R: Read>(
|
||||
config: &Config,
|
||||
@ -408,18 +412,66 @@ fn channel() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_version_range() {
|
||||
use super::{extract_llvm_version, extract_version_range};
|
||||
fn test_extract_llvm_version() {
|
||||
// Note: officially, semver *requires* that versions at the minimum have all three
|
||||
// `major.minor.patch` numbers, though for test-writer's convenience we allow omitting the minor
|
||||
// and patch numbers (which will be stubbed out as 0).
|
||||
assert_eq!(extract_llvm_version("0"), Version::new(0, 0, 0));
|
||||
assert_eq!(extract_llvm_version("0.0"), Version::new(0, 0, 0));
|
||||
assert_eq!(extract_llvm_version("0.0.0"), Version::new(0, 0, 0));
|
||||
assert_eq!(extract_llvm_version("1"), Version::new(1, 0, 0));
|
||||
assert_eq!(extract_llvm_version("1.2"), Version::new(1, 2, 0));
|
||||
assert_eq!(extract_llvm_version("1.2.3"), Version::new(1, 2, 3));
|
||||
assert_eq!(extract_llvm_version("4.5.6git"), Version::new(4, 5, 6));
|
||||
assert_eq!(extract_llvm_version("4.5.6-rc1"), Version::new(4, 5, 6));
|
||||
assert_eq!(extract_llvm_version("123.456.789-rc1"), Version::new(123, 456, 789));
|
||||
assert_eq!(extract_llvm_version("8.1.2-rust"), Version::new(8, 1, 2));
|
||||
assert_eq!(extract_llvm_version("9.0.1-rust-1.43.0-dev"), Version::new(9, 0, 1));
|
||||
assert_eq!(extract_llvm_version("9.3.1-rust-1.43.0-dev"), Version::new(9, 3, 1));
|
||||
assert_eq!(extract_llvm_version("10.0.0-rust"), Version::new(10, 0, 0));
|
||||
assert_eq!(extract_llvm_version("11.1.0"), Version::new(11, 1, 0));
|
||||
assert_eq!(extract_llvm_version("12.0.0libcxx"), Version::new(12, 0, 0));
|
||||
assert_eq!(extract_llvm_version("12.0.0-rc3"), Version::new(12, 0, 0));
|
||||
assert_eq!(extract_llvm_version("13.0.0git"), Version::new(13, 0, 0));
|
||||
}
|
||||
|
||||
assert_eq!(extract_version_range("1.2.3 - 4.5.6", extract_llvm_version), Some((10203, 40506)));
|
||||
assert_eq!(extract_version_range("0 - 4.5.6", extract_llvm_version), Some((0, 40506)));
|
||||
assert_eq!(extract_version_range("1.2.3 -", extract_llvm_version), None);
|
||||
assert_eq!(extract_version_range("1.2.3 - ", extract_llvm_version), None);
|
||||
assert_eq!(extract_version_range("- 4.5.6", extract_llvm_version), None);
|
||||
assert_eq!(extract_version_range("-", extract_llvm_version), None);
|
||||
assert_eq!(extract_version_range(" - 4.5.6", extract_llvm_version), None);
|
||||
assert_eq!(extract_version_range(" - 4.5.6", extract_llvm_version), None);
|
||||
assert_eq!(extract_version_range("0 -", extract_llvm_version), None);
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_llvm_version_invalid_components() {
|
||||
extract_llvm_version("4.x.6");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_llvm_version_invalid_prefix() {
|
||||
extract_llvm_version("meow4.5.6");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_llvm_version_too_many_components() {
|
||||
extract_llvm_version("4.5.6.7");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_version_range() {
|
||||
let wrapped_extract = |s: &str| Some(extract_llvm_version(s));
|
||||
|
||||
assert_eq!(
|
||||
extract_version_range("1.2.3 - 4.5.6", wrapped_extract),
|
||||
Some((Version::new(1, 2, 3), Version::new(4, 5, 6)))
|
||||
);
|
||||
assert_eq!(
|
||||
extract_version_range("0 - 4.5.6", wrapped_extract),
|
||||
Some((Version::new(0, 0, 0), Version::new(4, 5, 6)))
|
||||
);
|
||||
assert_eq!(extract_version_range("1.2.3 -", wrapped_extract), None);
|
||||
assert_eq!(extract_version_range("1.2.3 - ", wrapped_extract), None);
|
||||
assert_eq!(extract_version_range("- 4.5.6", wrapped_extract), None);
|
||||
assert_eq!(extract_version_range("-", wrapped_extract), None);
|
||||
assert_eq!(extract_version_range(" - 4.5.6", wrapped_extract), None);
|
||||
assert_eq!(extract_version_range(" - 4.5.6", wrapped_extract), None);
|
||||
assert_eq!(extract_version_range("0 -", wrapped_extract), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -228,7 +228,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
||||
Some(x) => panic!("argument for --color must be auto, always, or never, but found `{}`", x),
|
||||
};
|
||||
let llvm_version =
|
||||
matches.opt_str("llvm-version").as_deref().and_then(header::extract_llvm_version).or_else(
|
||||
matches.opt_str("llvm-version").as_deref().map(header::extract_llvm_version).or_else(
|
||||
|| header::extract_llvm_version_from_binary(&matches.opt_str("llvm-filecheck")?),
|
||||
);
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
use std::ffi::OsString;
|
||||
|
||||
use crate::debuggers::{extract_gdb_version, extract_lldb_version};
|
||||
use crate::header::extract_llvm_version;
|
||||
use crate::is_test;
|
||||
|
||||
#[test]
|
||||
@ -67,15 +66,3 @@ fn is_test_test() {
|
||||
assert!(!is_test(&OsString::from("#a_dog_gif")));
|
||||
assert!(!is_test(&OsString::from("~a_temp_file")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_llvm_version() {
|
||||
assert_eq!(extract_llvm_version("8.1.2-rust"), Some(80102));
|
||||
assert_eq!(extract_llvm_version("9.0.1-rust-1.43.0-dev"), Some(90001));
|
||||
assert_eq!(extract_llvm_version("9.3.1-rust-1.43.0-dev"), Some(90301));
|
||||
assert_eq!(extract_llvm_version("10.0.0-rust"), Some(100000));
|
||||
assert_eq!(extract_llvm_version("11.1.0"), Some(110100));
|
||||
assert_eq!(extract_llvm_version("12.0.0libcxx"), Some(120000));
|
||||
assert_eq!(extract_llvm_version("12.0.0-rc3"), Some(120000));
|
||||
assert_eq!(extract_llvm_version("13.0.0git"), Some(130000));
|
||||
}
|
||||
|
@ -4102,7 +4102,6 @@ ui/type-alias-impl-trait/issue-53678-coroutine-and-const-fn.rs
|
||||
ui/type-alias-impl-trait/issue-55099-lifetime-inference.rs
|
||||
ui/type-alias-impl-trait/issue-57188-associate-impl-capture.rs
|
||||
ui/type-alias-impl-trait/issue-57611-trait-alias.rs
|
||||
ui/type-alias-impl-trait/issue-57700.rs
|
||||
ui/type-alias-impl-trait/issue-57807-associated-type.rs
|
||||
ui/type-alias-impl-trait/issue-57961.rs
|
||||
ui/type-alias-impl-trait/issue-58662-coroutine-with-lifetime.rs
|
||||
|
15
tests/rustdoc-ui/doctest/dead-code-2024.rs
Normal file
15
tests/rustdoc-ui/doctest/dead-code-2024.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// This test ensures that the 2024 edition merged doctest will not use `#[allow(unused)]`.
|
||||
|
||||
//@ compile-flags:--test -Zunstable-options --edition 2024
|
||||
//@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
|
||||
//@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME"
|
||||
//@ failure-status: 101
|
||||
|
||||
#![doc(test(attr(allow(unused_variables), deny(warnings))))]
|
||||
|
||||
/// Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// trait T { fn f(); }
|
||||
/// ```
|
||||
pub fn f() {}
|
29
tests/rustdoc-ui/doctest/dead-code-2024.stdout
Normal file
29
tests/rustdoc-ui/doctest/dead-code-2024.stdout
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
running 1 test
|
||||
test $DIR/dead-code-2024.rs - f (line 12) - compile ... FAILED
|
||||
|
||||
failures:
|
||||
|
||||
---- $DIR/dead-code-2024.rs - f (line 12) stdout ----
|
||||
error: trait `T` is never used
|
||||
--> $DIR/dead-code-2024.rs:13:7
|
||||
|
|
||||
LL | trait T { fn f(); }
|
||||
| ^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/dead-code-2024.rs:11:9
|
||||
|
|
||||
LL | #![deny(warnings)]
|
||||
| ^^^^^^^^
|
||||
= note: `#[deny(dead_code)]` implied by `#[deny(warnings)]`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
Couldn't compile the test.
|
||||
|
||||
failures:
|
||||
$DIR/dead-code-2024.rs - f (line 12)
|
||||
|
||||
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
|
||||
|
15
tests/rustdoc-ui/doctest/dead-code.rs
Normal file
15
tests/rustdoc-ui/doctest/dead-code.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// This test ensures that the doctest will not use `#[allow(unused)]`.
|
||||
|
||||
//@ compile-flags:--test
|
||||
//@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
|
||||
//@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME"
|
||||
//@ failure-status: 101
|
||||
|
||||
#![doc(test(attr(allow(unused_variables), deny(warnings))))]
|
||||
|
||||
/// Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// trait T { fn f(); }
|
||||
/// ```
|
||||
pub fn f() {}
|
29
tests/rustdoc-ui/doctest/dead-code.stdout
Normal file
29
tests/rustdoc-ui/doctest/dead-code.stdout
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
running 1 test
|
||||
test $DIR/dead-code.rs - f (line 12) - compile ... FAILED
|
||||
|
||||
failures:
|
||||
|
||||
---- $DIR/dead-code.rs - f (line 12) stdout ----
|
||||
error: trait `T` is never used
|
||||
--> $DIR/dead-code.rs:13:7
|
||||
|
|
||||
LL | trait T { fn f(); }
|
||||
| ^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/dead-code.rs:11:9
|
||||
|
|
||||
LL | #![deny(warnings)]
|
||||
| ^^^^^^^^
|
||||
= note: `#[deny(dead_code)]` implied by `#[deny(warnings)]`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
Couldn't compile the test.
|
||||
|
||||
failures:
|
||||
$DIR/dead-code.rs - f (line 12)
|
||||
|
||||
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
|
||||
|
@ -8,7 +8,7 @@ use std::ops::Deref;
|
||||
struct Foo(u32);
|
||||
impl Foo {
|
||||
const fn get<R: Deref<Target = Self>>(self: R) -> u32 {
|
||||
//~^ ERROR: `R` cannot be used as the type of `self`
|
||||
//~^ ERROR invalid generic `self` parameter type
|
||||
//~| ERROR destructor of `R` cannot be evaluated at compile-time
|
||||
self.0
|
||||
//~^ ERROR cannot call non-const fn `<R as Deref>::deref` in constant function
|
||||
|
@ -15,18 +15,16 @@ LL | const fn get<R: Deref<Target = Self>>(self: R) -> u32 {
|
||||
LL | }
|
||||
| - value is dropped here
|
||||
|
||||
error[E0658]: `R` cannot be used as the type of `self` without the `arbitrary_self_types` feature
|
||||
error[E0801]: invalid generic `self` parameter type: `R`
|
||||
--> $DIR/arbitrary-self-from-method-substs-ice.rs:10:49
|
||||
|
|
||||
LL | const fn get<R: Deref<Target = Self>>(self: R) -> u32 {
|
||||
| ^
|
||||
|
|
||||
= note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
|
||||
= help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
= help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
|
||||
= note: type of `self` must not be a method generic parameter type
|
||||
= help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0015, E0493, E0658.
|
||||
Some errors have detailed explanations: E0015, E0493, E0801.
|
||||
For more information about an error, try `rustc --explain E0015`.
|
||||
|
@ -1,14 +1,168 @@
|
||||
error[E0658]: `R` cannot be used as the type of `self` without the `arbitrary_self_types` feature
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:8:43
|
||||
error[E0801]: invalid generic `self` parameter type: `R`
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:9:43
|
||||
|
|
||||
LL | fn get<R: Deref<Target = Self>>(self: R) -> u32 {
|
||||
| ^
|
||||
|
|
||||
= note: type of `self` must not be a method generic parameter type
|
||||
= help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
|
||||
|
||||
error[E0801]: invalid generic `self` parameter type: `&R`
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:13:44
|
||||
|
|
||||
LL | fn get1<R: Deref<Target = Self>>(self: &R) -> u32 {
|
||||
| ^^
|
||||
|
|
||||
= note: type of `self` must not be a method generic parameter type
|
||||
= help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
|
||||
|
||||
error[E0801]: invalid generic `self` parameter type: `&mut R`
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:17:44
|
||||
|
|
||||
LL | fn get2<R: Deref<Target = Self>>(self: &mut R) -> u32 {
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: type of `self` must not be a method generic parameter type
|
||||
= help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
|
||||
|
||||
error[E0801]: invalid generic `self` parameter type: `Rc<R>`
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:21:44
|
||||
|
|
||||
LL | fn get3<R: Deref<Target = Self>>(self: std::rc::Rc<R>) -> u32 {
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: type of `self` must not be a method generic parameter type
|
||||
= help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
|
||||
|
||||
error[E0801]: invalid generic `self` parameter type: `&Rc<R>`
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:25:44
|
||||
|
|
||||
LL | fn get4<R: Deref<Target = Self>>(self: &std::rc::Rc<R>) -> u32 {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: type of `self` must not be a method generic parameter type
|
||||
= help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
|
||||
|
||||
error[E0801]: invalid generic `self` parameter type: `Rc<&R>`
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:29:44
|
||||
|
|
||||
LL | fn get5<R: Deref<Target = Self>>(self: std::rc::Rc<&R>) -> u32 {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: type of `self` must not be a method generic parameter type
|
||||
= help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
|
||||
|
||||
error[E0658]: `<FR as FindReceiver>::Receiver` cannot be used as the type of `self` without the `arbitrary_self_types` feature
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:33:37
|
||||
|
|
||||
LL | fn get6<FR: FindReceiver>(self: FR::Receiver, other: FR) -> u32 {
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
|
||||
= help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
= help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
error[E0658]: `R` cannot be used as the type of `self` without the `arbitrary_self_types` feature
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:61:18
|
||||
|
|
||||
LL | fn get(self: R) {}
|
||||
| ^
|
||||
|
|
||||
= note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
|
||||
= help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
= help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
error[E0271]: type mismatch resolving `<Silly as FindReceiver>::Receiver == Foo`
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:92:9
|
||||
|
|
||||
LL | foo.get6(Silly);
|
||||
| ^^^^ type mismatch resolving `<Silly as FindReceiver>::Receiver == Foo`
|
||||
|
|
||||
note: expected this to be `Foo`
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:71:21
|
||||
|
|
||||
LL | type Receiver = std::rc::Rc<Foo>;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
= note: expected struct `Foo`
|
||||
found struct `Rc<Foo>`
|
||||
|
||||
error[E0271]: type mismatch resolving `<Silly as FindReceiver>::Receiver == &Foo`
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:96:9
|
||||
|
|
||||
LL | foo.get6(Silly);
|
||||
| ^^^^ type mismatch resolving `<Silly as FindReceiver>::Receiver == &Foo`
|
||||
|
|
||||
note: expected this to be `&Foo`
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:71:21
|
||||
|
|
||||
LL | type Receiver = std::rc::Rc<Foo>;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
= note: expected reference `&Foo`
|
||||
found struct `Rc<Foo>`
|
||||
|
||||
error[E0599]: the method `get` exists for struct `Rc<Bar<_>>`, but its trait bounds were not satisfied
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:100:7
|
||||
|
|
||||
LL | struct Bar<R>(std::marker::PhantomData<R>);
|
||||
| ------------- doesn't satisfy `Bar<_>: Deref`
|
||||
...
|
||||
LL | t.get();
|
||||
| ^^^ method cannot be called on `Rc<Bar<_>>` due to unsatisfied trait bounds
|
||||
|
|
||||
note: the following trait bounds were not satisfied:
|
||||
`<&Bar<_> as Deref>::Target = Bar<&Bar<_>>`
|
||||
`<&Rc<Bar<_>> as Deref>::Target = Bar<&Rc<Bar<_>>>`
|
||||
`<&mut Bar<_> as Deref>::Target = Bar<&mut Bar<_>>`
|
||||
`<&mut Rc<Bar<_>> as Deref>::Target = Bar<&mut Rc<Bar<_>>>`
|
||||
`<Rc<Bar<_>> as Deref>::Target = Bar<Rc<Bar<_>>>`
|
||||
`Bar<_>: Deref`
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:60:9
|
||||
|
|
||||
LL | impl<R: std::ops::Deref<Target = Self>> Bar<R> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------
|
||||
| | |
|
||||
| | unsatisfied trait bound introduced here
|
||||
| unsatisfied trait bound introduced here
|
||||
note: the trait `Deref` must be implemented
|
||||
--> $SRC_DIR/core/src/ops/deref.rs:LL:COL
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
= note: the following trait defines an item `get`, perhaps you need to implement it:
|
||||
candidate #1: `SliceIndex`
|
||||
|
||||
error[E0599]: the method `get` exists for reference `&Rc<Bar<_>>`, but its trait bounds were not satisfied
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:108:7
|
||||
|
|
||||
LL | struct Bar<R>(std::marker::PhantomData<R>);
|
||||
| ------------- doesn't satisfy `Bar<_>: Deref`
|
||||
...
|
||||
LL | t.get();
|
||||
| ^^^ method cannot be called on `&Rc<Bar<_>>` due to unsatisfied trait bounds
|
||||
|
|
||||
note: the following trait bounds were not satisfied:
|
||||
`<&&Rc<Bar<_>> as Deref>::Target = Bar<&&Rc<Bar<_>>>`
|
||||
`<&Bar<_> as Deref>::Target = Bar<&Bar<_>>`
|
||||
`<&Rc<Bar<_>> as Deref>::Target = Bar<&Rc<Bar<_>>>`
|
||||
`<&mut &Rc<Bar<_>> as Deref>::Target = Bar<&mut &Rc<Bar<_>>>`
|
||||
`<&mut Bar<_> as Deref>::Target = Bar<&mut Bar<_>>`
|
||||
`<&mut Rc<Bar<_>> as Deref>::Target = Bar<&mut Rc<Bar<_>>>`
|
||||
`<Rc<Bar<_>> as Deref>::Target = Bar<Rc<Bar<_>>>`
|
||||
`Bar<_>: Deref`
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:60:9
|
||||
|
|
||||
LL | impl<R: std::ops::Deref<Target = Self>> Bar<R> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------
|
||||
| | |
|
||||
| | unsatisfied trait bound introduced here
|
||||
| unsatisfied trait bound introduced here
|
||||
note: the trait `Deref` must be implemented
|
||||
--> $SRC_DIR/core/src/ops/deref.rs:LL:COL
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
= note: the following trait defines an item `get`, perhaps you need to implement it:
|
||||
candidate #1: `SliceIndex`
|
||||
|
||||
error: aborting due to 12 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0271, E0599, E0658, E0801.
|
||||
For more information about an error, try `rustc --explain E0271`.
|
||||
|
@ -1,9 +1,179 @@
|
||||
error[E0801]: invalid generic `self` parameter type: `R`
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:9:43
|
||||
|
|
||||
LL | fn get<R: Deref<Target = Self>>(self: R) -> u32 {
|
||||
| ^
|
||||
|
|
||||
= note: type of `self` must not be a method generic parameter type
|
||||
= help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
|
||||
|
||||
error[E0801]: invalid generic `self` parameter type: `&R`
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:13:44
|
||||
|
|
||||
LL | fn get1<R: Deref<Target = Self>>(self: &R) -> u32 {
|
||||
| ^^
|
||||
|
|
||||
= note: type of `self` must not be a method generic parameter type
|
||||
= help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
|
||||
|
||||
error[E0801]: invalid generic `self` parameter type: `&mut R`
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:17:44
|
||||
|
|
||||
LL | fn get2<R: Deref<Target = Self>>(self: &mut R) -> u32 {
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: type of `self` must not be a method generic parameter type
|
||||
= help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
|
||||
|
||||
error[E0801]: invalid generic `self` parameter type: `Rc<R>`
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:21:44
|
||||
|
|
||||
LL | fn get3<R: Deref<Target = Self>>(self: std::rc::Rc<R>) -> u32 {
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: type of `self` must not be a method generic parameter type
|
||||
= help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
|
||||
|
||||
error[E0801]: invalid generic `self` parameter type: `&Rc<R>`
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:25:44
|
||||
|
|
||||
LL | fn get4<R: Deref<Target = Self>>(self: &std::rc::Rc<R>) -> u32 {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: type of `self` must not be a method generic parameter type
|
||||
= help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
|
||||
|
||||
error[E0801]: invalid generic `self` parameter type: `Rc<&R>`
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:29:44
|
||||
|
|
||||
LL | fn get5<R: Deref<Target = Self>>(self: std::rc::Rc<&R>) -> u32 {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: type of `self` must not be a method generic parameter type
|
||||
= help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:16:5
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:76:5
|
||||
|
|
||||
LL | foo.get::<&Foo>();
|
||||
| ^^^ expected `&Foo`, found `Foo`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:78:5
|
||||
|
|
||||
LL | foo.get::<std::rc::Rc<Foo>>();
|
||||
| ^^^ expected `Rc<Foo>`, found `Foo`
|
||||
|
|
||||
= note: expected struct `Rc<Foo>`
|
||||
found struct `Foo`
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:84:5
|
||||
|
|
||||
LL | smart_ptr.get::<SmartPtr2<Foo>>();
|
||||
| ^^^^^^^^^ expected `SmartPtr2<'_, Foo>`, found `SmartPtr<'_, Foo>`
|
||||
|
|
||||
= note: expected struct `SmartPtr2<'_, Foo>`
|
||||
found struct `SmartPtr<'_, Foo>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:86:5
|
||||
|
|
||||
LL | smart_ptr.get::<&Foo>();
|
||||
| ^^^^^^^^^ expected `&Foo`, found `SmartPtr<'_, Foo>`
|
||||
|
|
||||
= note: expected reference `&Foo`
|
||||
found struct `SmartPtr<'_, Foo, >`
|
||||
|
||||
error[E0271]: type mismatch resolving `<Silly as FindReceiver>::Receiver == Foo`
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:92:9
|
||||
|
|
||||
LL | foo.get6(Silly);
|
||||
| ^^^^ type mismatch resolving `<Silly as FindReceiver>::Receiver == Foo`
|
||||
|
|
||||
note: expected this to be `Foo`
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:71:21
|
||||
|
|
||||
LL | type Receiver = std::rc::Rc<Foo>;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
= note: expected struct `Foo`
|
||||
found struct `Rc<Foo>`
|
||||
|
||||
error[E0271]: type mismatch resolving `<Silly as FindReceiver>::Receiver == &Foo`
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:96:9
|
||||
|
|
||||
LL | foo.get6(Silly);
|
||||
| ^^^^ type mismatch resolving `<Silly as FindReceiver>::Receiver == &Foo`
|
||||
|
|
||||
note: expected this to be `&Foo`
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:71:21
|
||||
|
|
||||
LL | type Receiver = std::rc::Rc<Foo>;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
= note: expected reference `&Foo`
|
||||
found struct `Rc<Foo>`
|
||||
|
||||
error[E0599]: the method `get` exists for struct `Rc<Bar<_>>`, but its trait bounds were not satisfied
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:100:7
|
||||
|
|
||||
LL | struct Bar<R>(std::marker::PhantomData<R>);
|
||||
| ------------- doesn't satisfy `Bar<_>: Deref`
|
||||
...
|
||||
LL | t.get();
|
||||
| ^^^ method cannot be called on `Rc<Bar<_>>` due to unsatisfied trait bounds
|
||||
|
|
||||
note: the following trait bounds were not satisfied:
|
||||
`<&Bar<_> as Deref>::Target = Bar<&Bar<_>>`
|
||||
`<&Rc<Bar<_>> as Deref>::Target = Bar<&Rc<Bar<_>>>`
|
||||
`<&mut Bar<_> as Deref>::Target = Bar<&mut Bar<_>>`
|
||||
`<&mut Rc<Bar<_>> as Deref>::Target = Bar<&mut Rc<Bar<_>>>`
|
||||
`<Rc<Bar<_>> as Deref>::Target = Bar<Rc<Bar<_>>>`
|
||||
`Bar<_>: Deref`
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:60:9
|
||||
|
|
||||
LL | impl<R: std::ops::Deref<Target = Self>> Bar<R> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------
|
||||
| | |
|
||||
| | unsatisfied trait bound introduced here
|
||||
| unsatisfied trait bound introduced here
|
||||
note: the trait `Deref` must be implemented
|
||||
--> $SRC_DIR/core/src/ops/deref.rs:LL:COL
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
= note: the following trait defines an item `get`, perhaps you need to implement it:
|
||||
candidate #1: `SliceIndex`
|
||||
|
||||
error[E0599]: the method `get` exists for reference `&Rc<Bar<_>>`, but its trait bounds were not satisfied
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:108:7
|
||||
|
|
||||
LL | struct Bar<R>(std::marker::PhantomData<R>);
|
||||
| ------------- doesn't satisfy `Bar<_>: Deref`
|
||||
...
|
||||
LL | t.get();
|
||||
| ^^^ method cannot be called on `&Rc<Bar<_>>` due to unsatisfied trait bounds
|
||||
|
|
||||
note: the following trait bounds were not satisfied:
|
||||
`<&&Rc<Bar<_>> as Deref>::Target = Bar<&&Rc<Bar<_>>>`
|
||||
`<&Bar<_> as Deref>::Target = Bar<&Bar<_>>`
|
||||
`<&Rc<Bar<_>> as Deref>::Target = Bar<&Rc<Bar<_>>>`
|
||||
`<&mut &Rc<Bar<_>> as Deref>::Target = Bar<&mut &Rc<Bar<_>>>`
|
||||
`<&mut Bar<_> as Deref>::Target = Bar<&mut Bar<_>>`
|
||||
`<&mut Rc<Bar<_>> as Deref>::Target = Bar<&mut Rc<Bar<_>>>`
|
||||
`<Rc<Bar<_>> as Deref>::Target = Bar<Rc<Bar<_>>>`
|
||||
`Bar<_>: Deref`
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:60:9
|
||||
|
|
||||
LL | impl<R: std::ops::Deref<Target = Self>> Bar<R> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------
|
||||
| | |
|
||||
| | unsatisfied trait bound introduced here
|
||||
| unsatisfied trait bound introduced here
|
||||
note: the trait `Deref` must be implemented
|
||||
--> $SRC_DIR/core/src/ops/deref.rs:LL:COL
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
= note: the following trait defines an item `get`, perhaps you need to implement it:
|
||||
candidate #1: `SliceIndex`
|
||||
|
||||
error: aborting due to 14 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0271, E0308, E0599, E0801.
|
||||
For more information about an error, try `rustc --explain E0271`.
|
||||
|
@ -2,17 +2,109 @@
|
||||
#![cfg_attr(feature, feature(arbitrary_self_types))]
|
||||
|
||||
use std::ops::Deref;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
struct Foo(u32);
|
||||
impl Foo {
|
||||
fn get<R: Deref<Target = Self>>(self: R) -> u32 {
|
||||
//[default]~^ ERROR: `R` cannot be used as the type of `self`
|
||||
//~^ ERROR: invalid generic `self` parameter type
|
||||
self.0
|
||||
}
|
||||
fn get1<R: Deref<Target = Self>>(self: &R) -> u32 {
|
||||
//~^ ERROR: invalid generic `self` parameter type
|
||||
self.0
|
||||
}
|
||||
fn get2<R: Deref<Target = Self>>(self: &mut R) -> u32 {
|
||||
//~^ ERROR: invalid generic `self` parameter type
|
||||
self.0
|
||||
}
|
||||
fn get3<R: Deref<Target = Self>>(self: std::rc::Rc<R>) -> u32 {
|
||||
//~^ ERROR: invalid generic `self` parameter type
|
||||
self.0
|
||||
}
|
||||
fn get4<R: Deref<Target = Self>>(self: &std::rc::Rc<R>) -> u32 {
|
||||
//~^ ERROR: invalid generic `self` parameter type
|
||||
self.0
|
||||
}
|
||||
fn get5<R: Deref<Target = Self>>(self: std::rc::Rc<&R>) -> u32 {
|
||||
//~^ ERROR: invalid generic `self` parameter type
|
||||
self.0
|
||||
}
|
||||
fn get6<FR: FindReceiver>(self: FR::Receiver, other: FR) -> u32 {
|
||||
//[default]~^ ERROR: `<FR as FindReceiver>::Receiver` cannot be used as the type of `self`
|
||||
42
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct SmartPtr<'a, T: ?Sized>(&'a T);
|
||||
|
||||
impl<'a, T: ?Sized> Deref for SmartPtr<'a, T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
struct SmartPtr2<'a, T: ?Sized>(&'a T);
|
||||
|
||||
impl<'a, T: ?Sized> Deref for SmartPtr2<'a, T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
struct Bar<R>(std::marker::PhantomData<R>);
|
||||
|
||||
impl<R: std::ops::Deref<Target = Self>> Bar<R> {
|
||||
fn get(self: R) {}
|
||||
//[default]~^ ERROR: `R` cannot be used as the type of `self`
|
||||
}
|
||||
|
||||
trait FindReceiver {
|
||||
type Receiver: Deref<Target = Foo>;
|
||||
}
|
||||
|
||||
struct Silly;
|
||||
impl FindReceiver for Silly {
|
||||
type Receiver = std::rc::Rc<Foo>;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut foo = Foo(1);
|
||||
foo.get::<&Foo>();
|
||||
//[feature]~^ ERROR mismatched types
|
||||
foo.get::<std::rc::Rc<Foo>>();
|
||||
//[feature]~^ ERROR mismatched types
|
||||
|
||||
let smart_ptr = SmartPtr(&foo);
|
||||
let smart_ptr2 = SmartPtr2(&foo);
|
||||
smart_ptr.get(); // this compiles
|
||||
smart_ptr.get::<SmartPtr2<Foo>>();
|
||||
//[feature]~^ ERROR mismatched types
|
||||
smart_ptr.get::<&Foo>();
|
||||
//[feature]~^ ERROR mismatched types
|
||||
|
||||
let mut foo = Foo(1);
|
||||
// This test is slightly contrived in an attempt to generate a mismatched types
|
||||
// error for the self type below, without using the turbofish.
|
||||
foo.get6(Silly);
|
||||
//~^ ERROR type mismatch
|
||||
let mut foo = Foo(1);
|
||||
let foo = &foo;
|
||||
foo.get6(Silly);
|
||||
//~^ ERROR type mismatch
|
||||
|
||||
let t = std::rc::Rc::new(Bar(std::marker::PhantomData));
|
||||
t.get();
|
||||
//~^ ERROR its trait bounds were not satisfied
|
||||
let t = &t;
|
||||
// This is a further attempt at triggering 'type mismatch' errors
|
||||
// from arbitrary self types without resorting to the turbofish.
|
||||
// Ideally, here, t is Thing<Rc<Target=Self>> while we're going to call
|
||||
// it with a &t method receiver. However, this doesn't work since that
|
||||
// type of t becomes recursive and trait bounds can't be satisfied.
|
||||
t.get();
|
||||
//~^ ERROR its trait bounds were not satisfied
|
||||
}
|
||||
|
@ -1,21 +0,0 @@
|
||||
#![feature(arbitrary_self_types)]
|
||||
#![feature(impl_trait_in_assoc_type)]
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
trait Foo {
|
||||
type Bar: Foo;
|
||||
|
||||
fn foo(self: impl Deref<Target = Self>) -> Self::Bar;
|
||||
}
|
||||
|
||||
impl<C> Foo for C {
|
||||
type Bar = impl Foo;
|
||||
|
||||
fn foo(self: impl Deref<Target = Self>) -> Self::Bar {
|
||||
self
|
||||
//~^ Error type parameter `impl Deref<Target = Self>` is part of concrete type but not used in parameter list for the `impl Trait` type alias
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -1,8 +0,0 @@
|
||||
error: type parameter `impl Deref<Target = Self>` is part of concrete type but not used in parameter list for the `impl Trait` type alias
|
||||
--> $DIR/issue-57700.rs:16:9
|
||||
|
|
||||
LL | self
|
||||
| ^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -966,7 +966,6 @@ cc = ["@kobzol"]
|
||||
warn_non_default_branch = true
|
||||
contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
|
||||
users_on_vacation = [
|
||||
"BoxyUwU",
|
||||
"fmease",
|
||||
"jyn514",
|
||||
"oli-obk",
|
||||
|
Loading…
Reference in New Issue
Block a user