mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-01 20:47:36 +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",
|
"miropt-test-tools",
|
||||||
"regex",
|
"regex",
|
||||||
"rustfix",
|
"rustfix",
|
||||||
|
"semver",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tracing",
|
"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,
|
E0798: 0798,
|
||||||
E0799: 0799,
|
E0799: 0799,
|
||||||
E0800: 0800,
|
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
|
.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
|
.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}`
|
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
|
.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),
|
hir::ImplItemKind::Type(ty) if ty.span != DUMMY_SP => (None, ty.span),
|
||||||
_ => (None, impl_item.span),
|
_ => (None, impl_item.span),
|
||||||
};
|
};
|
||||||
|
|
||||||
check_associated_item(tcx, impl_item.owner_id.def_id, span, method_sig)
|
check_associated_item(tcx, impl_item.owner_id.def_id, span, method_sig)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1725,8 +1724,11 @@ fn check_method_receiver<'tcx>(
|
|||||||
} else {
|
} else {
|
||||||
None
|
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 {
|
return Err(match arbitrary_self_types_level {
|
||||||
// Wherever possible, emit a message advising folks that the features
|
// Wherever possible, emit a message advising folks that the features
|
||||||
// `arbitrary_self_types` or `arbitrary_self_types_pointers` might
|
// `arbitrary_self_types` or `arbitrary_self_types_pointers` might
|
||||||
@ -1737,7 +1739,9 @@ fn check_method_receiver<'tcx>(
|
|||||||
receiver_ty,
|
receiver_ty,
|
||||||
self_ty,
|
self_ty,
|
||||||
Some(ArbitrarySelfTypesLevel::Basic),
|
Some(ArbitrarySelfTypesLevel::Basic),
|
||||||
) =>
|
generics,
|
||||||
|
)
|
||||||
|
.is_ok() =>
|
||||||
{
|
{
|
||||||
// Report error; would have worked with `arbitrary_self_types`.
|
// Report error; would have worked with `arbitrary_self_types`.
|
||||||
feature_err(
|
feature_err(
|
||||||
@ -1759,7 +1763,9 @@ fn check_method_receiver<'tcx>(
|
|||||||
receiver_ty,
|
receiver_ty,
|
||||||
self_ty,
|
self_ty,
|
||||||
Some(ArbitrarySelfTypesLevel::WithPointers),
|
Some(ArbitrarySelfTypesLevel::WithPointers),
|
||||||
) =>
|
generics,
|
||||||
|
)
|
||||||
|
.is_ok() =>
|
||||||
{
|
{
|
||||||
// Report error; would have worked with `arbitrary_self_types_pointers`.
|
// Report error; would have worked with `arbitrary_self_types_pointers`.
|
||||||
feature_err(
|
feature_err(
|
||||||
@ -1777,13 +1783,45 @@ fn check_method_receiver<'tcx>(
|
|||||||
_ =>
|
_ =>
|
||||||
// Report error; would not have worked with `arbitrary_self_types[_pointers]`.
|
// Report error; would not have worked with `arbitrary_self_types[_pointers]`.
|
||||||
{
|
{
|
||||||
|
match receiver_validity_err {
|
||||||
|
ReceiverValidityError::DoesNotDeref => {
|
||||||
tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty })
|
tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty })
|
||||||
}
|
}
|
||||||
|
ReceiverValidityError::MethodGenericParamUsed => {
|
||||||
|
tcx.dcx().emit_err(errors::InvalidGenericReceiverTy { span, receiver_ty })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Ok(())
|
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
|
/// 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
|
/// `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.
|
/// 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>,
|
receiver_ty: Ty<'tcx>,
|
||||||
self_ty: Ty<'tcx>,
|
self_ty: Ty<'tcx>,
|
||||||
arbitrary_self_types_enabled: Option<ArbitrarySelfTypesLevel>,
|
arbitrary_self_types_enabled: Option<ArbitrarySelfTypesLevel>,
|
||||||
) -> bool {
|
method_generics: &ty::Generics,
|
||||||
|
) -> Result<(), ReceiverValidityError> {
|
||||||
let infcx = wfcx.infcx;
|
let infcx = wfcx.infcx;
|
||||||
let tcx = wfcx.tcx();
|
let tcx = wfcx.tcx();
|
||||||
let cause =
|
let cause =
|
||||||
@ -1811,9 +1850,11 @@ fn receiver_is_valid<'tcx>(
|
|||||||
ocx.eq(&cause, wfcx.param_env, self_ty, receiver_ty)?;
|
ocx.eq(&cause, wfcx.param_env, self_ty, receiver_ty)?;
|
||||||
if ocx.select_all_or_error().is_empty() { Ok(()) } else { Err(NoSolution) }
|
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);
|
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`.
|
// 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
|
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
|
// Check if the self type unifies. If it does, then commit the result
|
||||||
// since it may have region side-effects.
|
// since it may have region side-effects.
|
||||||
if let Ok(()) = wfcx.infcx.commit_if_ok(|_| {
|
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) }
|
if ocx.select_all_or_error().is_empty() { Ok(()) } else { Err(NoSolution) }
|
||||||
}) {
|
}) {
|
||||||
wfcx.register_obligations(autoderef.into_obligations());
|
wfcx.register_obligations(autoderef.into_obligations());
|
||||||
return true;
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Without `feature(arbitrary_self_types)`, we require that each step in the
|
// 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);
|
debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`", receiver_ty, self_ty);
|
||||||
false
|
Err(ReceiverValidityError::DoesNotDeref)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn receiver_is_implemented<'tcx>(
|
fn receiver_is_implemented<'tcx>(
|
||||||
|
@ -1623,6 +1623,16 @@ pub(crate) struct InvalidReceiverTy<'tcx> {
|
|||||||
pub receiver_ty: Ty<'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)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(hir_analysis_cmse_inputs_stack_spill, code = E0798)]
|
#[diag(hir_analysis_cmse_inputs_stack_spill, code = E0798)]
|
||||||
#[note]
|
#[note]
|
||||||
|
@ -533,9 +533,6 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
|||||||
self.register_predicates(obligations);
|
self.register_predicates(obligations);
|
||||||
}
|
}
|
||||||
Err(terr) => {
|
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() {
|
if self.tcx.features().arbitrary_self_types() {
|
||||||
self.err_ctxt()
|
self.err_ctxt()
|
||||||
.report_mismatched_types(
|
.report_mismatched_types(
|
||||||
|
@ -32,8 +32,11 @@ pub(crate) struct Formatter<'mir, 'tcx, A>
|
|||||||
where
|
where
|
||||||
A: Analysis<'tcx>,
|
A: Analysis<'tcx>,
|
||||||
{
|
{
|
||||||
body: &'mir Body<'tcx>,
|
// The `RefCell` is used because `<Formatter as Labeller>::node_label`
|
||||||
results: RefCell<Option<Results<'tcx, A>>>,
|
// 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,
|
style: OutputStyle,
|
||||||
reachable: BitSet<BasicBlock>,
|
reachable: BitSet<BasicBlock>,
|
||||||
}
|
}
|
||||||
@ -48,11 +51,15 @@ where
|
|||||||
style: OutputStyle,
|
style: OutputStyle,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let reachable = mir::traversal::reachable_as_bitset(body);
|
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> {
|
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;
|
type Edge = CfgEdge;
|
||||||
|
|
||||||
fn graph_id(&self) -> dot::Id<'_> {
|
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()
|
dot::Id::new(format!("graph_for_def_id_{name}")).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,20 +97,11 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn node_label(&self, block: &Self::Node) -> dot::LabelText<'_> {
|
fn node_label(&self, block: &Self::Node) -> dot::LabelText<'_> {
|
||||||
let mut label = Vec::new();
|
let mut cursor = self.cursor.borrow_mut();
|
||||||
self.results.replace_with(|results| {
|
let mut fmt =
|
||||||
// `Formatter::result` is a `RefCell<Option<_>>` so we can replace
|
BlockFormatter { cursor: &mut cursor, style: self.style, bg: Background::Light };
|
||||||
// the value with `None`, move it into the results cursor, move it
|
let label = fmt.write_node_label(*block).unwrap();
|
||||||
// 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,
|
|
||||||
};
|
|
||||||
|
|
||||||
fmt.write_node_label(&mut label, *block).unwrap();
|
|
||||||
Some(fmt.results.into_results())
|
|
||||||
});
|
|
||||||
dot::LabelText::html(String::from_utf8(label).unwrap())
|
dot::LabelText::html(String::from_utf8(label).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,12 +110,12 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn edge_label(&self, e: &Self::Edge) -> dot::LabelText<'_> {
|
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())
|
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
|
where
|
||||||
A: Analysis<'tcx>,
|
A: Analysis<'tcx>,
|
||||||
{
|
{
|
||||||
@ -125,7 +123,7 @@ where
|
|||||||
type Edge = CfgEdge;
|
type Edge = CfgEdge;
|
||||||
|
|
||||||
fn nodes(&self) -> dot::Nodes<'_, Self::Node> {
|
fn nodes(&self) -> dot::Nodes<'_, Self::Node> {
|
||||||
self.body
|
self.body()
|
||||||
.basic_blocks
|
.basic_blocks
|
||||||
.indices()
|
.indices()
|
||||||
.filter(|&idx| self.reachable.contains(idx))
|
.filter(|&idx| self.reachable.contains(idx))
|
||||||
@ -134,10 +132,10 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn edges(&self) -> dot::Edges<'_, Self::Edge> {
|
fn edges(&self) -> dot::Edges<'_, Self::Edge> {
|
||||||
self.body
|
let body = self.body();
|
||||||
.basic_blocks
|
body.basic_blocks
|
||||||
.indices()
|
.indices()
|
||||||
.flat_map(|bb| dataflow_successors(self.body, bb))
|
.flat_map(|bb| dataflow_successors(body, bb))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
@ -147,20 +145,20 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn target(&self, edge: &Self::Edge) -> Self::Node {
|
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
|
where
|
||||||
A: Analysis<'tcx>,
|
A: Analysis<'tcx>,
|
||||||
{
|
{
|
||||||
results: ResultsCursor<'mir, 'tcx, A>,
|
cursor: &'a mut ResultsCursor<'mir, 'tcx, A>,
|
||||||
bg: Background,
|
bg: Background,
|
||||||
style: OutputStyle,
|
style: OutputStyle,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'mir, 'tcx, A> BlockFormatter<'mir, 'tcx, A>
|
impl<'tcx, A> BlockFormatter<'_, '_, 'tcx, A>
|
||||||
where
|
where
|
||||||
A: Analysis<'tcx>,
|
A: Analysis<'tcx>,
|
||||||
A::Domain: DebugWithContext<A>,
|
A::Domain: DebugWithContext<A>,
|
||||||
@ -173,7 +171,9 @@ where
|
|||||||
bg
|
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:
|
// Sample output:
|
||||||
// +-+-----------------------------------------------+
|
// +-+-----------------------------------------------+
|
||||||
// A | bb4 |
|
// A | bb4 |
|
||||||
@ -200,6 +200,9 @@ where
|
|||||||
// attributes. Make sure to test the output before trying to remove the redundancy.
|
// 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>.
|
// 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!(
|
let table_fmt = concat!(
|
||||||
" border=\"1\"",
|
" border=\"1\"",
|
||||||
" cellborder=\"1\"",
|
" cellborder=\"1\"",
|
||||||
@ -219,8 +222,8 @@ where
|
|||||||
|
|
||||||
// C: State at start of block
|
// C: State at start of block
|
||||||
self.bg = Background::Light;
|
self.bg = Background::Light;
|
||||||
self.results.seek_to_block_start(block);
|
self.cursor.seek_to_block_start(block);
|
||||||
let block_start_state = self.results.get().clone();
|
let block_start_state = self.cursor.get().clone();
|
||||||
self.write_row_with_full_state(w, "", "(on start)")?;
|
self.write_row_with_full_state(w, "", "(on start)")?;
|
||||||
|
|
||||||
// D + E: Statement and terminator transfer functions
|
// D + E: Statement and terminator transfer functions
|
||||||
@ -228,12 +231,12 @@ where
|
|||||||
|
|
||||||
// F: State at end of block
|
// 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
|
// Write the full dataflow state immediately after the terminator if it differs from the
|
||||||
// state at block entry.
|
// state at block entry.
|
||||||
self.results.seek_to_block_end(block);
|
self.cursor.seek_to_block_end(block);
|
||||||
if self.results.get() != &block_start_state || A::Direction::IS_BACKWARD {
|
if self.cursor.get() != &block_start_state || A::Direction::IS_BACKWARD {
|
||||||
let after_terminator_name = match terminator.kind {
|
let after_terminator_name = match terminator.kind {
|
||||||
mir::TerminatorKind::Call { target: Some(_), .. } => "(on unwind)",
|
mir::TerminatorKind::Call { target: Some(_), .. } => "(on unwind)",
|
||||||
_ => "(on end)",
|
_ => "(on end)",
|
||||||
@ -250,8 +253,8 @@ where
|
|||||||
match terminator.kind {
|
match terminator.kind {
|
||||||
mir::TerminatorKind::Call { destination, .. } => {
|
mir::TerminatorKind::Call { destination, .. } => {
|
||||||
self.write_row(w, "", "(on successful return)", |this, w, fmt| {
|
self.write_row(w, "", "(on successful return)", |this, w, fmt| {
|
||||||
let state_on_unwind = this.results.get().clone();
|
let state_on_unwind = this.cursor.get().clone();
|
||||||
this.results.apply_custom_effect(|analysis, state| {
|
this.cursor.apply_custom_effect(|analysis, state| {
|
||||||
analysis.apply_call_return_effect(
|
analysis.apply_call_return_effect(
|
||||||
state,
|
state,
|
||||||
block,
|
block,
|
||||||
@ -265,9 +268,9 @@ where
|
|||||||
colspan = this.style.num_state_columns(),
|
colspan = this.style.num_state_columns(),
|
||||||
fmt = fmt,
|
fmt = fmt,
|
||||||
diff = diff_pretty(
|
diff = diff_pretty(
|
||||||
this.results.get(),
|
this.cursor.get(),
|
||||||
&state_on_unwind,
|
&state_on_unwind,
|
||||||
this.results.analysis()
|
this.cursor.analysis()
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
@ -275,8 +278,8 @@ where
|
|||||||
|
|
||||||
mir::TerminatorKind::Yield { resume, resume_arg, .. } => {
|
mir::TerminatorKind::Yield { resume, resume_arg, .. } => {
|
||||||
self.write_row(w, "", "(on yield resume)", |this, w, fmt| {
|
self.write_row(w, "", "(on yield resume)", |this, w, fmt| {
|
||||||
let state_on_coroutine_drop = this.results.get().clone();
|
let state_on_coroutine_drop = this.cursor.get().clone();
|
||||||
this.results.apply_custom_effect(|analysis, state| {
|
this.cursor.apply_custom_effect(|analysis, state| {
|
||||||
analysis.apply_call_return_effect(
|
analysis.apply_call_return_effect(
|
||||||
state,
|
state,
|
||||||
resume,
|
resume,
|
||||||
@ -290,9 +293,9 @@ where
|
|||||||
colspan = this.style.num_state_columns(),
|
colspan = this.style.num_state_columns(),
|
||||||
fmt = fmt,
|
fmt = fmt,
|
||||||
diff = diff_pretty(
|
diff = diff_pretty(
|
||||||
this.results.get(),
|
this.cursor.get(),
|
||||||
&state_on_coroutine_drop,
|
&state_on_coroutine_drop,
|
||||||
this.results.analysis()
|
this.cursor.analysis()
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
@ -302,8 +305,8 @@ where
|
|||||||
if !targets.is_empty() =>
|
if !targets.is_empty() =>
|
||||||
{
|
{
|
||||||
self.write_row(w, "", "(on successful return)", |this, w, fmt| {
|
self.write_row(w, "", "(on successful return)", |this, w, fmt| {
|
||||||
let state_on_unwind = this.results.get().clone();
|
let state_on_unwind = this.cursor.get().clone();
|
||||||
this.results.apply_custom_effect(|analysis, state| {
|
this.cursor.apply_custom_effect(|analysis, state| {
|
||||||
analysis.apply_call_return_effect(
|
analysis.apply_call_return_effect(
|
||||||
state,
|
state,
|
||||||
block,
|
block,
|
||||||
@ -317,9 +320,9 @@ where
|
|||||||
colspan = this.style.num_state_columns(),
|
colspan = this.style.num_state_columns(),
|
||||||
fmt = fmt,
|
fmt = fmt,
|
||||||
diff = diff_pretty(
|
diff = diff_pretty(
|
||||||
this.results.get(),
|
this.cursor.get(),
|
||||||
&state_on_unwind,
|
&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(
|
fn write_block_header_simple(
|
||||||
@ -407,9 +412,9 @@ where
|
|||||||
block: BasicBlock,
|
block: BasicBlock,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
let diffs = StateDiffCollector::run(
|
let diffs = StateDiffCollector::run(
|
||||||
self.results.body(),
|
self.cursor.body(),
|
||||||
block,
|
block,
|
||||||
self.results.mut_results(),
|
self.cursor.mut_results(),
|
||||||
self.style,
|
self.style,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -420,7 +425,7 @@ where
|
|||||||
if A::Direction::IS_FORWARD { it.next().unwrap() } else { it.next_back().unwrap() }
|
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 statement_str = format!("{statement:?}");
|
||||||
let index_str = format!("{i}");
|
let index_str = format!("{i}");
|
||||||
|
|
||||||
@ -442,7 +447,7 @@ where
|
|||||||
assert!(diffs_after.is_empty());
|
assert!(diffs_after.is_empty());
|
||||||
assert!(diffs_before.as_ref().map_or(true, ExactSizeIterator::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();
|
let mut terminator_str = String::new();
|
||||||
terminator.kind.fmt_head(&mut terminator_str).unwrap();
|
terminator.kind.fmt_head(&mut terminator_str).unwrap();
|
||||||
|
|
||||||
@ -492,8 +497,8 @@ where
|
|||||||
mir: &str,
|
mir: &str,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
self.write_row(w, i, mir, |this, w, fmt| {
|
self.write_row(w, i, mir, |this, w, fmt| {
|
||||||
let state = this.results.get();
|
let state = this.cursor.get();
|
||||||
let analysis = this.results.analysis();
|
let analysis = this.cursor.analysis();
|
||||||
|
|
||||||
// FIXME: The full state vector can be quite long. It would be nice to split on commas
|
// FIXME: The full state vector can be quite long. It would be nice to split on commas
|
||||||
// and use some text wrapping algorithm.
|
// and use some text wrapping algorithm.
|
||||||
|
@ -84,7 +84,7 @@ fn current_dll_path() -> Result<PathBuf, String> {
|
|||||||
loop {
|
loop {
|
||||||
if libc::loadquery(
|
if libc::loadquery(
|
||||||
libc::L_GETINFO,
|
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,
|
(std::mem::size_of::<libc::ld_info>() * buffer.len()) as u32,
|
||||||
) >= 0
|
) >= 0
|
||||||
{
|
{
|
||||||
|
@ -198,10 +198,6 @@ fn generate_mergeable_doctest(
|
|||||||
} else {
|
} else {
|
||||||
writeln!(output, "mod {test_id} {{\n{}{}", doctest.crates, doctest.maybe_crate_attrs)
|
writeln!(output, "mod {test_id} {{\n{}{}", doctest.crates, doctest.maybe_crate_attrs)
|
||||||
.unwrap();
|
.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 {
|
if doctest.has_main_fn {
|
||||||
output.push_str(&doctest.everything_else);
|
output.push_str(&doctest.everything_else);
|
||||||
} else {
|
} else {
|
||||||
|
@ -18,6 +18,7 @@ build_helper = { path = "../build_helper" }
|
|||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }
|
tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }
|
||||||
regex = "1.0"
|
regex = "1.0"
|
||||||
|
semver = { version = "1.0.23", features = ["serde"] }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
rustfix = "0.8.1"
|
rustfix = "0.8.1"
|
||||||
|
@ -7,6 +7,7 @@ use std::sync::OnceLock;
|
|||||||
use std::{fmt, iter};
|
use std::{fmt, iter};
|
||||||
|
|
||||||
use build_helper::git::GitConfig;
|
use build_helper::git::GitConfig;
|
||||||
|
use semver::Version;
|
||||||
use serde::de::{Deserialize, Deserializer, Error as _};
|
use serde::de::{Deserialize, Deserializer, Error as _};
|
||||||
use test::{ColorConfig, OutputFormat};
|
use test::{ColorConfig, OutputFormat};
|
||||||
|
|
||||||
@ -298,7 +299,7 @@ pub struct Config {
|
|||||||
pub lldb_version: Option<u32>,
|
pub lldb_version: Option<u32>,
|
||||||
|
|
||||||
/// Version of LLVM
|
/// Version of LLVM
|
||||||
pub llvm_version: Option<u32>,
|
pub llvm_version: Option<Version>,
|
||||||
|
|
||||||
/// Is LLVM a system LLVM
|
/// Is LLVM a system LLVM
|
||||||
pub system_llvm: bool,
|
pub system_llvm: bool,
|
||||||
|
@ -6,6 +6,7 @@ use std::io::prelude::*;
|
|||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
|
use semver::Version;
|
||||||
use tracing::*;
|
use tracing::*;
|
||||||
|
|
||||||
use crate::common::{Config, Debugger, FailMode, Mode, PassMode};
|
use crate::common::{Config, Debugger, FailMode, Mode, PassMode};
|
||||||
@ -1113,26 +1114,39 @@ fn parse_normalize_rule(header: &str) -> Option<(String, String)> {
|
|||||||
Some((regex, replacement))
|
Some((regex, replacement))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_llvm_version(version: &str) -> Option<u32> {
|
/// Given an llvm version string that looks like `1.2.3-rc1`, extract as semver. Note that this
|
||||||
let pat = |c: char| !c.is_ascii_digit() && c != '.';
|
/// accepts more than just strict `semver` syntax (as in `major.minor.patch`); this permits omitting
|
||||||
let version_without_suffix = match version.find(pat) {
|
/// minor and patch version components so users can write e.g. `//@ min-llvm-version: 19` instead of
|
||||||
Some(pos) => &version[..pos],
|
/// 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,
|
None => version,
|
||||||
};
|
};
|
||||||
let components: Vec<u32> = version_without_suffix
|
|
||||||
|
let components: Vec<u64> = version_without_suffix
|
||||||
.split('.')
|
.split('.')
|
||||||
.map(|s| s.parse().expect("Malformed version component"))
|
.map(|s| s.parse().expect("llvm version component should consist of only digits"))
|
||||||
.collect();
|
.collect();
|
||||||
let version = match *components {
|
|
||||||
[a] => a * 10_000,
|
match &components[..] {
|
||||||
[a, b] => a * 10_000 + b * 100,
|
[major] => Version::new(*major, 0, 0),
|
||||||
[a, b, c] => a * 10_000 + b * 100 + c,
|
[major, minor] => Version::new(*major, *minor, 0),
|
||||||
_ => panic!("Malformed version"),
|
[major, minor, patch] => Version::new(*major, *minor, *patch),
|
||||||
};
|
_ => panic!("malformed llvm version string, expected only 1-3 components: {version}"),
|
||||||
Some(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()?;
|
let output = Command::new(binary_path).arg("--version").output().ok()?;
|
||||||
if !output.status.success() {
|
if !output.status.success() {
|
||||||
return None;
|
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()?;
|
let version = String::from_utf8(output.stdout).ok()?;
|
||||||
for line in version.lines() {
|
for line in version.lines() {
|
||||||
if let Some(version) = line.split("LLVM version ").nth(1) {
|
if let Some(version) = line.split("LLVM version ").nth(1) {
|
||||||
return extract_llvm_version(version);
|
return Some(extract_llvm_version(version));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
@ -1247,15 +1261,17 @@ pub fn llvm_has_libzstd(config: &Config) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Takes a directive of the form `"<version1> [- <version2>]"`,
|
/// Takes a directive of the form `"<version1> [- <version2>]"`, returns the numeric representation
|
||||||
/// returns the numeric representation of `<version1>` and `<version2>` as
|
/// of `<version1>` and `<version2>` as tuple: `(<version1>, <version2>)`.
|
||||||
/// tuple: `(<version1> as u32, <version2> as u32)`.
|
|
||||||
///
|
///
|
||||||
/// If the `<version2>` part is omitted, the second component of the tuple
|
/// If the `<version2>` part is omitted, the second component of the tuple is the same as
|
||||||
/// is the same as `<version1>`.
|
/// `<version1>`.
|
||||||
fn extract_version_range<F>(line: &str, parse: F) -> Option<(u32, u32)>
|
fn extract_version_range<'a, F, VersionTy: Clone>(
|
||||||
|
line: &'a str,
|
||||||
|
parse: F,
|
||||||
|
) -> Option<(VersionTy, VersionTy)>
|
||||||
where
|
where
|
||||||
F: Fn(&str) -> Option<u32>,
|
F: Fn(&'a str) -> Option<VersionTy>,
|
||||||
{
|
{
|
||||||
let mut splits = line.splitn(2, "- ").map(str::trim);
|
let mut splits = line.splitn(2, "- ").map(str::trim);
|
||||||
let min = splits.next().unwrap();
|
let min = splits.next().unwrap();
|
||||||
@ -1273,7 +1289,7 @@ where
|
|||||||
let max = match max {
|
let max = match max {
|
||||||
Some("") => return None,
|
Some("") => return None,
|
||||||
Some(max) => parse(max)?,
|
Some(max) => parse(max)?,
|
||||||
_ => min,
|
_ => min.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Some((min, max))
|
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(actual_version) = &config.llvm_version {
|
||||||
if let Some(rest) = line.strip_prefix("min-llvm-version:").map(str::trim) {
|
// Note that these `min` versions will check for not just major versions.
|
||||||
let min_version = extract_llvm_version(rest).unwrap();
|
|
||||||
// Ignore if actual version is smaller the minimum required
|
if let Some(version_string) = config.parse_name_value_directive(line, "min-llvm-version") {
|
||||||
// version
|
let min_version = extract_llvm_version(&version_string);
|
||||||
if actual_version < min_version {
|
// Ignore if actual version is smaller than the minimum required version.
|
||||||
|
if *actual_version < min_version {
|
||||||
return IgnoreDecision::Ignore {
|
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) {
|
} else if let Some(version_string) =
|
||||||
let min_version = extract_llvm_version(rest).unwrap();
|
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
|
// Ignore if using system LLVM and actual version
|
||||||
// is smaller the minimum required 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 {
|
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>]"
|
// Syntax is: "ignore-llvm-version: <version1> [- <version2>]"
|
||||||
let (v_min, v_max) =
|
let (v_min, v_max) =
|
||||||
extract_version_range(rest, extract_llvm_version).unwrap_or_else(|| {
|
extract_version_range(&version_range, |s| Some(extract_llvm_version(s)))
|
||||||
panic!("couldn't parse version range: {:?}", rest);
|
.unwrap_or_else(|| {
|
||||||
|
panic!("couldn't parse version range: \"{version_range}\"");
|
||||||
});
|
});
|
||||||
if v_max < v_min {
|
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.
|
// 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 {
|
if v_min == v_max {
|
||||||
return IgnoreDecision::Ignore {
|
return IgnoreDecision::Ignore {
|
||||||
reason: format!("ignored when the LLVM version is {rest}"),
|
reason: format!("ignored when the LLVM version is {actual_version}"),
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return IgnoreDecision::Ignore {
|
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::io::Read;
|
||||||
use std::path::Path;
|
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::common::{Config, Debugger, Mode};
|
||||||
use crate::header::{EarlyProps, HeadersCache, parse_normalize_rule};
|
|
||||||
|
|
||||||
fn make_test_description<R: Read>(
|
fn make_test_description<R: Read>(
|
||||||
config: &Config,
|
config: &Config,
|
||||||
@ -408,18 +412,66 @@ fn channel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_extract_version_range() {
|
fn test_extract_llvm_version() {
|
||||||
use super::{extract_llvm_version, extract_version_range};
|
// 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)));
|
#[test]
|
||||||
assert_eq!(extract_version_range("0 - 4.5.6", extract_llvm_version), Some((0, 40506)));
|
#[should_panic]
|
||||||
assert_eq!(extract_version_range("1.2.3 -", extract_llvm_version), None);
|
fn test_llvm_version_invalid_components() {
|
||||||
assert_eq!(extract_version_range("1.2.3 - ", extract_llvm_version), None);
|
extract_llvm_version("4.x.6");
|
||||||
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);
|
#[test]
|
||||||
assert_eq!(extract_version_range(" - 4.5.6", extract_llvm_version), None);
|
#[should_panic]
|
||||||
assert_eq!(extract_version_range("0 -", extract_llvm_version), None);
|
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]
|
#[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),
|
Some(x) => panic!("argument for --color must be auto, always, or never, but found `{}`", x),
|
||||||
};
|
};
|
||||||
let llvm_version =
|
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")?),
|
|| header::extract_llvm_version_from_binary(&matches.opt_str("llvm-filecheck")?),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
|
|
||||||
use crate::debuggers::{extract_gdb_version, extract_lldb_version};
|
use crate::debuggers::{extract_gdb_version, extract_lldb_version};
|
||||||
use crate::header::extract_llvm_version;
|
|
||||||
use crate::is_test;
|
use crate::is_test;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -67,15 +66,3 @@ fn is_test_test() {
|
|||||||
assert!(!is_test(&OsString::from("#a_dog_gif")));
|
assert!(!is_test(&OsString::from("#a_dog_gif")));
|
||||||
assert!(!is_test(&OsString::from("~a_temp_file")));
|
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-55099-lifetime-inference.rs
|
||||||
ui/type-alias-impl-trait/issue-57188-associate-impl-capture.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-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-57807-associated-type.rs
|
||||||
ui/type-alias-impl-trait/issue-57961.rs
|
ui/type-alias-impl-trait/issue-57961.rs
|
||||||
ui/type-alias-impl-trait/issue-58662-coroutine-with-lifetime.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);
|
struct Foo(u32);
|
||||||
impl Foo {
|
impl Foo {
|
||||||
const fn get<R: Deref<Target = Self>>(self: R) -> u32 {
|
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
|
//~| ERROR destructor of `R` cannot be evaluated at compile-time
|
||||||
self.0
|
self.0
|
||||||
//~^ ERROR cannot call non-const fn `<R as Deref>::deref` in constant function
|
//~^ 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 | }
|
LL | }
|
||||||
| - value is dropped here
|
| - 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
|
--> $DIR/arbitrary-self-from-method-substs-ice.rs:10:49
|
||||||
|
|
|
|
||||||
LL | const fn get<R: Deref<Target = Self>>(self: R) -> u32 {
|
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
|
= note: type of `self` must not be a method generic parameter type
|
||||||
= help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
|
= 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`)
|
||||||
= 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 3 previous errors
|
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`.
|
For more information about an error, try `rustc --explain E0015`.
|
||||||
|
@ -1,7 +1,72 @@
|
|||||||
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.rs:8:43
|
--> $DIR/arbitrary-self-from-method-substs.rs:9:43
|
||||||
|
|
|
|
||||||
LL | fn get<R: Deref<Target = Self>>(self: R) -> u32 {
|
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[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
|
= note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
|
||||||
@ -9,6 +74,95 @@ LL | fn get<R: Deref<Target = Self>>(self: R) -> u32 {
|
|||||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
= 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`)
|
= 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[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>`
|
||||||
|
|
||||||
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: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
|
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>();
|
LL | foo.get::<&Foo>();
|
||||||
| ^^^ expected `&Foo`, found `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))]
|
#![cfg_attr(feature, feature(arbitrary_self_types))]
|
||||||
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
struct Foo(u32);
|
struct Foo(u32);
|
||||||
impl Foo {
|
impl Foo {
|
||||||
fn get<R: Deref<Target = Self>>(self: R) -> u32 {
|
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
|
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() {
|
fn main() {
|
||||||
let mut foo = Foo(1);
|
let mut foo = Foo(1);
|
||||||
foo.get::<&Foo>();
|
foo.get::<&Foo>();
|
||||||
//[feature]~^ ERROR mismatched types
|
//[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
|
warn_non_default_branch = true
|
||||||
contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
|
contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
|
||||||
users_on_vacation = [
|
users_on_vacation = [
|
||||||
"BoxyUwU",
|
|
||||||
"fmease",
|
"fmease",
|
||||||
"jyn514",
|
"jyn514",
|
||||||
"oli-obk",
|
"oli-obk",
|
||||||
|
Loading…
Reference in New Issue
Block a user